上文,咱们看了IOC设计要点和设计构造;以及Spring如何实现将资源配置(以xml配置为例)通过加载,解析,生成BeanDefination并注册到IoC容器中的;容器中寄存的是Bean的定义即BeanDefinition放到beanDefinitionMap中,实质上是一个ConcurrentHashMap<String, Object>
;并且BeanDefinition接口中蕴含了这个类的Class信息以及是否是单例等。那么如何从BeanDefinition中实例化Bean对象呢,这是本文次要钻研的内容?@pdai
Spring框架系列(8) - Spring IOC实现原理详解之Bean实例化(生命周期,循环依赖等)
- 引入
BeanFactory中getBean的主体思路
- 初步的思考
- Spring中getBean的主体思路
重点:Spring如何解决循环依赖问题
- Spring单例模式下的属性依赖
Spring为何不能解决非单例属性之外的循环依赖?
- Spring为什么不能解决结构器的循环依赖?
- Spring为什么不能解决prototype作用域循环依赖?
- Spring为什么不能解决多例的循环依赖?
- 那么其它循环依赖如何解决?
重点:Spring中Bean的生命周期
- Spring Bean生命周期流程
- Spring Bean生命周期案例
- 参考文章
- 更多文章
引入
上文,咱们看了IOC设计要点和设计构造;以及Spring如何实现将资源配置(以xml配置为例)通过加载,解析,生成BeanDefination并注册到IoC容器中的;容器中寄存的是Bean的定义即BeanDefinition放到beanDefinitionMap中,实质上是一个ConcurrentHashMap<String, Object>
;并且BeanDefinition接口中蕴含了这个类的Class信息以及是否是单例等。那么如何从BeanDefinition中实例化Bean对象呢?
本文次要钻研如何从IOC容器已有的BeanDefinition信息,实例化出Bean对象;这里还会包含三块重点内容:
- BeanFactory中getBean的主体思路
- Spring如何解决循环依赖问题
- Spring中Bean的生命周期
BeanFactory中getBean的主体思路
上文中咱们晓得BeanFactory定义了Bean容器的标准,其中蕴含依据bean的名字, Class类型和参数等来失去bean实例。
// 依据bean的名字和Class类型等来失去bean实例 Object getBean(String name) throws BeansException; Object getBean(String name, Class requiredType) throws BeansException; Object getBean(String name, Object... args) throws BeansException;<T> T getBean(Class<T> requiredType) throws BeansException;<T> T getBean(Class<T> requiredType, Object... args) throws BeansException;
初步的思考
上文咱们曾经剖析了IoC初始化的流程,最终的将Bean的定义即BeanDefinition放到beanDefinitionMap中,实质上是一个ConcurrentHashMap<String, Object>
;并且BeanDefinition接口中蕴含了这个类的Class信息以及是否是单例等;
这样咱们初步有了实现Object getBean(String name)
这个办法的思路:
- 从beanDefinitionMap通过beanName取得BeanDefinition
- 从BeanDefinition中取得beanClassName
通过反射初始化beanClassName的实例instance
- 构造函数从BeanDefinition的getConstructorArgumentValues()办法获取
- 属性值从BeanDefinition的getPropertyValues()办法获取
- 返回beanName的实例instance
因为BeanDefinition还有单例的信息,如果是无参构造函数的实例还能够放在一个缓存中,这样下次获取这个单例的实例时只须要从缓存中获取,如果获取不到再通过上述步骤获取。
(PS:如上只是咱们初步的思路,而Spring还须要思考各种设计上的问题,比方beanDefinition中其它定义,循环依赖等;所以咱们来看下Spring是如何是如何实现的)
Spring中getBean的主体思路
BeanFactory实现getBean办法在AbstractBeanFactory中,这个办法重载都是调用doGetBean办法进行实现的:
public Object getBean(String name) throws BeansException { return doGetBean(name, null, null, false);}public <T> T getBean(String name, Class<T> requiredType) throws BeansException { return doGetBean(name, requiredType, null, false);}public Object getBean(String name, Object... args) throws BeansException { return doGetBean(name, null, args, false);}public <T> T getBean(String name, @Nullable Class<T> requiredType, @Nullable Object... args) throws BeansException { return doGetBean(name, requiredType, args, false);}
咱们来看下doGetBean办法(这个办法很长,咱们次要看它的整体思路和设计要点):
// 参数typeCheckOnly:bean实例是否蕴含一个类型查看protected <T> T doGetBean( String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly) throws BeansException { // 解析bean的真正name,如果bean是工厂类,name前缀会加&,须要去掉 String beanName = transformedBeanName(name); Object beanInstance; // Eagerly check singleton cache for manually registered singletons. Object sharedInstance = getSingleton(beanName); if (sharedInstance != null && args == null) { // 无参单例从缓存中获取 beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null); } else { // 如果bean实例还在创立中,则间接抛出异样 if (isPrototypeCurrentlyInCreation(beanName)) { throw new BeanCurrentlyInCreationException(beanName); } // 如果 bean definition 存在于父的bean工厂中,委派给父Bean工厂获取 BeanFactory parentBeanFactory = getParentBeanFactory(); if (parentBeanFactory != null && !containsBeanDefinition(beanName)) { // Not found -> check parent. String nameToLookup = originalBeanName(name); if (parentBeanFactory instanceof AbstractBeanFactory) { return ((AbstractBeanFactory) parentBeanFactory).doGetBean( nameToLookup, requiredType, args, typeCheckOnly); } else if (args != null) { // Delegation to parent with explicit args. return (T) parentBeanFactory.getBean(nameToLookup, args); } else if (requiredType != null) { // No args -> delegate to standard getBean method. return parentBeanFactory.getBean(nameToLookup, requiredType); } else { return (T) parentBeanFactory.getBean(nameToLookup); } } if (!typeCheckOnly) { // 将以后bean实例放入alreadyCreated汇合里,标识这个bean筹备创立了 markBeanAsCreated(beanName); } StartupStep beanCreation = this.applicationStartup.start("spring.beans.instantiate") .tag("beanName", name); try { if (requiredType != null) { beanCreation.tag("beanType", requiredType::toString); } RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); checkMergedBeanDefinition(mbd, beanName, args); // 确保它的依赖也被初始化了. String[] dependsOn = mbd.getDependsOn(); if (dependsOn != null) { for (String dep : dependsOn) { if (isDependent(beanName, dep)) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'"); } registerDependentBean(dep, beanName); try { getBean(dep); // 初始化它依赖的Bean } catch (NoSuchBeanDefinitionException ex) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "'" + beanName + "' depends on missing bean '" + dep + "'", ex); } } } // 创立Bean实例:单例 if (mbd.isSingleton()) { sharedInstance = getSingleton(beanName, () -> { try { // 真正创立bean的办法 return createBean(beanName, mbd, args); } catch (BeansException ex) { // Explicitly remove instance from singleton cache: It might have been put there // eagerly by the creation process, to allow for circular reference resolution. // Also remove any beans that received a temporary reference to the bean. destroySingleton(beanName); throw ex; } }); beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); } // 创立Bean实例:原型 else if (mbd.isPrototype()) { // It's a prototype -> create a new instance. Object prototypeInstance = null; try { beforePrototypeCreation(beanName); prototypeInstance = createBean(beanName, mbd, args); } finally { afterPrototypeCreation(beanName); } beanInstance = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd); } // 创立Bean实例:依据bean的scope创立 else { String scopeName = mbd.getScope(); if (!StringUtils.hasLength(scopeName)) { throw new IllegalStateException("No scope name defined for bean ´" + beanName + "'"); } Scope scope = this.scopes.get(scopeName); if (scope == null) { throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'"); } try { Object scopedInstance = scope.get(beanName, () -> { beforePrototypeCreation(beanName); try { return createBean(beanName, mbd, args); } finally { afterPrototypeCreation(beanName); } }); beanInstance = getObjectForBeanInstance(scopedInstance, name, beanName, mbd); } catch (IllegalStateException ex) { throw new ScopeNotActiveException(beanName, scopeName, ex); } } } catch (BeansException ex) { beanCreation.tag("exception", ex.getClass().toString()); beanCreation.tag("message", String.valueOf(ex.getMessage())); cleanupAfterBeanCreationFailure(beanName); throw ex; } finally { beanCreation.end(); } } return adaptBeanInstance(name, beanInstance, requiredType);}
这段代码很长,次要看我加中文正文的办法即可。
- 解析bean的真正name,如果bean是工厂类,name前缀会加&,须要去掉
- 无参单例先从缓存中尝试获取
- 如果bean实例还在创立中,则间接抛出异样
- 如果bean definition 存在于父的bean工厂中,委派给父Bean工厂获取
- 标记这个beanName的实例正在创立
- 确保它的依赖也被初始化
真正创立
- 单例时
- 原型时
- 依据bean的scope创立
重点:Spring如何解决循环依赖问题
首先咱们须要阐明,Spring只是解决了单例模式下属性依赖的循环问题;Spring为了解决单例的循环依赖问题,应用了三级缓存。
Spring单例模式下的属性依赖
先来看下这三级缓存
/** Cache of singleton objects: bean name --> bean instance */private final Map<String, Object> singletonObjects = new ConcurrentHashMap<String, Object>(256); /** Cache of early singleton objects: bean name --> bean instance */private final Map<String, Object> earlySingletonObjects = new HashMap<String, Object>(16);/** Cache of singleton factories: bean name --> ObjectFactory */private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<String, ObjectFactory<?>>(16);
- 第一层缓存(singletonObjects):单例对象缓存池,曾经实例化并且属性赋值,这里的对象是成熟对象;
- 第二层缓存(earlySingletonObjects):单例对象缓存池,曾经实例化但尚未属性赋值,这里的对象是半成品对象;
- 第三层缓存(singletonFactories): 单例工厂的缓存
如下是获取单例中
protected Object getSingleton(String beanName, boolean allowEarlyReference) { // Spring首先从singletonObjects(一级缓存)中尝试获取 Object singletonObject = this.singletonObjects.get(beanName); // 若是获取不到而且对象在建设中,则尝试从earlySingletonObjects(二级缓存)中获取 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) { //若是仍是获取不到而且答应从singletonFactories通过getObject获取,则通过singletonFactory.getObject()(三级缓存)获取 singletonObject = singletonFactory.getObject(); //若是获取到了则将singletonObject放入到earlySingletonObjects,也就是将三级缓存进步到二级缓存中 this.earlySingletonObjects.put(beanName, singletonObject); this.singletonFactories.remove(beanName); } } } } return (singletonObject != NULL_OBJECT ? singletonObject : null);}
补充一些办法和参数
isSingletonCurrentlyInCreation()
:判断以后单例bean是否正在建设中,也就是没有初始化实现(好比A的结构器依赖了B对象因而得先去建设B对象, 或则在A的populateBean过程当中依赖了B对象,得先去建设B对象,这时的A就是处于建设中的状态。)allowEarlyReference
:是否答应从singletonFactories中通过getObject拿到对象
剖析getSingleton()的整个过程,Spring首先从一级缓存singletonObjects中获取。若是获取不到,而且对象正在建设中,就再从二级缓存earlySingletonObjects中获取。若是仍是获取不到且答应singletonFactories通过getObject()获取,就从三级缓存singletonFactory.getObject()(三级缓存)获取,若是获取到了则从三级缓存挪动到了二级缓存。
从下面三级缓存的剖析,咱们可能晓得,Spring解决循环依赖的窍门就在于singletonFactories这个三级cache。这个cache的类型是ObjectFactory,定义以下:
public interface ObjectFactory<T> { T getObject() throws BeansException;}
在bean建设过程当中,有两处比拟重要的匿名外部类实现了该接口。一处是Spring利用其建设bean的时候,另外一处就是:
addSingletonFactory(beanName, new ObjectFactory<Object>() { @Override public Object getObject() throws BeansException { return getEarlyBeanReference(beanName, mbd, bean); }});
此处就是解决循环依赖的要害,这段代码产生在createBeanInstance当前,也就是说单例对象此时曾经被建设进去的。这个对象曾经被生产进去了,尽管还不完满(尚未进行初始化的第二步和第三步),可是曾经能被人认出来了(依据对象援用能定位到堆中的对象),因而Spring此时将这个对象提前曝光进去让你们意识,让你们应用。
好比“A对象setter依赖B对象,B对象setter依赖A对象”,A首先实现了初始化的第一步,而且将自身提前曝光到singletonFactories中,此时进行初始化的第二步,发现自身依赖对象B,此时就尝试去get(B),发现B尚未被create,因而走create流程,B在初始化第一步的时候发现自身依赖了对象A,因此尝试get(A),尝试一级缓存singletonObjects(确定没有,因为A还没初始化彻底),尝试二级缓存earlySingletonObjects(也没有),尝试三级缓存singletonFactories,因为A通过ObjectFactory将自身提前曝光了,因而B能够通过ObjectFactory.getObject拿到A对象(半成品),B拿到A对象后顺利完成了初始化阶段一、二、三,彻底初始化当前将自身放入到一级缓存singletonObjects中。此时返回A中,A此时能拿到B的对象顺利完成自身的初始化阶段二、三,最终A也实现了初始化,进去了一级缓存singletonObjects中,并且更加侥幸的是,因为B拿到了A的对象援用,因而B现在hold住的A对象实现了初始化。
Spring为何不能解决非单例属性之外的循环依赖?
通过以下几个问题,辅助咱们进一步了解。
Spring为什么不能解决结构器的循环依赖?
结构器注入造成的循环依赖: 也就是beanB须要在beanA的构造函数中实现初始化,beanA也须要在beanB的构造函数中实现初始化,这种状况的后果就是两个bean都不能实现初始化,循环依赖难以解决。
Spring解决循环依赖次要是依赖三级缓存,然而的在调用构造方法之前还未将其放入三级缓存之中,因而后续的依赖调用构造方法的时候并不能从三级缓存中获取到依赖的Bean,因而不能解决。
Spring为什么不能解决prototype作用域循环依赖?
这种循环依赖同样无奈解决,因为spring不会缓存‘prototype’作用域的bean,而spring中循环依赖的解决正是通过缓存来实现的。
Spring为什么不能解决多例的循环依赖?
多实例Bean是每次调用一次getBean都会执行一次构造方法并且给属性赋值,基本没有三级缓存,因而不能解决循环依赖。
那么其它循环依赖如何解决?
那么理论开发中,相似的依赖是如何解决?
- 生成代理对象产生的循环依赖
这类循环依赖问题解决办法很多,次要有:
- 应用@Lazy注解,提早加载
- 应用@DependsOn注解,指定加载先后关系
- 批改文件名称,扭转循环依赖类的加载程序
- 应用@DependsOn产生的循环依赖
这类循环依赖问题要找到@DependsOn注解循环依赖的中央,迫使它不循环依赖就能够解决问题。
- 多例循环依赖
这类循环依赖问题能够通过把bean改成单例的解决。
- 结构器循环依赖
这类循环依赖问题能够通过应用@Lazy注解解决。
重点:Spring中Bean的生命周期
Spring 只帮咱们治理单例模式 Bean 的残缺生命周期,对于 prototype 的 bean ,Spring 在创立好交给使用者之后则不会再治理后续的生命周期。
Spring 容器能够治理 singleton 作用域 Bean 的生命周期,在此作用域下,Spring 可能准确地晓得该 Bean 何时被创立,何时初始化实现,以及何时被销毁。
而对于 prototype 作用域的 Bean,Spring 只负责创立,当容器创立了 Bean 的实例后,Bean 的实例就交给客户端代码治理,Spring 容器将不再跟踪其生命周期。每次客户端申请 prototype 作用域的 Bean 时,Spring 容器都会创立一个新的实例,并且不会管那些被配置成 prototype 作用域的 Bean 的生命周期。
理解 Spring 生命周期的意义就在于,能够利用 Bean 在其存活期间的指定时刻实现一些相干操作。这种时刻可能有很多,但个别状况下,会在 Bean 被初始化后和被销毁前执行一些相干操作。
Spring Bean生命周期流程
在 Spring 中,Bean 的生命周期是一个很简单的执行过程,咱们能够利用 Spring 提供的办法定制 Bean 的创立过程。
Spring 容器中 Bean 的生命周期流程
- 如果 BeanFactoryPostProcessor 和 Bean 关联, 则调用postProcessBeanFactory办法.(即首先尝试从Bean工厂中获取Bean)
- 如果 InstantiationAwareBeanPostProcessor 和 Bean 关联,则调用postProcessBeforeInstantiation办法
- 依据配置状况调用 Bean 构造方法实例化 Bean。
- 利用依赖注入实现 Bean 中所有属性值的配置注入。
- 如果 InstantiationAwareBeanPostProcessor 和 Bean 关联,则调用postProcessAfterInstantiation办法和postProcessProperties
调用xxxAware接口 (上图只是给了几个例子)
第一类Aware接口
- 如果 Bean 实现了 BeanNameAware 接口,则 Spring 调用 Bean 的 setBeanName() 办法传入以后 Bean 的 id 值。
- 如果 Bean 实现了 BeanClassLoaderAware 接口,则 Spring 调用 setBeanClassLoader() 办法传入classLoader的援用。
- 如果 Bean 实现了 BeanFactoryAware 接口,则 Spring 调用 setBeanFactory() 办法传入以后工厂实例的援用。
第二类Aware接口
- 如果 Bean 实现了 EnvironmentAware 接口,则 Spring 调用 setEnvironment() 办法传入以后 Environment 实例的援用。
- 如果 Bean 实现了 EmbeddedValueResolverAware 接口,则 Spring 调用 setEmbeddedValueResolver() 办法传入以后 StringValueResolver 实例的援用。
- 如果 Bean 实现了 ApplicationContextAware 接口,则 Spring 调用 setApplicationContext() 办法传入以后 ApplicationContext 实例的援用。
- ...
- 如果 BeanPostProcessor 和 Bean 关联,则 Spring 将调用该接口的预初始化办法 postProcessBeforeInitialzation() 对 Bean 进行加工操作,此处十分重要,Spring 的 AOP 就是利用它实现的。
- 如果 Bean 实现了 InitializingBean 接口,则 Spring 将调用 afterPropertiesSet() 办法。(或者有执行@PostConstruct注解的办法)
- 如果在配置文件中通过 init-method 属性指定了初始化办法,则调用该初始化办法。
- 如果 BeanPostProcessor 和 Bean 关联,则 Spring 将调用该接口的初始化办法 postProcessAfterInitialization()。此时,Bean 曾经能够被利用零碎应用了。
- 如果在
<bean>
中指定了该 Bean 的作用范畴为 scope="singleton",则将该 Bean 放入 Spring IoC 的缓存池中,将触发 Spring 对该 Bean 的生命周期治理;如果在<bean>
中指定了该 Bean 的作用范畴为 scope="prototype",则将该 Bean 交给调用者,调用者治理该 Bean 的生命周期,Spring 不再治理该 Bean。 - 如果 Bean 实现了 DisposableBean 接口,则 Spring 会调用 destory() 办法将 Spring 中的 Bean 销毁;(或者有执行@PreDestroy注解的办法)
- 如果在配置文件中通过 destory-method 属性指定了 Bean 的销毁办法,则 Spring 将调用该办法对 Bean 进行销毁。
Bean的残缺生命周期经验了各种办法调用,这些办法能够划分为以下几类:(<mark>联合上图,须要有如下顶层思维</mark>)
- Bean本身的办法: 这个包含了Bean自身调用的办法和通过配置文件中
<bean>
的init-method和destroy-method指定的办法 - Bean级生命周期接口办法: 这个包含了BeanNameAware、BeanFactoryAware、ApplicationContextAware;当然也包含InitializingBean和DiposableBean这些接口的办法(能够被@PostConstruct和@PreDestroy注解代替)
- 容器级生命周期接口办法: 这个包含了InstantiationAwareBeanPostProcessor 和 BeanPostProcessor 这两个接口实现,个别称它们的实现类为“后处理器”。
- 工厂后处理器接口办法: 这个包含了AspectJWeavingEnabler, ConfigurationClassPostProcessor, CustomAutowireConfigurer等等十分有用的工厂后处理器接口的办法。工厂后处理器也是容器级的。在利用上下文拆卸配置文件之后立刻调用。
Spring Bean生命周期案例
咱们通过一个例子来验证下面的整个流程
定义Bean(这里是User), 并让它实现BeanNameAware,BeanFactoryAware,ApplicationContextAware接口和InitializingBean,DisposableBean接口:
package tech.pdai.springframework.entity;import lombok.ToString;import lombok.extern.slf4j.Slf4j;import org.springframework.beans.BeansException;import org.springframework.beans.factory.BeanFactory;import org.springframework.beans.factory.BeanFactoryAware;import org.springframework.beans.factory.BeanNameAware;import org.springframework.beans.factory.DisposableBean;import org.springframework.beans.factory.InitializingBean;import org.springframework.context.ApplicationContext;import org.springframework.context.ApplicationContextAware;/** * @author pdai */@Slf4j@ToStringpublic class User implements BeanFactoryAware, BeanNameAware, ApplicationContextAware, InitializingBean, DisposableBean { /** * user's name. */ private String name; /** * user's age. */ private int age; /** * bean factory. */ private BeanFactory beanFactory; /** * application context. */ private ApplicationContext applicationContext; /** * bean name. */ private String beanName; public User() { log.info("execute User#new User()"); } public void setName(String name) { log.info("execute User#setName({})", name); this.name = name; } public void setAge(int age) { log.info("execute User#setAge({})", age); this.age = age; } @Override public void setBeanFactory(BeanFactory beanFactory) throws BeansException { log.info("execute BeanFactoryAware#setBeanFactory"); this.beanFactory = beanFactory; } @Override public void setBeanName(String s) { log.info("execute BeanNameAware#setBeanName"); this.beanName = s; } @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { log.info("execute ApplicationContextAware#setApplicationContext"); this.applicationContext = applicationContext; } @Override public void destroy() throws Exception { log.info("execute DisposableBean#destroy"); } @Override public void afterPropertiesSet() throws Exception { log.info("execute InitializingBean#afterPropertiesSet"); } public void doInit() { log.info("execute User#doInit"); } public void doDestroy() { log.info("execute User#doDestroy"); }}
定义BeanFactoryPostProcessor的实现类
/** * @author pdai */@Slf4j@Componentpublic class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor { @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException { log.info("execute BeanFactoryPostProcessor#postProcessBeanFactory"); }}
定义InstantiationAwareBeanPostProcessor的实现类
/** * @author pdai */@Slf4j@Componentpublic class MyInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor { @Override public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException { log.info("execute InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation for {}", beanName); return InstantiationAwareBeanPostProcessor.super.postProcessBeforeInstantiation(beanClass, beanName); } @Override public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException { log.info("execute InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation for {}", beanName); return InstantiationAwareBeanPostProcessor.super.postProcessAfterInstantiation(bean, beanName); } @Override public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException { log.info("execute InstantiationAwareBeanPostProcessor#postProcessProperties for {}", beanName); return InstantiationAwareBeanPostProcessor.super.postProcessProperties(pvs, bean, beanName); }}
定义BeanPostProcessor的实现类
/** * @author pdai */@Slf4j@Componentpublic class MyBeanPostProcessor implements BeanPostProcessor { @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { log.info("execute BeanPostProcessor#postProcessBeforeInitialization for {}", beanName); return BeanPostProcessor.super.postProcessBeforeInitialization(bean, beanName); } @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { log.info("execute BeanPostProcessor#postProcessAfterInitialization for {}", beanName); return BeanPostProcessor.super.postProcessAfterInitialization(bean, beanName); }}
通过Java配置形式初始化Bean
/** * @author pdai */@Configurationpublic class BeansConfig { @Bean(name = "user", initMethod = "doInit", destroyMethod = "doDestroy") public User create() { User user = new User(); user.setName("pdai"); user.setAge(18); return user; }}
测试的主办法
/** * Cglib proxy demo. * * @author pdai */@Slf4jpublic class App { /** * main interface. * * @param args args */ public static void main(String[] args) { log.info("Init application context"); // create and configure beans AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext( "tech.pdai.springframework"); // retrieve configured instance User user = (User) context.getBean("user"); // print info from beans log.info(user.toString()); log.info("Shutdown application context"); context.registerShutdownHook(); }}
输入后果(剔除无关输入):
12:44:42.547 [main] INFO tech.pdai.springframework.App - Init application context...12:44:43.134 [main] INFO tech.pdai.springframework.processor.MyBeanFactoryPostProcessor - execute BeanFactoryPostProcessor#postProcessBeanFactory...12:44:43.216 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'user'12:44:43.216 [main] INFO tech.pdai.springframework.processor.MyInstantiationAwareBeanPostProcessor - execute InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation for user12:44:43.236 [main] INFO tech.pdai.springframework.entity.User - execute User#new User()12:44:43.237 [main] INFO tech.pdai.springframework.entity.User - execute User#setName(pdai)12:44:43.237 [main] INFO tech.pdai.springframework.entity.User - execute User#setAge(18)12:44:43.237 [main] INFO tech.pdai.springframework.processor.MyInstantiationAwareBeanPostProcessor - execute InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation for user12:44:43.237 [main] INFO tech.pdai.springframework.processor.MyInstantiationAwareBeanPostProcessor - execute InstantiationAwareBeanPostProcessor#postProcessProperties for user12:44:43.242 [main] INFO tech.pdai.springframework.entity.User - execute BeanNameAware#setBeanName12:44:43.242 [main] INFO tech.pdai.springframework.entity.User - execute BeanFactoryAware#setBeanFactory12:44:43.242 [main] INFO tech.pdai.springframework.entity.User - execute ApplicationContextAware#setApplicationContext12:44:43.242 [main] INFO tech.pdai.springframework.processor.MyBeanPostProcessor - execute BeanPostProcessor#postProcessBeforeInitialization for user12:44:43.242 [main] INFO tech.pdai.springframework.entity.User - execute InitializingBean#afterPropertiesSet12:44:43.243 [main] INFO tech.pdai.springframework.entity.User - execute User#doInit12:44:43.243 [main] INFO tech.pdai.springframework.processor.MyBeanPostProcessor - execute BeanPostProcessor#postProcessAfterInitialization for user12:44:43.270 [main] INFO tech.pdai.springframework.App - User(name=pdai, age=18)12:44:43.270 [main] INFO tech.pdai.springframework.App - Shutdown application context12:44:43.276 [SpringContextShutdownHook] INFO tech.pdai.springframework.entity.User - execute DisposableBean#destroy12:44:43.276 [SpringContextShutdownHook] INFO tech.pdai.springframework.entity.User - execute User#doDestroy
参考文章
https://juejin.cn/post/684490...
https://www.zhihu.com/questio...
更多文章
首先, 从Spring框架的整体架构和组成对整体框架有个认知。
Spring根底 - Spring和Spring框架组成
- Spring是什么?它是怎么诞生的?有哪些次要的组件和外围性能呢? 本文通过这几个问题帮忙你构筑Spring和Spring Framework的整体认知。
其次,通过案例引出Spring的外围(IoC和AOP),同时对IoC和AOP进行案例应用剖析。
Spring根底 - Spring简略例子引入Spring的外围
- 上文中咱们简略介绍了Spring和Spring Framework的组件,那么这些Spring Framework组件是如何配合工作的呢?本文次要承接上文,向你展现Spring Framework组件的典型利用场景和基于这个场景设计出的简略案例,并以此引出Spring的外围要点,比方IOC和AOP等;在此基础上还引入了不同的配置形式, 如XML,Java配置和注解形式的差别。
Spring根底 - Spring外围之管制反转(IOC)
- 在Spring根底 - Spring简略例子引入Spring的外围中向你展现了IoC的根底含意,同时以此发散了一些IoC相干知识点; 本节将在此基础上进一步解读IOC的含意以及IOC的应用形式
Spring根底 - Spring外围之面向切面编程(AOP)
- 在Spring根底 - Spring简略例子引入Spring的外围中向你展现了AOP的根底含意,同时以此发散了一些AOP相干知识点; 本节将在此基础上进一步解读AOP的含意以及AOP的应用形式。
基于Spring框架和IOC,AOP的根底,为构建下层web利用,须要进一步学习SpringMVC。
Spring根底 - SpringMVC申请流程和案例
- 前文咱们介绍了Spring框架和Spring框架中最为重要的两个技术点(IOC和AOP),那咱们如何更好的构建下层的利用呢(比方web 利用),这便是SpringMVC;Spring MVC是Spring在Spring Container Core和AOP等技术根底上,遵循上述Web MVC的标准推出的web开发框架,目标是为了简化Java栈的web开发。 本文次要介绍SpringMVC的申请流程和根底案例的编写和运行。
Spring进阶 - IoC,AOP以及SpringMVC的源码剖析
Spring进阶 - Spring IOC实现原理详解之IOC体系结构设计
- 在对IoC有了初步的认知后,咱们开始对IOC的实现原理进行深刻了解。本文将帮忙你站在设计者的角度去看IOC最顶层的结构设计
Spring进阶 - Spring IOC实现原理详解之IOC初始化流程
- 上文,咱们看了IOC设计要点和设计构造;紧接着这篇,咱们能够看下源码的实现了:Spring如何实现将资源配置(以xml配置为例)通过加载,解析,生成BeanDefination并注册到IoC容器中的
Spring进阶 - Spring IOC实现原理详解之Bean实例化(生命周期,循环依赖等)
- 上文,咱们看了IOC设计要点和设计构造;以及Spring如何实现将资源配置(以xml配置为例)通过加载,解析,生成BeanDefination并注册到IoC容器中的;容器中寄存的是Bean的定义即BeanDefinition放到beanDefinitionMap中,实质上是一个
ConcurrentHashMap<String, Object>
;并且BeanDefinition接口中蕴含了这个类的Class信息以及是否是单例等。那么如何从BeanDefinition中实例化Bean对象呢,这是本文次要钻研的内容?
- 上文,咱们看了IOC设计要点和设计构造;以及Spring如何实现将资源配置(以xml配置为例)通过加载,解析,生成BeanDefination并注册到IoC容器中的;容器中寄存的是Bean的定义即BeanDefinition放到beanDefinitionMap中,实质上是一个
Spring进阶 - Spring AOP实现原理详解之切面实现
- 前文,咱们剖析了Spring IOC的初始化过程和Bean的生命周期等,而Spring AOP也是基于IOC的Bean加载来实现的。本文次要介绍Spring AOP原理解析的切面实现过程(将切面类的所有切面办法依据应用的注解生成对应Advice,并将Advice连同切入点匹配器和切面类等信息一并封装到Advisor,为后续交给代理加强实现做筹备的过程)。
Spring进阶 - Spring AOP实现原理详解之AOP代理
- 上文咱们介绍了Spring AOP原理解析的切面实现过程(将切面类的所有切面办法依据应用的注解生成对应Advice,并将Advice连同切入点匹配器和切面类等信息一并封装到Advisor)。本文在此基础上持续介绍,代理(cglib代理和JDK代理)的实现过程。
Spring进阶 - Spring AOP实现原理详解之Cglib代理实现
- 咱们在前文中曾经介绍了SpringAOP的切面实现和创立动静代理的过程,那么动静代理是如何工作的呢?本文次要介绍Cglib动静代理的案例和SpringAOP实现的原理。
Spring进阶 - Spring AOP实现原理详解之JDK代理实现
- 上文咱们学习了SpringAOP Cglib动静代理的实现,本文次要是SpringAOP JDK动静代理的案例和实现局部。
Spring进阶 - SpringMVC实现原理之DispatcherServlet初始化的过程
- 前文咱们有了IOC的源码根底以及SpringMVC的根底,咱们便能够进一步深刻了解SpringMVC次要实现原理,蕴含DispatcherServlet的初始化过程和DispatcherServlet解决申请的过程的源码解析。本文是第一篇:DispatcherServlet的初始化过程的源码解析。
Spring进阶 - SpringMVC实现原理之DispatcherServlet解决申请的过程
- 前文咱们有了IOC的源码根底以及SpringMVC的根底,咱们便能够进一步深刻了解SpringMVC次要实现原理,蕴含DispatcherServlet的初始化过程和DispatcherServlet解决申请的过程的源码解析。本文是第二篇:DispatcherServlet解决申请的过程的源码解析。