IOC容器
IOC就是控制反转,是指创建对象的控制权的转移,以前创建对象的权利全是交由用户来控制的,现在这种权利交由Spring容器控制,容器会根据配置文件去创建各个实例之间的依赖关系,实现了对象与对象之间的松耦合。实现原理是通过Java的反射来动态生成对象,注入方式一共有三种,分别是构造器注入,setter注入。
容器启动及配置类加载流程
- 容器的启动
首先,调用BeanDefinitionReader加载配置文件,将内容映射到BeanDefinition中,解析配置文件,并将类型信息存储到BeanDefinition,交给BeanDefinitionRegistry管理,最后注册到BeanFactory。
 - Bean实例化

 
创建过程
- 实例化bean对象,以及设置bean属性;
 - 如果通过Aware接口声明了依赖关系,则会注入Bean对容器基础设施层面的依赖,Aware接口是为了感知到自身的一些属性。容器管理的Bean一般不需要知道容器的状态和直接使用容器。但是在某些情况下是需要在Bean中对IOC容器进行操作的。这时候需要在bean中设置对容器的感知。SpringIOC容器也提供了该功能,它是通过特定的Aware接口来完成的。 比如BeanNameAware接口,可以知道自己在容器中的名字。 如果这个Bean已经实现了BeanFactoryAware接口,可以用这个方式来获取其它Bean。 (如果Bean实现了BeanNameAware接口,调用setBeanName()方法,传入Bean的名字。 如果Bean实现了BeanClassLoaderAware接口,调用setBeanClassLoader()方法,传入ClassLoader对象的实例。 如果Bean实现了BeanFactoryAware接口,调用setBeanFactory()方法,传入BeanFactory对象的实例。)
 - 紧接着会调用BeanPostProcess的前置初始化方法postProcessBeforeInitialization,主要作用是在Spring完成实例化之后,初始化之前,对Spring容器实例化的Bean添加自定义的处理逻辑。有点类似于AOP。
 - 如果实现了BeanFactoryPostProcessor接口的afterPropertiesSet方法,做一些属性被设定后的自定义的事情。
 - 调用Bean自身定义的init方法,去做一些初始化相关的工作。
 - 调用BeanPostProcess的后置初始化方法,postProcessAfterInitialization去做一些bean初始化之后的自定义工作。
 - 完成以上创建之后就可以在应用里使用这个Bean了。
 
销毁过程
当Bean不再用到,便要销毁 。
自动装配的方式
当 bean 在 Spring 容器中组合在一起时,它被称为装配或 bean 装配。 Spring 容器需要知道需要什么 bean 以及容器应该如何使用依赖注入来将 bean 绑定在一起,同时装配 bean。
Spring 容器能够自动装配 bean。也就是说,可以通过检查 BeanFactory 的内容让 Spring 自动解析 bean 的协作者。
- no:不进行自动装配,手动设置Bean的依赖关系。
 - byName:根据Bean的名字进行自动装配。
 - byType:根据Bean的类型进行自动装配。
 - constructor:类似于byType,不过是应用于构造器的参数,如果正好有一个Bean与构造器的参数类型相同则可以自动装配,否则会导致错误。
 - autodetect:如果有默认的构造器,则通过constructor的方式进行自动装配,否则使用byType的方式进行自动装配。
 
缺点
- 覆盖的可能性 - 您始终可以使用 和 设置指定依赖项,这将覆盖自动装配。
 - 基本元数据类型 - 简单属性(如原数据类型,字符串和类)无法自动装配。
 - 令人困惑的性质 - 总是喜欢使用明确的装配,因为自动装配不太精确。
