- Spring
- BeanFactory的作用
- BeanDefinition是什么
- BeanFactory和ApplicationContext区别
- BeanFactory和FactoryBean区别
- IOC容器的加载过程
- spring 提供了哪些配置方式
- Spring 中的 bean 的作用域有哪些?
- 什么是IOC
- DI
- 单例Bean的优势
- SpringBean是线程安全的吗
- Spring如何处理线程并发问题
- 什么是Bean的装配(注入),什么是Bean的自动装配(注入)
- 自动注入有什么限制吗
- Bean有哪声明周期的回调方法?实现方式?
- Spring 中的 bean 生命周期?
- Spring是如何解决Bean的循环依赖的。
- Spring是如何帮助我们在并发的时候获取不完整的Bean.
- @Compont @Controller @Respostitory @Service区别
- @Import可以有几种用法
- 如何让自动注入没有找到依赖的Bean不报错
- @Autowrited和@Resource区别
- AOP
- Spring事物
- Spring中使用了哪些设计模式
- SpringMVC
- SpringCloud
Spring
BeanFactory的作用
- BeFactory是Spring中一个非常核心的顶层接口。
- 他是Bean的工厂,主要职责就是生产bean.
- 实现了简单的工厂设计模式,通过getBean传入标识生产一个Bean.
他有非常多的实现类,每个工厂都有不同的职责(单一职责)功能。最强大的工厂是DefaultListableBeanFactory,Spring底层就是使用这个工厂生产bean的。
BeanDefinition是什么
主要负责存储bean的定义信息,决定bean的生产方式。
- 后续beanFactory根据这些信息就能生产bean
- 比如实例化需要beanDefinition 中的 class信息,从而反射实例化对象。
- 比如lazy 则不会在ioc容器加载时创建bean.
配置bean:
<bean class="com.bczhaoa.User" id="user" scope="singleton" lazy="false" autowire="none" ><property name="username" value="狗蛋"/></bean>
beanDefinition就是存储这些配置信息的。
BeanFactory和ApplicationContext区别
- ApplicationContext实现了BeanFactory。
- BeanFactory功能单一,就是作为Bean的工厂生产Bean.
- ApplicationContext不生产Bean,而是通知FactoryBean来生成Bean.
- BeanFactory在启动的时候不会取实例化Bean,当Spring应用中有从容器拿Bean时才做实例化,即懒加载。
APplicationContext在启动时就把所有Bean都生产了,也可以通过配置bean来实现懒加载。
BeanFactory和FactoryBean区别
BeanFactory是一个工厂,也就是一个容器。用来管理和生产Bean的。
- FactoryBean是一个Bean,所以他也是由BeanFactory来管理的。
- FactoryBean不是一个普通的Bean,他会表现出工厂模式的样子,是一个能生产对象的工厂Bean.
- 里面的getObject方法就是用来获取FactoryBean产生的对象。
- 如果需要获取工厂bean本身对象,getBean需要加 &前缀。
IOC容器的加载过程
- 从概念态到定义态
- 实例化一个ApplicationContext对象
- 调用bean工厂的后置处理器完成扫描。
- 循环解析出扫描出的信息,xml或注解解析。
- 实例化BeanDefinition,一个bean对应一个BeanDefinition.
- 所有类扫描完成后第一步即 将所有定义信息封装成了一个BeanDefinitionMap
- 从定义态到纯净态
- 实例化之前的验证,判断一个bean的prototype. 是否lazy, 是否abstract等。
- 只有一个bean是单例,非延迟加载,非抽象类。才会做实例化。
- 实例化的时候跟通过推断构造方法来实例化的。
- 实例化完成就是通过反射实例化了一个对象,并没有依赖注入。所以并不是一个完成的bean.
- 从纯净态到完成态
基于 xml 配置:bean 所需的依赖项和服务在 XML 格式的配置文件中指定。这些配置文件通常包含许多 bean 定义和特定于应用程序的配置选项。它们通常以 bean 标签开头。例如:
<bean id="studentbean" class="org.edureka.firstSpring.StudentBean"><property name="name" value="Edureka"></property></bean>
基于注解配置:通过在相关的类,方法或字段声明上使用注解,将 bean 配置为组件类本身,而不是使用 XML 来描述 bean 装配。默认情况下,Spring 容器中未打开注解装配。
<beans><context:annotation-config/><!-- bean definitions go here --></beans>
基于 Java API 配置: Spring 的 Java 配置是通过使用 @Bean 和 @Configuration 来实现。
@Configurationpublic class StudentConfig {@Beanpublic StudentBean myStudent() {return new StudentBean();}}
静态工厂配置 factory-method。 需要保证指定的方法时静态的。
- 实例工厂配置 factory-bean 加 factory-method ,实际上就是@Bean注解。
- factory-bean的方式。 一个bean实现implement FactoryBean
, 通过getObjet来返回指定的bean. Spring 中的 bean 的作用域有哪些?
- singleton : 唯一 bean 实例,Spring 中的 bean 默认都是单例的。
- prototype : 每次请求都会创建一个新的 bean 实例。
- request : 每一次HTTP请求都会产生一个新的bean,该bean仅在当前HTTP request内有效。
session : :在一个HTTP Session中,一个Bean定义对应一个实例。该作用域仅在基于web的Spring
什么是IOC
在没有spring之前
- Controller依赖Service,Service依赖Dao.
- 如果Service又依赖了其他实例,Controller实例化Service的方法也需要跟着变动。

