IOC和DI是什么?
IOC是反转控制,DI是依赖注入。反转控制,就是把控制权由程序员交给SPRING程序。依赖注入的意思是在程序云庆期间,由外部容器动态的将依赖对象注入到组件中。一般通过构造器注入,或者SETTER注入。
SPRING 初始化过程
Resource定位
我们一般使用外部资源来描述Bean对象,所以IOC容器第一步就是需要定位Resource外部资源。Resource的定位其实就是BeanDefinition的资源定位,它是由ResourceLoader通过统一的Resource接口来完成的,这个Resource对各种形式的BeanDefinition的使用都提供了统一接口。
载入
第二个过程就是BeanDefinition的载入,BeanDefinitionReader读取,解析Resource定位的资源,也就是将用户定义好的Bean表示成IOC容器的内部数据结构也就是BeanDefinition,在IOC容器内部维护着一个BeanDefinition Map的数据结构,通过这样的数据结构,IOC容器能够对Bean进行更好的管理。
在配置文件中每一个都对应着一个BeanDefinition对象。
注册
第三个过程则是注册,即向IOC容器注册这些BeanDefinition,这个过程是通过BeanDefinitionRegistery接口来实现的。
在IOC容器内部其实是将第二个过程解析得到的BeanDefinition注入到一个HashMap容器中,IOC容器就是通过这个HashMap来维护这些BeanDefinition的。
上面提到的过程一般是不包括Bean的依赖注入的实现,Bean的载入和依赖注入是两个独立的过程,依赖注入是发生在应用第一次调用getBean向容器所要Bean时。
当然我们可以通过设置预处理,即对某个Bean设置lazyinit属性,那么这个Bean的依赖注入就会在容器初始化的时候完成。
经过这 (Resource定位,载入,注册)三个步骤,IOC容器的初始化过程就已经完成了。
BeanFactory 和 FactoryBean的区别
BeanFactory是个Factory,也就是IOC容器或对象工厂,在Spring中,所有的Bean都是由BeanFactory(也就是IOC容器)来进行管理的,提供了实例化对象和拿对象的功能。
FactoryBean是个Bean,这个Bean不是简单的Bean,而是一个能生产或者修饰对象生成的工厂Bean,它的实现与设计模式中的工厂模式和修饰器模式类似。
BeanFactory和ApplicationContext的区别?
BeanFactory:在启动的时候不会去实例化Bean,中有从容器中拿Bean的时候才会去实例化;
ApplicationContext:在启动的时候就把所有的Bean全部实例化了。它还可以为Bean配置lazy-init=true来让Bean延迟实例化;
ApplicationContext 生命周期
1.实例化
2.根据上下文对实例化的BEAN配置
3.CHECK BEAN NAME AWARE接口
4.CHECK BEAN FACTORY AWARE接口
5.CHECK ApplicationContextAware 接口
6.BeanPostProcessor 接口 postProcessBeforeInitialization()
- init method
8.postProcessAfterInitialization()
销毁时
当Bean不再需要时,会经过清理阶段,如果Bean实现了DisposableBean接口,会调用其实现的destroy方法
最后,如果这个Bean的Spring配置中配置了destroy-method属性,会自动调用其配置的销毁方法
Spring Bean 的生命周期
1.bean 建立
2.setter 注入
3.BeanNameAware
4.BeanFactoryAware
5.processBeforeInitialization()
6.afterPropertiesSet()
7.init-method
8.processAfterInitialization
9.DisposableBean 的 destroy
10.destroy-method
AOP 有哪些注释
@Aspect指定一个类为切面类;
@Pointcut(“execution(* cn.itcast.e_aop_anno..(..))”) 指定切入点表达式;
@Before(“pointCut_()”)前置通知: 目标方法之前执行;
@After(“pointCut_()”)后置通知:目标方法之后执行(始终执行);
@AfterReturning(“pointCut_()”)返回后通知: 执行方法结束前执行(异常不执行);
@AfterThrowing(“pointCut_()”)异常通知: 出现异常时候执行;
@Around(“pointCut_()”)环绕通知:环绕目标方法执行;
AOP的实现原理
Spring AOP使用的动态代理,所谓的动态代理就是说AOP框架不会去修改字节码,而是在内存中临时为方法生成一个AOP对象,这个AOP对象包含了目标对象的全部方法,并且在特定的切点做了增强处理,并回调原对象的方法。
Spring AOP中的动态代理主要有两种方式,JDK动态代理和CGLIB动态代理。JDK动态代理通过反射来接收被代理的类,并且要求被代理的类必须实现一个接口。JDK动态代理的核心是InvocationHandler接口和Proxy类。
如果目标类没有实现接口,那么Spring AOP会选择使用CGLIB来动态代理目标类。CGLIB(Code Generation Library),是一个代码生成的类库,可以在运行时动态的生成某个类的子类,注意,CGLIB是通过继承的方式做的动态代理,因此如果某个类被标记为final,那么它是无法使用CGLIB做动态代理的。
Spring 是如何管理事务的,事务管理机制
声明式事务管理使用了AOP面向切面编程实现的,本质就是在目标方法执行前后进行拦截。在目标方法执行前加入或创建一个事务,在执行方法执行后,根据实际情况选择提交或是回滚事务。
事务的隔离级别
脏读(看到未提交的数据)
不可重复读(2次读的结果不一致)
幻影读(2次读的结果不可能不一致,但是可能有新增的数据)
read_uncommited 脏读,不可重复读,幻读都会发生
read_commited 可能发生不可重读,幻读
repeatable_read 幻读
serializable 全不会发生
默认情况下只有未检查异常(RuntimeException和Error类型的异常)会导致事务回滚. 而受检查异常不会.
事务的回滚规则可以通过@Transactional 注解的 rollbackFor 和 noRollbackFor 属性来定义,这两个属性被声明为 Class[] 类型的, 因此可以为这两个属性指定多个异常类。
rollbackFor: 遇到时必须进行回滚
noRollbackFor: 一组异常类,遇到时必须不回滚
事务传播行为
PROPAGATION_REQUIRED
外方法有事务,就继续用。没有就新开一个
PROPAGATION_REQUIRED_NEW
外方法有没有事务都新开一个
PROPAGATION_SUPPORTS
外方法有就用,没有就不用
PROPAGATION_MANDATORY
外方法必须有,不如抛异常
PROPAGATION_NOT_SUPPORTED
无论外方法有没有,我都没有
PROPAGATION_NEVER
外方法有,我就抛异常
PROPAGATION_NESTED
外方法有,就嵌套一个新的事务,没有开一个新的。
Spring 中用到了那些设计模式
工厂模式:beanFactory
代理模式:AOP
模板方法:REST TEMPLATE
观察者: SPRING时间驱动模型,ApplicationListener
适配器:AOP
Spring MVC 工作原理
1.请求会发给DispatchServlet
2.DispatchServlet 接收到请求后,会去问HandlerMapping找对应的Handler
3.HandlerMapping把Handler 发给DispatchServlet
4、DispatchServlet 把 handler 发给handler Adapter
5.Adapter 去调用HANDLER的方法
6.Handler 返回一个MODEL AND VIEW 给ADAPTER
7.ADAPTER把MODEL AND VIEW发给DispatchServlet
8。DispatchServlet 发给ViewResolver 解析得到VIEW
9.返回给用户。
Spring 如何解决循环依赖
一、构造器循环依赖:表示通过构造器注入构成的循环依赖,此依赖是无法解决的,只能抛出BeanCurrentlyInCreationException异常表示循环依赖。
如在创建CircleA类时,构造器需要CircleB类,那将去创建CircleB,在创建CircleB类时又发现需要CircleC类,则又去创建CircleC,最终在创建CircleC时发现又需要CircleA;从而形成一个环,没办法创建。
Spring容器将每一个正在创建的Bean 标识符放在一个“当前创建Bean池”中,Bean标识符在创建过程中将一直保持在这个池中,因此如果在创建Bean过程中发现自己已经在“当前创建Bean池”里时将抛出BeanCurrentlyInCreationException异常表示循环依赖;而对于创建完毕的Bean将从“当前创建Bean池”中清除掉
二、setter循环依赖:表示通过setter注入方式构成的循环依赖。
对于setter注入造成的依赖是通过Spring容器提前暴露刚完成构造器注入但未完成其他步骤(如setter注入)的Bean来完成的,而且只能解决单例作用域的Bean循环依赖。
1、Spring容器创建单例“circleA” Bean,首先根据无参构造器创建Bean,并暴露一个“ObjectFactory ”用于返回一个提前暴露一个创建中的Bean,并将“circleA” 标识符放到“当前创建Bean池”;然后进行setter注入“circleB”;
2、Spring容器创建单例“circleB” Bean,首先根据无参构造器创建Bean,并暴露一个“ObjectFactory”用于返回一个提前暴露一个创建中的Bean,并将“circleB” 标识符放到“当前创建Bean池”,然后进行setter注入“circleC”;
3、Spring容器创建单例“circleC” Bean,首先根据无参构造器创建Bean,并暴露一个“ObjectFactory ”用于返回一个提前暴露一个创建中的Bean,并将“circleC” 标识符放到“当前创建Bean池”,然后进行setter注入“circleA”;进行注入“circleA”时由于提前暴露了“ObjectFactory”工厂从而使用它返回提前暴露一个创建中的Bean;
4、最后在依赖注入“circleB”和“circleA”,完成setter注入。