IOC和DI
IoC叫控制反转,是Inversion of Control的缩写,通俗的说就是我们不用自己创建实例对象,这些都交给Spring的bean工厂帮我们创建管理。这也是Spring的核心思想,通过面向接口编程的方式来是实现对业务组件的动态依赖。这就意味着IOC是Spring针对解决程序耦合而存在的。DI(Dependency Injection)叫依赖注入,是对IoC更简单的诠释。DI即组件之间的依赖关系由容器在运行期决定,形象的来说,即由容器动态的将某种依赖关系注入到组件之中。 
依赖注入可以通过setter方法注入(设值注入)、构造器注入和接口注入三种方式来实现,Spring支持setter注入和构造器注入,通常使用构造器注入来注入必须的依赖关系,对于可选的依赖关系,则setter注入是更好的选择,setter注入需要类提供无参构造器或者无参的静态工厂方法来创建对象。
构造器注入和Setter注入的区别
| 构造函数注入 | Setter注入 | 
|---|---|
| 没有部分注入 | 有部分注入 | 
| 不会覆盖 setter 属性 | 会覆盖 setter 属性 | 
| 任意修改都会创建一个新实例 | 任意修改不会创建一个新实例 | 
| 适用于设置很多属性 | 适用于设置少量属性 | 
BeanFactory和ApplicationContext的区别
- BeanFactory
BeanFactory是spring中比较原始,比较古老的Factory。因为比较古老,所以BeanFactory无法支持spring插件,例如:AOP、Web应用等功能。 - ApplicationContext
ApplicationContext是BeanFactory的子接口,因为古老的BeanFactory无法满足不断更新的spring的需求,于是ApplicationContext就基本上代替了BeanFactory的工作,以一种更面向框架的工作方式以及对上下文进行分层和实现继承,并在这个基础上对功能进行扩展:- MessageSource, 提供国际化的消息访问;
 - 资源访问(如URL和文件);
 - 事件传递;
 - Bean的自动装配;
 - 各种不同应用层的Context实现。
 
 
区别:
| BeanFactory | ApplicationContext | 
|---|---|
| 不支持AOP、WEB | 支持AOP、WEB | 
| 懒汉式加载Bean | 饿汉式加载单例 | 
| 使用语法显式提供资源对象 | 自己创建和管理资源对象 | 
| 不支持国际化 | 支持国际化 | 
| 不支持基于依赖的注解 | 支持基于依赖的注解 | 
BeanFactory的优缺点:
- 优点:应用启动的时候占用资源很少,对资源要求较高的应用,比较有优势;
 - 缺点:运行速度会相对来说慢一些。而且有可能会出现空指针异常的错误,而且通过Bean工厂创建的Bean生命周期会简单一些。
 
ApplicationContext的优缺点:
- 优点:所有的Bean在启动的时候都进行了加载,系统运行的速度快;在系统启动的时候,可以发现系统中的配置问题。
 - 缺点:把费时的操作放到系统启动中完成,所有的对象都可以预加载,缺点就是内存占用较大。
创建Bean的几种方式
 
- 使用xml配置(不利于对象管理) 
<bean id="xxxx" class="xxxx.xxxx"/>
 
- 使用注解@Component,@Service,@Controller,@Repository  
@Component:侧重于通用的Bean类;
@Service:标识该类用于业务逻辑;
@Controler:标识该类为Spring MVC的控制器类;
@Repository:标识该类是一个实体类,只有属性和Setter,Getter。它为 DAO 提供了额外的好处。它将 DAO 导入 IOC 容器,并使未经检查的异常有资格转换为 Spring DataAccessException。 - 使用@Bean注解
 - 使用@Import   
@Import(User.class)public class MicroblogUserWebApplication {public static void main(String args[]) {SpringApplication.run(MicroblogUserWebApplication.class, args);}}
 