- 在使用了工厂模式之后
- Controller不再实例化Service, Service的变动不再影响Controller对他的实例化,而是将所有Service的实例化交给了 工厂类,Controller从工厂类获取Service对象。

使用Spring之后
Inversion of control, 缩写IOC,控制反转的意思。
把对象的创建,对象之间依赖注入的过程,都交给spring管理。
Spring怎么管理的
xml配置方式
- xml文件配置
- spring启动时,扫描出xml配置的bean信息。反射创建对象。注入其他依赖的对象。
- xml文件配置
- 注解方式
- 需要交给spring管理的对象添加注解。
- 开启扫描指定包。
- spring启动时,扫描对应包的class文件。通过反射,根据注解找到需要管理的类。
- 默认都走无参构造。
ApplicationContext类图关系

DI
- Dependency Injection, 即依赖注入的意思。
- 程序员只需要将bean交给spring管理。不用再关心这些bean之间的依赖关系。添加 @Autowired 注解即可。
也就是说,一个bean对其他bean的依赖由spring进行注入。
单例Bean的优势
减少了生词实例的性能消耗
- 反射和aop都会增加性能消耗。
- 重复生成bean,会重复分配内存。
- 减少jvm垃圾回收次数。
可以快速获取bean,单例bean除了第一次生成其余都是在内存中获取,所以很快。
SpringBean是线程安全的吗
单例bean的情况
- 如果在类里面声明了成员变量,并且有读写操作(有状态),这个时候就会出现线程不安全。
- 如果单例bean没有成员变量,所有共享读写数据都是在方法入参上声明(无状态),此时没有线程安全问题 。
-
Spring如何处理线程并发问题
设置为多实例 @Scope(“prototype”).
- 将成员变量放在ThreadLocal中,通过get set方法修改,获取。
- 通过同步锁的发方式解决。会影响服务器吞吐量。
-
什么是Bean的装配(注入),什么是Bean的自动装配(注入)
手动依赖注入。
-
自动注入有什么限制吗
一定要声明set方法。
- 重写, 可以通过
和 property可以覆盖。 - 基本数据类型不能自动注入。手动可以注入,如果使用@Value.
自动注入有可能匹配到多个。使用 @Autowried. 先根据类型,再根据名字。
Bean有哪声明周期的回调方法?实现方式?
初始化
- @PostConstruct
- InitializingBean 重写 afterPropertiesSet方法
- 通过 initMethod,必须使用@Bean(InitMethod=””)或者使用xml。使用component不行。
销毁
实例化
- 通过反射推断构造函数进行实例化。
- 实例工厂、静态工厂实例化
- 属性赋值
- 解析自动注入,DI的体现。
- 方式 @Autowarie 配置方式的 byname/bytype/constract/non等。
- 初始化
- 调用多个 Aware回调
- BeanNameAware-获取容器中的Bean名称
- BeanFactoryAware-获取当前BeanFactory。
- ApplicationContextAware 获取容器
- MessSoureAware 获取Message文本信息。
- ApplicationEventPublisherAware 发布时间
- ResourceLoadAware 获取资源文件。
- 调用初始化声明周期回调,上个题。
- 如果Bean实现了Aop,会创建动态代理。
- 调用多个 Aware回调
- 销毁
- 一级缓存:存储完整的Bean.
- 二级缓存:把三级缓存创建完成的放进去的B,或者AOP代理对象放入二级缓存。
- 三级缓存:
- 缓存的是函数接口:通过lambda把方法(Bean的实例和Bean的名字传递进去)。
- 不会立即调用三级缓存。如果立即调用,不管bean是否循环依赖,都会在实例化后直接创建proxy,而正常的bean是在初始化的时候创建动态代理的。
- ABA,A的第二次getBeanA 会调用三级缓存。
- 如果A使用了AOP,创建动态代理对象。
- 如果没有使用AOP,存储的就是放进去的A实例。
- 然后保存在二级缓存中。避免重复创建。 如果不放 A被多个bean循环依赖。 二级缓存中就会有多个A被实例化。
二级缓存能不能解决循环依赖
- 如果只是死循环的问题,一级缓存就可以解决: 无法避免在并发情况下获取到不完整的bean的问题。
二级缓存必然也可以:但是如果A比多个对象循环依赖,A会被多次创建动态代理。
多例bean能不能解决循环依赖。
不能,因为多例bean就没有使用缓存,1.2.3都没有用。
- 多例bean每次使用都需要重新创建,所有不适用缓存。不适用缓存保存早期对象。就无法解决循环依赖。
- 解决循环依赖的关键是有个缓存作为出口来换取该依赖对象。没有缓存就没有出口。
Spring有没有解决构造函数的循环依赖
- 默认没有解决,可以人工解决。
- 可以通过延迟加载来解决@Lazy.
Lazy的原理: 不会立即调用实例化方法,只有在使用的时候才会生成对象。
-
@Compont @Controller @Respostitory @Service区别
实际上其他几个都是Compont的原注解。
只是为了可读性更好。
@Import可以有几种用法
- 直接指定类
- 如果是配置类按照配置类正常解析。
- 如果是个普通类就会解析成Ban.
- 通过ImportSelector可以一次性注册多个,返归一个String[] 数组,每个值就是一个完整的类路径。
- 通过DeferredImportSelector可以一次性注册多个,返回一个String[],每一个值就是类的完整路径。
通过ImportBeanDefintionRegistrar可以一次性注册多个,通过BeanDefinitionRegistry可以动态注册BeanDefintion。
如何让自动注入没有找到依赖的Bean不报错
@Autowrited和@Resource区别
Autowrited是Spring的注解,Resource是Jdk注解。
- Autowrite先根据类型找bean,再根据名称找bean。
Resource先根据名称找bean,再根据类型找bean.
AOP
什么是AOP,能做什么
面向切面编程,将与业务无关的,却对多个对象产生影响的公共行为和逻辑,抽取并封装成一个可重用模块。
- 抽取并封装的模块被称为切面。
- 减少系统中的重复代码,降低模块之间的耦合度。
- 同时提高系统的可维护性。
-
AOP常见的概念名词
切面 Aspect 指的就是就是切面类,类中管理 切点和通知。
- 连接点(Join Point)指的就是被增强的业务方法
- 通知(Advice): 就是需要增加到业务代码中的公共代码,通知有很多类型
- 前置通知
- 异常通知
- 后置通知
- 环绕通知
- 切入点(Ponitcut):有他决定哪些方法需要增强,哪些不需要增强,集合切点表达式。
- 目标对象 TargetObject: 指的就是被增强的对象。
-
AOP中有哪些通知
前置通知 Before : 在目标方法执行之前调用的通知功能。
- 后置通知 After: 在目标方法执行完成之后调用的的通知。相当于finally
- 返回通知 After-returning : 在目标方法执行之后调用的通知。
- 异常通知 after-throwing: 在目标方法抛出异常之后调用的通知。
- 环绕通知 Around: 通知包裹了被通知的方法,之前和之后自定义执行。
- 执行顺序
- 当在Spring中使用@Aspect,@Before 等这些注解的时候就需要添加AspectJ依赖。
- SpringAop提供的AspectJ的支持,但是只用到了AspectJ的切点解析和匹配。
- SpringAop基于动态代理来实现,默认的如果使用接口,用JDK提供的动态代理实现。如果么有接口,使用CGLib实现。
Aspectj是静态代理的增强,就是在编译时会生成AOP代理类。
JDK动态代理实现
接口类 ```java package proxy;
public interface Star { String sing(String name);
String dance(String name);
}
2. 被代理类实现接口
```java
package proxy;
public class LiuDeHua implements Star
{
@Override
public String sing(String name)
{
System.out.println("给我一杯忘情水");
return "唱完" ;
}
@Override
public String dance(String name)
{
System.out.println("开心的马骝");
return "跳完" ;
}
}
- 实现InvocationHander接口的包装了,这个仅仅是个wapper,不是代理类。 ```java package proxy;
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy;
public class StarProxy implements InvocationHandler { // 目标类,也就是被代理对象 private Object target;
public void setTarget(Object target)
{
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
{
// 这里可以做增强
System.out.println("收钱");
Object result = method.invoke(target, args);
return result;
}
// 生成代理类
public Object CreatProxyedObj()
{
return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
}
}
<a name="vteaf"></a>
### cglib动态代理实现
```java
package proxy;
import java.lang.reflect.Method;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
public class CglibProxy implements MethodInterceptor
{
// 根据一个类型产生代理类,此方法不要求一定放在MethodInterceptor中
public Object CreatProxyedObj(Class<?> clazz)
{
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(clazz);
enhancer.setCallback(this);
return enhancer.create();
}
@Override
public Object intercept(Object arg0, Method arg1, Object[] arg2, MethodProxy arg3) throws Throwable
{
// 这里增强
System.out.println("收钱");
return arg3.invokeSuper(arg0, arg2);
}
}
第一个参数传递的是this,代表代理类本身,第二个参数标示拦截的方法,第三个参数是入参,第四个参数是cglib方法,intercept方法完成增强后,我们调用cglib方法间接调用父类方法完成整个方法链的调用。
JDK动态代理和CGLib动态代理的区别
- JDK动态代理只提供接口的代理,不支持类的代理。
- JDK会在运行时生成一个动态代理代,$proxy*.class.
- 该类是实现了目标类的一个接口,并且会实现接口所有方法的增强代码。
- 调用时先去调用处理类进行增强,再通过反射的方式进行调用目标方法。
- 代理类如果没有实现接口,那么SpringAOP会选择使用CGLIB来动态代理目标类。
- 主要实现时继承后重写父类方法。
- 调用时先通过代理类增强,再直接调用父类方法。
- CGLIB是通过继承的方式做的动态代理。因此一个类如果被标记为final,那么是无法使用CGLIB做动态代理的。
- 创建对象速度:jdk创建对象的速度远大于cglib,这是由于cglib创建对象时需要操作字节码
- 方法调用速度:Jdk是反射调用,调用比cglib直接调用父类慢。
内存消耗:另外由于CGLIB的大部分类是直接对Java字节码进行操作,这样生成的类会在Java的永久堆中。如果动态代理操作过多,容易造成永久堆满,触发OutOfMemory异常。
JavaConfig的方式如何开启AOP,如何强制使用cglib。
配置类需要开启配置 EnableAspectJAutoProxy.
- 如果需要强制使用cglib,需要配置 proxyTargetClass=true.
在线程中暴露代理对象 , exposeProxy=true.
AOP失效原因,怎么解决。
方法不是private. 解决 改为public
- 目标类没有配置为springBean. 解决:配置为SpringBean.
- 切点表达式没有配置正确。
在本类内部调用不会走代理。
编程式事物,通过编程的方式管理事物,灵活性高,难维护。
-
Spring事物实现的方式有哪些
声明式
- 编程式: 直接使用 TransactionTemplate 的 execute
- PlatformTransactionManager :Spring并不直接管理事务,
通过这个接口,Spring为各个平台如JDBC、Hibernate等都提供了对应的事务管理器,也就是将事务管理的职责委托给Hibernate或者JTA等持久化机制所提供的相关平台框架的事务来实现
b. TransactionStatus :在上面 PlatformTransactionManager 接口中,有如下方法:
这个方法返回的是 TransactionStatus对象,然后程序根据返回的对象来获取事务状态,然后进行相应的操作。
而 TransactionStatus 这个接口的内容如下:

