共计 22403 个字符,预计需要花费 57 分钟才能阅读完成。
上文,咱们看了 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
@ToString
public 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
@Component
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {log.info("execute BeanFactoryPostProcessor#postProcessBeanFactory");
}
}
定义 InstantiationAwareBeanPostProcessor 的实现类
/**
* @author pdai
*/
@Slf4j
@Component
public 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
@Component
public 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
*/
@Configuration
public 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
*/
@Slf4j
public 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 user
12: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 user
12:44:43.237 [main] INFO tech.pdai.springframework.processor.MyInstantiationAwareBeanPostProcessor - execute InstantiationAwareBeanPostProcessor#postProcessProperties for user
12:44:43.242 [main] INFO tech.pdai.springframework.entity.User - execute BeanNameAware#setBeanName
12:44:43.242 [main] INFO tech.pdai.springframework.entity.User - execute BeanFactoryAware#setBeanFactory
12:44:43.242 [main] INFO tech.pdai.springframework.entity.User - execute ApplicationContextAware#setApplicationContext
12:44:43.242 [main] INFO tech.pdai.springframework.processor.MyBeanPostProcessor - execute BeanPostProcessor#postProcessBeforeInitialization for user
12:44:43.242 [main] INFO tech.pdai.springframework.entity.User - execute InitializingBean#afterPropertiesSet
12:44:43.243 [main] INFO tech.pdai.springframework.entity.User - execute User#doInit
12:44:43.243 [main] INFO tech.pdai.springframework.processor.MyBeanPostProcessor - execute BeanPostProcessor#postProcessAfterInitialization for user
12: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 context
12:44:43.276 [SpringContextShutdownHook] INFO tech.pdai.springframework.entity.User - execute DisposableBean#destroy
12: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 解决申请的过程的源码解析。