手动注入 ```java @Component public class LocationRegister implements BeanFactoryAware {
@Override public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
DefaultListableBeanFactory listableBeanFactory = (DefaultListableBeanFactory)beanFactory;
//方式1 Location location = new Location(); listableBeanFactory.registerSingleton(Location.class.getName(),location);
//方式2 BeanDefinition locationBeanDefinition = new RootBeanDefinition(Location.class); listableBeanFactory.registerBeanDefinition(Location.class.getName(),locationBeanDefinition); } }
<a name="QjAXS"></a>#### Spring中的单例bean的线程安全问题当多个用户同时请求一个服务时,容器会给每一个请求分配一个线程,这时多个线程会并发执行该请求对应的业务逻辑(成员方法),此时就要注意了,如果该处理逻辑中有对单例状态的修改(体现为该单例的成员属性),则必须考虑线程同步问题。 **线程安全问题都是由全局变量及静态变量引起的。** 若每个线程中对全局变量、静态变量只有读操作,而无写操作,一般来说,这个全局变量是线程安全的;若有多个线程同时执行写操作,一般都需要考虑线程同步,否则就可能影响线程安全.<br />**无状态bean和有状态bean**- 有状态就是有数据存储功能。有状态对象(Stateful Bean),就是有实例变量的对象,可以保存数据,是非线程安全的。在不同方法调用间不保留任何状态。- 无状态就是一次操作,不能保存数据。无状态对象(Stateless Bean),就是没有实例变量的对象 .不能保存数据,是不变类,是线程安全的。在spring中无状态的Bean适合用不变模式,就是单例模式,这样可以共享实例提高性能。有状态的Bean在多线程环境下不安全,适合用[Proto](/jump/super-jump/word?word=Proto)type原型模式。 Spring使用ThreadLocal解决线程安全问题。如果你的Bean有多种状态的话(比如 View Model 对象),就需要自行保证线程安全 。<a name="77b59385"></a>#### 实例化Bean的源码分析以单例为例:<a name="56a51423"></a>##### DefaultSingletonBeanRegistry#getSingleton()```javapublic Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {Assert.notNull(beanName, "Bean name must not be null");synchronized (this.singletonObjects) {Object singletonObject = this.singletonObjects.get(beanName);if (singletonObject == null) {...try {// 从单例工厂获取实例对象singletonObject = singletonFactory.getObject();newSingleton = true;}catch (IllegalStateException ex) {...}...return singletonObject;}}
主要通过singletonFactory.getObject()方法来获取实例Bean,其中,getObject()主要调用了AbstractBeanFactory的doGetBean()方法。
AbstractBeanFactory#doGetBean()
if (mbd.isSingleton()) {sharedInstance = getSingleton(beanName, () -> {try {return createBean(beanName, mbd, args);}catch (BeansException ex) {destroySingleton(beanName);throw ex;}});...}
这段代码主要是调用了createBean()方法。
AbstractAutowireCapableBeanFactory#createBean
@Overrideprotected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)throws BeanCreationException {...// 根据设置的class属性或className来解析得到class引用Class<?> resolvedClass = resolveBeanClass(mbd, beanName);...try {// 处理InstantiationAwareBeanPostProcessorObject bean = resolveBeforeInstantiation(beanName, mbdToUse);if (bean != null) {return bean;}}catch (Throwable ex) {...}try {// 创建bean实例Object beanInstance = doCreateBean(beanName, mbdToUse, args);...return beanInstance;}catch (BeanCreationException ex) {...}}
createBean解析class并得到class的引用,并做了一些前置后置处理器的初始化,随后会进入doCreateBean()。
AbstractAutowireCapableBeanFactory#doCreateBean()
- 如果是单例,尝试从缓存中获取 bean 的包装器 BeanWrapper
 - 如果不存在对应的 Wrapper,则说明 bean 未被实例化,创建 bean 实例
 - 应用 MergedBeanDefinitionPostProcessor
 - 检查是否需要提前曝光,避免循环依赖
 - 初始化 bean 实例
 - 再次基于依存关系验证是否存在循环依赖
 - 注册 DisposableBean
 
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)throws BeanCreationException {BeanWrapper instanceWrapper = null;// 如果是单例,尝试获取对应的Bean包装器if (mbd.isSingleton()) {instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);}if (instanceWrapper == null) {/** 说明对应的bean还没有创建,用对应的策略(工厂方法、构造函数)创建bean实例,以及简单初始化** 将beanDefinition转成BeanWrapper,大致流程如下:* 1. 如果存在工厂方法,则使用工厂方法初始化* 2. 否则,如果存在多个构造函数,则根据参数确定构造函数,并利用构造函数初始化* 3. 否则,使用默认构造函数初始化*/instanceWrapper = createBeanInstance(beanName, mbd, args);}final Object bean = instanceWrapper.getWrappedInstance();// 获取class引用Class<?> beanType = instanceWrapper.getWrappedClass();if (beanType != NullBean.class) {mbd.resolvedTargetType = beanType;}// 应用MergedBeanDefinitionPostProcessorsynchronized (mbd.postProcessingLock) {if (!mbd.postProcessed) {try {applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);}catch (Throwable ex) {...}mbd.postProcessed = true;}}// 检查是否需要提前曝光,避免循环依赖boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences && isSingletonCurrentlyInCreation(beanName));if (earlySingletonExposure) {...// 添加一级缓存addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));}// 初始化Bean实例Object exposedObject = bean;try {// 属性填充populateBean(beanName, mbd, instanceWrapper);// 调用初始化方法exposedObject = initializeBean(beanName, exposedObject, mbd);}catch (Throwable ex) {...}// 在此基于依存关系验证是否存在循环依赖if (earlySingletonExposure) {// 提前曝光Object earlySingletonReference = getSingleton(beanName, false);if (earlySingletonReference != null) {// 检测到循环依赖if (exposedObject == bean) {exposedObject = earlySingletonReference;}else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {// 获取依赖的bean nameString[] dependentBeans = getDependentBeans(beanName);Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);for (String dependentBean : dependentBeans) {// 检测依赖,记录未完成创建的beanif (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {actualDependentBeans.add(dependentBean);}}// 不为空说明bean依赖的bean没有创建,存在循环依赖if (!actualDependentBeans.isEmpty()) {throw new BeanCurrentlyInCreationException(...);}}}}//注册DisposableBeantry {registerDisposableBeanIfNecessary(beanName, bean, mbd);}catch (BeanDefinitionValidationException ex) {...}return exposedObject;}
AbstractAutowireCapableBeanFactory#populateBean
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {if (bw == null) {...}boolean continueWithPropertyPopulation = true;// 给InstantiationAwareBeanPostProcessors最后一次机会在注入属性前改变bean实例if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {for (BeanPostProcessor bp : getBeanPostProcessors()) {if (bp instanceof InstantiationAwareBeanPostProcessor) {InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {continueWithPropertyPopulation = false;break;}}}}// 如果处理器指明不需要再继续执行属性注入,则返回if (!continueWithPropertyPopulation) {return;}PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);// autowire by name or autowire by typeif (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {MutablePropertyValues newPvs = new MutablePropertyValues(pvs);// autowire by nameif (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {autowireByName(beanName, mbd, bw, newPvs);}// autowire by typeif (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {autowireByType(beanName, mbd, bw, newPvs);}pvs = newPvs;}boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);// 在属性注入前应用实例化后置处理器if (hasInstAwareBpps || needsDepCheck) {if (pvs == null) {pvs = mbd.getPropertyValues();}PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);if (hasInstAwareBpps) {for (BeanPostProcessor bp : getBeanPostProcessors()) {if (bp instanceof InstantiationAwareBeanPostProcessor) {InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;// 调用后置处理器的postProcessPropertyValues方法pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);if (pvs == null) {return;}}}}if (needsDepCheck) {checkDependencies(beanName, mbd, filteredPds, pvs);}}// 执行属性注入if (pvs != null) {applyPropertyValues(beanName, mbd, bw, pvs);}}
该方法会执行 InstantiationAwareBeanPostProcessor 后置处理器的 postProcessAfterInstantiation 方法逻辑,从而实现对完成实例化且还没有注入属性值的对象进行最后的更改。
如果我们在 postProcessAfterInstantiation 指明不需要执行后续的属性注入过程,则方法到此结束;否则方法会检测当前的注入类型,是 byName 还是 byType,并调用相应的注入逻辑获取依赖的 bean,加入属性集合中。然后方法会调用 InstantiationAwareBeanPostProcessor 后置处理器的 postProcessPropertyValues 方法,实现在将属性值应用到 bean 实例之前的最后一次对属性值的更改,同时会依据配置执行依赖检查,以确保所有的属性都被赋值。
接下来我们看看真正的属性赋值操作。
AbstractAutowireCapableBeanFactory#applyPropertyValues
protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {...// 获取对应的解析器BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this, beanName, mbd, converter);// 深度拷贝List<PropertyValue> deepCopy = new ArrayList<>(original.size());boolean resolveNecessary = false;// 遍历属性,将属性转换成对应类的属性类型for (PropertyValue pv : original) {if (pv.isConverted()) {deepCopy.add(pv);}else {// 执行类型转换String propertyName = pv.getName();Object originalValue = pv.getValue();Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue);Object convertedValue = resolvedValue;boolean convertible = bw.isWritableProperty(propertyName) &&!PropertyAccessorUtils.isNestedOrIndexedProperty(propertyName);if (convertible) {convertedValue = convertForProperty(resolvedValue, propertyName, bw, converter);}// Possibly store converted value in merged bean definition,// in order to avoid re-conversion for every created bean instance.if (resolvedValue == originalValue) {if (convertible) {pv.setConvertedValue(convertedValue);}deepCopy.add(pv);}else if (convertible && originalValue instanceof TypedStringValue &&!((TypedStringValue) originalValue).isDynamic() &&!(convertedValue instanceof Collection || ObjectUtils.isArray(convertedValue))) {pv.setConvertedValue(convertedValue);deepCopy.add(pv);}else {resolveNecessary = true;deepCopy.add(new PropertyValue(pv, convertedValue));}}}if (mpvs != null && !resolveNecessary) {mpvs.setConverted();}try {// 设置值bw.setPropertyValues(new MutablePropertyValues(deepCopy));}catch (BeansException ex) {...}}
使用深拷贝完成了属性的注入。属性注入完成后执行的是initializeBean()方法。
AbstractAutowireCapableBeanFactory#initializeBean
- 激活 bean 实现的 Aware 类:BeanNameAware, BeanClassLoaderAware, BeanFactoryAware
 - 应用 BeanPostProcessor 的 postProcessBeforeInitialization
 - 激活用户自定义的 init-method 方法,以及常用的 afterPropertiesSet 方法
 - 应用 BeanPostProcessor 的 postProcessAfterInitialization
 
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {// 1. 激活bean实现的Aware类:BeanNameAware, BeanClassLoaderAware, BeanFactoryAwareif (System.getSecurityManager() != null) {AccessController.doPrivileged((PrivilegedAction<Object>) () -> {invokeAwareMethods(beanName, bean);return null;}, getAccessControlContext());}else {invokeAwareMethods(beanName, bean);}// 2. 应用 BeanPostProcessor 的 postProcessBeforeInitializationObject wrappedBean = bean;if (mbd == null || !mbd.isSynthetic()) {wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);}// 3. 激活用户自定义的 init-method 方法,以及常用的 afterPropertiesSet 方法try {invokeInitMethods(beanName, wrappedBean, mbd);}catch (Throwable ex) {throw new BeanCreationException((mbd != null ? mbd.getResourceDescription() : null),beanName, "Invocation of init method failed", ex);}// 4. 应用 BeanPostProcessor 的 postProcessAfterInitializationif (mbd == null || !mbd.isSynthetic()) {wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);}return wrappedBean;}
总结
首先,从Singleton工厂获取对象,随后进入createBean()方法,执行相关前置和后置处理器的初始化;处理完成后,调用doCrateBean的createBeanInstance进行Bean实例化操作;通过populateBean和applyPropertyValues进行属性注入,然后使用initializeBean激活Bean实现的Aware类,并检查循环依赖相关的逻辑,如果有必要,还会注册DisposableBean。
Spring中出现同名Bean怎么办
- 同一个配置文件内同名的Bean,以最上面定义的为准
 - 不同配置文件中存在同名Bean,后解析的配置文件会覆盖先解析的配置文件
 - 同文件中ComponentScan和@Bean出现同名Bean。同文件下@Bean的会生效,@ComponentScan扫描进来不会生效。通过@ComponentScan扫描进来的优先级是最低的,原因就是它扫描进来的Bean定义是最先被注册的
循环依赖
循环依赖:当Bean A依赖于Bean B时,而Bean B也正好依赖于Bean A。
spring对循环依赖的处理有三种情况: ①构造器的循环依赖:这种依赖spring是处理不了的,直 接抛出BeanCurrentlylnCreationException异常。 ②单例模式下的setter循环依赖:通过“三级缓存”处理循环依赖。 ③非单例循环依赖:无法处理。
Spring单例对象初始化主要步骤如下: 
- createBeanInstance:实例化,其实也就是调用对象的构造方法实例化对象;
 - populateBean:填充属性,这一步主要是多bean的依赖属性进行填充;
 - initializeBean:调用spring xml中的init 方法。
 
循环依赖主要发生在第一、二步,分别是构造器循环依赖和field循环依赖。在这里,引入了一个三级缓存的概念,源码在DefaultSingletonBeanRegistry类中:
/** Cache of singleton objects: bean name --> bean instance */private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);/** Cache of singleton factories: bean name --> ObjectFactory */private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);/** Cache of early singleton objects: bean name --> bean instance */private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);
三级缓存从里到外分别是:
- singletonFactories : 单例对象工厂的cache;
 - earlySingletonObjects :提前曝光的单例对象的Cache;
 - singletonObjects:单例对象的cache。
 
具体获取Bean的代码在DefaultSingletonBeanRegistry的getSingleton()方法中:
@Nullableprotected Object getSingleton(String beanName, boolean allowEarlyReference) {// 先从最外层缓存获取Object singletonObject = this.singletonObjects.get(beanName);if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {synchronized (this.singletonObjects) {singletonObject = this.earlySingletonObjects.get(beanName);if (singletonObject == null && allowEarlyReference) {ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);if (singletonFactory != null) {singletonObject = singletonFactory.getObject();this.earlySingletonObjects.put(beanName, singletonObject);this.singletonFactories.remove(beanName);}}}}return singletonObject;}
那么一级缓存是什么时候添加的呢,细心的读者一定可以发现,在doCreateBean()方法中,createBeanInstance之后,属性注入之前,有一步:addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));,只要完成了实例化,就直接曝光,这就是所谓的早期引用概念。
值得注意的是,早期引用只能解决Setter注入的循环依赖问题,对于构造器注入和多实例的循环依赖问题是没有办法解决的。可以使用@Lazy注解进行懒加载来解决。
前置后置处理器
具体使用例子如下:
public class InitHelloWorld implements BeanPostProcessor{public Object postProcessBeforeInitialization(Object bean,String beanName) {System.out.println("BeforeInitialization:"+beanName);return bean; // you can return any other object as well}public Object postProcessAfterInitialization(Object bean,String beanName) {System.out.println("AfterInitialization:"+beanName);return bean; // you can return any other object as well}}
首先需要实现BeanPostProcessor接口,然后重写前置和后置逻辑,最后需要在xml文件中进行配置:
<bean class = "com.lamarsan.InitHelloWorld"></bean>
AOP
Spring AOP是面向切面编程,它的单元是切面,我们可以对切面做一些增强,同时它有利于代码的维护。AOP的实现方式主要有基于jdk的动态代理以及基于cglib的动态代理,我们可以用基于xml配置以及AspectJ注解来实现Spring AOP。好处是减少重复代码,提高开发效率,并且便于维护。
相关概念术语
- 连接点(Joinpoint)
程序执行的某个特定位置(如:某个方法调用前、调用后,方法抛出异常后)。Spring仅支持方法的连接点。 - 增强(Advice)
增强是织入到目标类连接点上的一段程序代码。 - 引介(Introduction)
引介是一种特殊的增强,它为类添加一些属性和方法。这样,即使一个业务类原本没有实现某个接口,通过引介功能,可以动态的未该业务类添加接口的实现逻辑,让业务类成为这个接口的实现类。 - 切点(Pointcut)
查询条件,一个切点可以匹配多个连接点。Spring AOP的规则解析引擎负责解析切点所设定的查询条件,找到对应的连接点。 - 切面(Aspect)
切面是由切点和增强(引介)组成的,它包括了对横切关注功能的定义,也包括了对连接点的定义。 - 织入(Weaving)
织入是将增强添加到目标类具体连接点上的过程,AOP有三种织入方式:- 编译期织入:需要特殊的Java编译期(例如AspectJ的ajc);
 - 装载期织入:要求使用特殊的类加载器,在装载类的时候对类进行增强;
 - 运行时织入:在运行时为目标类生成代理实现增强。
 
 
Spring采用了动态代理的方式实现了运行时织入,而AspectJ采用了编译期织入和装载期织入的方式。
AOP的原理
AOP代理主要分为静态代理和动态代理。
- 静态代理
静态代理的代表为AspectJ;而动态代理则以Spring AOP为代表。通常使用AspectJ的编译时增强实现AOP,AspectJ是静态代理的增强,所谓的静态代理就是AOP框架会在编译阶段生成AOP代理类,因此也称为编译时增强。 动态代理
Spring AOP中的动态代理主要有两种方式,JDK动态代理和CGLIB动态代理。
JDK动态代理通过反射来接收被代理的类,并且要求被代理的类必须实现一个接口。
如果目标类没有实现接口,那么Spring AOP会选择使用CGLIB来动态代理目标类。CGLIB(Code Generation Library),是一个代码生成的类库,可以在运行时动态的生成某个类的子类,注意,CGLIB是通过继承的方式做的动态代理,因此如果某个类被标记为final,那么它是无法使用CGLIB做动态代理的。Spring事务隔离级别和事务传播属性
隔离级别
DEFAULT(默认),使用数据库默认的隔离级别
- READ_UNCOMMITTED(读未提交)
 - READ_COMMITTED(读已提交)
 - REPEATABLE_READ(可重复读)
 - 
传播属性
 REQUIRED(默认)
如果存在一个事务,则支持当前事务,没有就开启一个新的事务。- REQUIRES_NEW
新建一个事务,如果当前存在事务,就挂起。 - MANDATORY
支持当前事务,如果没有事务就抛出异常。 - NEVER
以非事务方式运行,如果存在事务就抛出异常。 - NOT_SUPPORTED
以非事务方式执行操作,如果当前存在事务,就挂起。 - SUPPORTS
支持当前事务,如果当前没有事务,就以非事务方式执行。 NESTED(嵌套事务)
支持当前事务,新增Savepoint,与当前事务同步提交或回滚。Spring声明式事务原理
当声明了@Transaction之后,首先会使用拦截器TransactionInterceptor进行拦截,调用invoke,然后调用父类的invokeWithinTransaction方法:
public Object invoke(MethodInvocation invocation) throws Throwable {Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null);// Adapt to TransactionAspectSupport's invokeWithinTransaction...return invokeWithinTransaction(invocation.getMethod(), targetClass, invocation::proceed);}
原理
在应用系统调用声明@Transactional 的目标方法时,Spring Framework ,根据@Transactional 的属性配置信息,这个代理对象决定该声明@Transactional 的目标方法是否由拦截器 TransactionInterceptor 来使用拦截,在 TransactionInterceptor 拦截时,会在目标方法开始执行之前创建并加入事务,并执行目标方法的逻辑, 最后根据执行情况是否出现异常,利用抽象事务管理器AbstractPlatformTransactionManager 操作数据源 DataSource 提交或回滚事务。
失效原因
- @Transactional注解应用到非public方法(除非特殊配置,例如使用AspectJ 静态织入实现 AOP);
 - 自调用,因为@Transactional是基于动态代理实现的;
 - 异常在代码中被你自己try catch了;
 - 异常类型不正确,默认只支持RuntimeException和Error,不支持检查异常;
 - 事务传播配置不符合业务逻辑。
 
由于基于动态代理实现(实现接口),因此修饰接口的必须是public类型,非public类型可以用AspectJ。
Spring事务管理有哪些优点
- 它提供了跨不同事务api(如JTA、JDBC、Hibernate、JPA和JDO)的一致编程模型。
 - 它为编程事务管理提供了比JTA等许多复杂事务API更简单的API。
 - 它支持声明式事务管理。
 - 它很好地集成了Spring的各种数据访问抽象。
Spring中的设计模式
 
- 简单工厂模式
简单工厂模式的实质是由一个工厂类根据传入的参数,动态决定应该创建哪一个产品类,不属于23种设计模式之一。Spring 中的 BeanFactory 就是简单工厂模式的体现,根据传入一个唯一的标识来获得 Bean 对象。 - 工厂方法模式
应用程序将对象的创建及初始化职责交给工厂对象。 一般情况下,应用程序有自己的工厂对象来创建 Bean。 - 单例模式
保证一个类仅有一个实例,并提供一个访问它的全局访问点。 Spring 中的单例模式完成了后半句话,即提供了全局的访问点 BeanFactory。但没有从构造器级别去 控制单例,这是因为 Spring 管理的是是任意的 Java 对象。 Spring 下默认的 Bean 均为单例。 - 原型模式
原型模式就是从一个对象再创建另外一个可定制的对象,而且不需要知道任何创建的细节。如在IOC为Bean注入属性的时候,会使用深拷贝,就是一个原型模式的体现。 - 代理模式
为其他对象提供一种代理以控制对这个对象的访问。Spring 的 Proxy 模式在 AOP 中有体现,比如 JdkDynamicAopProxy 和 Cglib2AopProxy。 - 策略模式
定义一系列的算法,把它们一个个封装起来,并且使它们可相互替换,使最终结果是固定的。Spring 中在实例化对象的时候用到 Strategy 模式,在 SimpleInstantiationStrategy 有使用。 - 模板方法模式
定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。Spring 中的 JdbcTemplate就是用的模板模式。 - 适配器模式
注重转换。前端控制器DispatcherServlet可以把它理解为适配器模式中的Client,它的主要作用在于通过处理映射器(HandlerMapper)来找到相应的Handler,然后通过适配器去找到对应的Controller,并执行Controller中相应的方法并返回ModelAndView。如果不使用适配器接口,就要多许多if,else判断了,违反开闭原则。 - 装饰器模式
主要用于扩展功能。所有以Wrapper和Decorator结尾的类名都是。 - 观察者模式
定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象 都得到通知并被自动更新。Spring 中 Observer 模式常用的地方是 Listener 的实现。如 ApplicationListener。 