c. TransactionDefinition 事务定义
d. 一般使用直接 使用 TransactionTemplate.excute执行。
package com.thit.serviceImpl;
import java.util.Date;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallback;
import org.springframework.transaction.support.TransactionTemplate;
import com.thit.dao.OrderDao;
import com.thit.dao.ProductDao;
import com.thit.entity.Order;
import com.thit.entity.Product;
import com.thit.service.OrderService;
@Service(value="orderServiceimpl2")
public class OrderServiceImpl2 implements OrderService {
@Autowired
private OrderDao orderDao;
@Autowired
private ProductDao productDao;
@Autowired
private TransactionTemplate template;
public void addOrder(final Order order) {
// TODO Auto-generated method stub
//订单表
System.out.println("进入");
order.setCreateTime(new Date());
order.setStatus("待付款测试2");
template.execute(new TransactionCallback<Object>() {
public Object doInTransaction(TransactionStatus status) {
// TODO Auto-generated method stub
//开启事务
try {
orderDao.insert(order);
//商品
Product p=productDao.select(order.getProductsId());
p.setStock(p.getStock()-order.getNumber());
productDao.update(p);
} catch (Exception e) {
// TODO: handle exception
//回滚
status.setRollbackOnly();
e.printStackTrace();
}
return null;
}
});
}
}
Spring事物的传播行为
事物的传播行为指的是当开启当前事物时,如果外部有事物,如何处理。
常用的三种:
- Required 默认的,外部不存在事物,开启新事物。存在融入到外部事物中。默认的。适用场景为增删改操作。
- Support 外部不存在事物,不开启新事物,外部存在,融入到外部。适用查询操作。
Require_new, 外部不存在事物,开启新事物,外部存在,不使用外部事物。 适用内部与外部事物 业务没有管理的场景。
事物的隔离级别
Isolation.DEFAULT:为数据源的默认隔离级别
- isolation=Isolation.READ_UNCOMMITTED:读未提交 不能防止脏、不可、幻读
- iIsolation.READ_COMMITTED:授权读取级别 可以防止脏读、不能防止不可、幻读
- iIsolation.REPEATABLE_READ:可重复读取级别, 可以防止脏读、不可重复读,不能防止幻读。
- iIsolation.SERIALIZABLE:序列化级别 可以防止脏、不可、幻读。
Spring中事物失效原因
- 同AOP失效原因。
- private
- 没有配置为bean
-
Spring中使用了哪些设计模式
简单工程 BeanFactory.
- 工厂方法 FactoryBean.
- 单例模式 Bean实例
- 适配器模式 SpringMVC中的HandlerAdatper.
- 装饰器模式 BeanWapper.
- 代理模式 AOP底层
- 观察者模式,Spring时间监听。
- 策略模式 excudeFilters、includeFilters.
- 模板方法模式
- 责任链模式 -AOP中的方法调用
SpringMVC
常用注解
@Configuration
- 声明这是一个spring配置类,spring的注解。不是boot的。
- 配置类里面使用@Bean注解标注在方法上,给容器注册组件。默认单实例
- 配置类本身也是组件。
- 参数 proxyBeanMethods : 代理@Bean方法
- 默认是true,默认就是全量模式,表示@Bean所标注的bean,每次创建先去容器看有没有,没有才创建。
- false,轻量模式,调用方法直接new. 不走代理,也不去容器看有没有。
- 选择: 配置组件之间无依赖,建议使用lite轻量模式,加速容器启动过程,减少判断。如果配置组件之间有依赖关系,即必须是单例的场景下,使用Full模式。
@Import
导入某个类,即创建某个类的实例,spring的注解,不是boot的@Conditional
条件判断,在某些场景下,开启配置。或者不开启。@ImportResource
原生配置文件导入。@ConfigurationProperties + @EnableConfigurationProperties
属性值绑定并加载到容器@ConfigurationProperties + @Component
同上拦截器、过滤器区别
过滤器
什么是过滤器
- 过滤器的英文名称为 Filter, 是 Servlet 技术中最实用的技术。
- 如同它的名字一样,过滤器是处于客户端和服务器资源文件之间的一道过滤网,帮助我们过滤掉一些不符合要求的请求,通常用作 Session 校验,判断用户权限,如果不符合设定条件,则会被拦截到特殊的地址或者基于特殊的响应。
过滤器的使用
首先需要实现 Filter接口然后重写它的三个方法
init 方法:在容器中创建当前过滤器的时候自动调用
destory 方法:在容器中销毁当前过滤器的时候自动调用
doFilter 方法:过滤的具体操作
代码示例
import lombok.extern.log4j.Log4j2;
import org.springframework.stereotype.Component;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
import java.io.IOException;
@Log4j2
public class MyFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
log.info("初始化过滤器");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest)servletRequest;
HttpServletResponseWrapper wrapper = new HttpServletResponseWrapper((HttpServletResponse) response);
String requestUri = request.getRequestURI();
log.info("请求地址是:"+requestUri);
if (requestUri.contains("/addSession")
|| requestUri.contains("/removeSession")
|| requestUri.contains("/online")
|| requestUri.contains("/favicon.ico")) {
filterChain.doFilter(servletRequest, response);
} else {
wrapper.sendRedirect("/online");
}
}
@Override
public void destroy() {
//在服务关闭时销毁
log.info("销毁过滤器");
}
}
拦截器
什么是拦截器
- Java中的拦截器是动态拦截 action 调用的对象,然后提供了可以在 action 执行前后增加一些操作,也可以在 action 执行前停止操作,功能与过滤器类似,但是标准和实现方式不同。
- 登录认证:在一些应用中,可能会通过拦截器来验证用户的登录状态,如果没有登录或者登录失败,就会给用户一个友好的提示或者返回登录页面,当然大型项目中都不采用这种方式,都是调单点登录系统接口来验证用户。
- 记录系统日志:我们在常见应用中,通常要记录用户的请求信息,比如请求
ip,方法执行时间等,通过这些记录可以监控系统的状况,以便于对系统进行信息监控、信息统计、计算 PV、性能调优等。
- 通用处理:在应用程序中可能存在所有方法都要返回的信息,这是可以利用拦截器来实现,省去每个方法冗余重复的代码实现。
拦截器的使用
我们需要实现 HandlerInterceptor 类,并且重写三个方法:
preHandle:在 Controller 处理请求之前被调用,返回值是 boolean类型,如果是true就进行下一步操作;若返回false,则证明不符合拦截条件,在失败的时候不会包含任何响应,此时需要调用对应的response返回对应响应。
postHandler:在 Controller 处理请求执行完成后、生成视图前执行,可以通过ModelAndView对视图进行处理,当然ModelAndView也可以设置为 null。
afterCompletion:在 DispatcherServlet 完全处理请求后被调用,通常用于记录消耗时间,也可以对一些资源进行处理。
代码示例
@Component
public class MyInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
log.info("【MyInterceptor】调用了:{}", request.getRequestURI());
request.setAttribute("requestTime", System.currentTimeMillis());
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response,
Object handler, ModelAndView modelAndView) throws Exception {
if (!request.getRequestURI().contains("/online")) {
HttpSession session = request.getSession();
String sessionName = (String) session.getAttribute("name");
if ("cj".equals(sessionName)) {
log.info("【MyInterceptor】当前浏览器存在 session:{}",sessionName);
}
}
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response,
Object handler, Exception ex) throws Exception {
long duration = (System.currentTimeMillis() - (Long)request.getAttribute("requestTime"));
log.info("【MyInterceptor】[{}]调用耗时:{}ms",request.getRequestURI(), duration);
}
}
拦截区过滤器区别
1、拦截器是基于java的反射机制的 - - - - - 过滤器是基于函数回调
2、拦截器不依赖与servlet容器 - - - - - 过滤器依赖与servlet容器,
3、拦截器只能对action请求起作用 - - - - - 过滤器则可以对几乎所有的请求起作用
4、拦截器可以访问action上下文、值栈里的对象 - - - - - 过滤器不能
5、在action的生命周期中,拦截器可以多次被调用 - - - - - 过滤器只能在容器初始化时被调用一次
SpirngBoot的理解,有哪些优点
Spring是用来快速开发spring应用程序的脚手架。目的是简化spring配置和开发过程。
- 提供了很多内置starter结合自动配置。对主流框架无配置继承,开箱即用。
- 简化了开发,可以做到0xml配置。
- 内置web容器。
- 管理了三方依赖版本。减少冲突。
自带监控功能,可监控运行情况,内存,线层池,http等装填。
SPirng 和SpringBoot的关系区别。
SpringFramework是一个容器框架
SpringBoot不是框架,他是一个可以快速构建spring的脚手架。
SpringBoot核心注解。
SpringBootApplication 标记当前应用为SpringBoot项目。
SpringBootApplication 实际上是三个注解的组合注解: 包括 ComponentScan 、SpringBootConfigration、EnableAutoConfigration.
- 其中 第一个注解SpringBootConfigration 使用了注解@Configration 。表明了当前类是个配置类。
- 第二个注解 ComponentScan 表示开启扫描。
- 第三个注解 EnableAutoConfigRation. 这个注解包含了两个注解
自定义starter中 META-INF文件夹下创建文件 spring-factories。并指定配置类。
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\配置类全类名-
SpringBoot配置文件加载顺序。
通过ConfigFileApplicationListener读取。
优先级高到第。
- file: ./config 当前jar包的config文件夹。
- file下的文件 同config同级文件。
- calsspath:config
- classpath:
SpringCloud
Eureka
什么是Eureka
Eureka作为SpringCloud的服务注册功能服务器,他是服务注册中心,系统中的其他服务使用Eureka的客户端将其连接到Eureka Service中,并且保持心跳,这样工作人员可以通过EurekaService来监控各个微服务是否运行正常。Eureka怎么实现高可用
注册多台 Eureka ,然后把 SpringCloud 服务互相注册,客户端从 Eureka 获取信息时,按照Eureka 的顺序来访问。什么是Eureka的自我保护模式
默认情况下,如果 Eureka Service 在一定时间内没有接收到某个微服务的心跳, Eureka Service 会进入自我保护模式,在该模式下Eureka Service 会保护服务注册表中的信息,不在删除注册表中的数据,当网络故障恢复后,Eureka Servic 节点会自动退出自我保护模式DiscoveryClient的作用
可以从注册中心中根据服务别名获取注册的服务器信息。Eureka和ZooKeeper都可以提供服务注册与发现的功能,请说说两个的区别
ZooKeeper中的节点服务挂了就要选举 在选举期间注册服务瘫痪,虽然服务最终会恢复,但是选举期间不可用的, 选举就是改微服务做了集群,必须有一台主其他的都是从
- Eureka各个节点是平等关系,服务器挂了没关系,只要有一台Eureka就可以保证服务可用,数据都是最新的。 如果查询到的数据并不是最新的,就是因为Eureka的自我保护模式导致的
- Eureka本质上是一个工程,而ZooKeeper只是一个进程
- Eureka可以很好的应对因网络故障导致部分节点失去联系的情况,而不会像ZooKeeper 一样使得整个注册系统瘫痪
- ZooKeeper保证的是CP,Eureka保证的是AP
CloudGateWay
什么是网关?
网关相当于一个网络服务架构的入口,所有网络请求必须通过网关转发到具体的服务网关的作用是什么
统一管理微服务请求,权限控制、负载均衡、路由转发、监控、安全控制黑名单和白名单等网关与过滤器有什么区别
网关是对所有服务的请求进行分析过滤,过滤器是对单个服务而言。Ribbon
Ribbon是什么
Ribbon客户端组件提供一系列完善的配置项,如连接超时,重试等。简单的说,就是在配置文件中列出后面所有的机器,Ribbon会自动的帮助你基于某种规则(如简单轮询,随即连接等)去连接这些机器。我们也很容易使用Ribbon实现自定义的负载均衡算法。(有点类似Nginx)Ribbon底层实现原理
Ribbon 使用 discoveryClient 从注册中心读取目标服务信息,对同一接口请求进行计数,使用 % 取余算法获取目标服务集群索引,返回获取到的目标服务信息。
@LoadBalanced注解的作用
Hystrix
什么是断路器
当一个服务调用另一个服务由于网络原因或自身原因出现问题,调用者就会等待被调用者的响应 当更多的服务请求到这些资源导致更多的请求等待,发生连锁效应(雪崩效应)
断路器有三种状态
打开状态:一段时间内 达到一定的次数无法调用 并且多次监测没有恢复的迹象 断路器完全打开 那么下次请求就不会请求到该服务 半开状态:短时间内 有恢复迹象 断路器会将部分请求发给该服务,正常调用时 断路器关闭 关闭状态:当服务一直处于正常状态 能正常调用
什么是 Hystrix
雪崩效应是在大型互联网项目中,当某个服务发生宕机时,调用这个服务的其他服务也会发生宕机,大型项目的微服务之间的调用是互通的,这样就会将服务的不可用逐步扩大到各个其他服务中,从而使整个项目的服务宕机崩溃.发生雪崩效应的原因有以下几点
单个服务的代码存在bug. 2请求访问量激增导致服务发生崩溃(如大型商城的枪红包,秒杀功能). 3.服务器的硬件故障也会导致部分服务不可用.
服务雪崩效应产生的原因
因为Tomcat默认情况下只有一个线程池来维护客户端发送的所有的请求,这时候某一接口在某一时刻被大量访问就会占据tomcat线程池中的所有线程,其他请求处于等待状态,无法连接到服务接口。
谈谈服务降级、熔断、服务隔离
服务降级:当客户端请求服务器端的时候,防止客户端一直等待,不会处理业务逻辑代码,直接返回一个友好的提示给客户端。
服务熔断是在服务降级的基础上更直接的一种保护方式,当在一个统计时间范围内的请求失败数量达到设定值(requestVolumeThreshold)或当前的请求错误率达到设定的错误率阈值(errorThresholdPercentage)时开启断路,之后的请求直接走fallback方法,在设定时间(sleepWindowInMilliseconds)后尝试恢复。
服务隔离就是Hystrix为隔离的服务开启一个独立的线程池,这样在高并发的情况下不会影响其他服务。服务隔离有线程池和信号量两种实现方式,一般使用线程池方式。
服务降级底层是如何实现的
Hystrix实现服务降级的功能是通过重写HystrixCommand中的getFallback()方法,当Hystrix的run方法或construct执行发生错误时转而执行getFallback()方法。
Feign
什么是Feign
Feign 是一个声明web服务客户端,这使得编写web服务客户端更容易
他将我们需要调用的服务方法定义成抽象方法保存在本地就可以了,不需要自己构建Http请求了,直接调用接口就行了,不过要注意,调用方法要和本地抽象方法的签名完全一致。
SpringCloud有几种调用接口方式
Feign
- RestTemplate
Ribbon和Feign调用服务的区别
调用方式同:Ribbon需要我们自己构建Http请求,模拟Http请求然后通过RestTemplate发给其他服务,步骤相当繁琐
而Feign则是在Ribbon的基础上进行了一次改进,采用接口的形式,将我们需要调用的服务方法定义成抽象方法保存在本地就可以了,不需要自己构建Http请求了,直接调用接口就行了,不过要注意,调用方法要和本地抽象方法的签名完全一致。
Bus
什么是 Spring Cloud Bus?
Spring Cloud Bus就像一个分布式执行器,用于扩展的Spring Boot应用程序的配置文件,但也可以用作应用程序之间的通信通道。
Spring Cloud Bus 不能单独完成通信,需要配合MQ支持
Spring Cloud Bus一般是配合Spring Cloud Config做配置中心的
Springcloud config实时刷新也必须采用SpringCloud Bus消息总线
Config
什么是Spring Cloud Config?
Spring Cloud Config为分布式系统中的外部配置提供服务器和客户端支持,可以方便的对微服务各个环境下的配置进行集中式管理。Spring Cloud Config分为Config Server和Config Client两部分。Config Server负责读取配置文件,并且暴露Http API接口,Config Client通过调用Config Server的接口来读取配置文件。
[
](https://blog.csdn.net/weixin_43122090/article/details/105463548)
