【一篇搞懂】 bean的生命周期详解
概述
Spring中的一个Bean从生到灭要经历很多过程,总体分为Bean定义、实例化、属性赋值(依赖注入)、初始化、生存期、销毁几个阶段:
下面是一个细化的Bean生命周期图:
过程比较复杂,重点关注Bean的定义、初始化、销毁过程,可以抓住重点:
BeanPostProcessor接口可以对Bean生命周期中的很多部分进行扩展,并且Spring容器中有很多内建的BeanPostProcessor对Spring Bean的功能进行支持。BeanPostProcessor不仅在IOC上发挥了重要作用,在AOP上也发挥了重要的作用。搞懂了Spring内置的BeanPostProcessor的功能,基本上就把Spring Bean的生命周期搞懂了。
还有Spring中的一些基础概念可以参考: 【一篇搞懂】Sping 容器启动过程详解
一、Bean生命周期划分
Spring Bean的生命周期上面图二已经展示,可以主要分为如下4个部分:
- (1)处理BeanDefinition:BeanDefinition的解析,注册,合并
- (2)Bean实例化(Instantiation):还没有生成bean,即没有调用构造函数,生成对象
- (3) Bean属性赋值:查找被@Autowired和@Value标注的方法或属性,注入需要的值
- (4)Bean初始化(Initialization):已经生成bean,进行属性赋值
- (5)Bean销毁:并没有gc
ok,下面就按照这个顺序去捋一下源码。为了方便演示,测试代码如下:
@EnableAspectJAutoProxy
@Configuration
public class AopOneConfig implements DemoInterface{
@Bean
public AopOne aopOne() {
return new AopOne();
}
@Bean
@ConditionalOnBean(name = "aopOne") // 如果aopOne存在才实例化AopOneAspect
public AopOneAspect oneAspect() {
return new AopOneAspect();
}
}
@Test
public void test2() {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AopOneConfig.class);
AopOne bean = applicationContext.getBean(AopOne.class);
bean.compute(10, 1);
}
二、BeanDefinition 处理
spring中的bean,在Java类的基础上增加了很多概念属性,比如scope(作用域),isLazyInit(是否延迟初始化),isSingleton(是否单例)等属性特征。spring就是根据BeanDefinition来实例化对应的bean。 【一篇搞懂】Sping 容器启动过程详解 —— 基本概念
处理BeanDefinition分为三个阶段:BeanDefinition的解析,注册,合并。
2.1 BeanDefinitionReader —— BeanDefinition解析
BeanDefinitionReader
可以将XML、注解等形式的bean配置信息解析读取进来,将其转换为 IoC 容器内部的数据结构:BeanDefinition。它有4个实现类:
AbstractBeanDefinitionReader
:实现了EnvironmentCapable,提供了获取/设置环境的方法。定义了一些通用方法,使用策略模式,将一些具体方法放到子类实现。XmlBeanDefinitionReader
:读取 XML 文件定义的 BeanDefinitionPropertiesBeanDefinitionReader
:可以从属性文件,Resource,Property 对象等读取 BeanDefinitionGroovyBeanDefinitionReader
:可以读取 Groovy 语言定义的 Bean
我们的测试代码使用的是AnnotatedBeanDefinitionReader
,但 AnnotatedBeanDefinitionReader
并不是 BeanDefinitionReader
的实现类,它没有继承任何类。在AnnotationConfigApplicationContext
中使用到,AnnotatedBeanDefinitionReader
的构造方法中参数为BeanDefinitionRegistry
。它的重要方法是register,用于获取一个或多个带有注解的具体类,之后将他们解析为BeanDefintion,之后注册到Registry中。
测试代码中用到的 AnnotatedBeanDefinitionReader
的构造方法如下:
/**
* Create a new {@code AnnotatedBeanDefinitionReader} for the given registry and using
* the given {@link Environment}.
* @param registry the {@code BeanFactory} to load bean definitions into,
* in the form of a {@code BeanDefinitionRegistry}
* @param environment the {@code Environment} to use when evaluating bean definition
* profiles.
* @since 3.1
*/
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
Assert.notNull(environment, "Environment must not be null");
this.registry = registry;
this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);
AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
}
这个构造方法中,new 了一个 ConditionEvaluator
,这个是条件解析器,那你肯定想到了 @Conditional
相关一系列注解(@ConditionalOnBean / @ConditionalOnClass
…),而这些条件注解的解析就是ConditionEvaluator
。
AnnotationConfigUtils.registerAnnotationConfigProcessors
则是提前注入一些后置处理器。通过该方法之后, beanFactory中就存在了6个bd。当然这里仅是生成了后置处理器的BeanDefinition。
2.2 BeanDefinitionRegistry—— BeanDefinition注册
配置通过 BeanDefinitionReader
被解析成BeanDefinition后,会被注册到 BeanDefinitionRegistry
。所谓的注册其实就是用各种容器去保存相应的信息的过程。
BeanDefinitionRegistry
基本实现就是 DefaultListableBeanFactory
,DefaultListableBeanFactory
中和BeanDefinition相关的属性如下:
beanDefinitionMap用来保存beanName和BeanDefinition的映射关系 因为map不能保存bean放进来的顺序,所以增加了一个beanDefinitionNames来保存bean的顺序。
2.3 MergedBeanDefinition—— BeanDefinition合并
两个有继承关系的bean就会涉及BeanDefinition的合并。比如有2个对象User和Student,Student继承自User:
User(id=1, name=zhang)
Student(super=User(id=1, name=zhang), age=10, description=xml)
从容器中获取这2个对象时,属性如下,可以看到 Student 把 User 对象的属性继承过来了,这种情况就涉及到BeanDefinition的合并。在最开始的时候User和Student都是 GenericBeanDefinition
,当进行完合并的时候会变成RootBeanDefinition
。
这点在 【一篇搞懂】Sping 容器启动过程详解 详细说明过。
三、Bean实例化
实例化就是找到相应的构造方法去生成实例的过程。可以分为实例化前、实例化、实例化后三个阶段。
3.1 实例化前
InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation
以我们的测试类为例,在 refresh
#finishBeanFactoryInitialization
#preInstantiateSingletons
是在容器启动阶段实例化容器中所有的非懒加载的单例bean,我们来看看实例化前的操作,完整的调用链路如下:
refresh
#finishBeanFactoryInitialization
#preInstantiateSingletons
#getBean
#doGetBean
#createBean
#resolveBeforeInstantiation
#applyBeanPostProcessorsBeforeInstantiation#postProcessBeforeInstantiation
/**
* Central method of this class: creates a bean instance,
* populates the bean instance, applies post-processors, etc.
* @see #doCreateBean
*/
@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
if (logger.isTraceEnabled()) {
logger.trace("Creating instance of bean '" + beanName + "'");
}
RootBeanDefinition mbdToUse = mbd;
// Make sure bean class is actually resolved at this point, and
// clone the bean definition in case of a dynamically resolved Class
// which cannot be stored in the shared merged bean definition.
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
mbdToUse = new RootBeanDefinition(mbd);
mbdToUse.setBeanClass(resolvedClass);
}
// Prepare method overrides.
try {
mbdToUse.prepareMethodOverrides();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
beanName, "Validation of method overrides failed", ex);
}
try {
// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
}
catch (Throwable ex) {
throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
"BeanPostProcessor before instantiation of bean failed", ex);
}
try {
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
if (logger.isTraceEnabled()) {
logger.trace("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;
}
catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
// A previously detected exception with proper bean creation context already,
// or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.
throw ex;
}
catch (Throwable ex) {
throw new BeanCreationException(
mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
}
}
上面的方法主要完成创建一个 bean 实例,填充 bean 实例,应用后处理器等。
/**
* Apply before-instantiation post-processors, resolving whether there is a
* before-instantiation shortcut for the specified bean.
* @param beanName the name of the bean
* @param mbd the bean definition for the bean
* @return the shortcut-determined bean instance, or {@code null} if none
*/
@Nullable
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
Object bean = null;
// 如果尚未被解析
if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
// Make sure bean class is actually resolved at this point.
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
Class<?> targetType = determineTargetType(beanName, mbd);
if (targetType != null) {
bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
if (bean != null) {
bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
}
}
}
mbd.beforeInstantiationResolved = (bean != null);
}
return bean;
}
resolveBeforeInstantiation
方法对BeanDefinigiton中的属性做些前置处理。
/**
* Apply InstantiationAwareBeanPostProcessors to the specified bean definition
* (by class and name), invoking their {@code postProcessBeforeInstantiation} methods.
* <p>Any returned object will be used as the bean instead of actually instantiating
* the target bean. A {@code null} return value from the post-processor will
* result in the target bean being instantiated.
* @param beanClass the class of the bean to be instantiated
* @param beanName the name of the bean
* @return the bean object to use instead of a default instance of the target bean, or {@code null}
* @see InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation
*/
@Nullable
protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
if (result != null) {
return result;
}
}
}
return null;
}
/**
* Apply this BeanPostProcessor <i>before the target bean gets instantiated</i>.
* The returned bean object may be a proxy to use instead of the target bean,
* effectively suppressing default instantiation of the target bean.
* <p>If a non-null object is returned by this method, the bean creation process
* will be short-circuited. The only further processing applied is the
* {@link #postProcessAfterInitialization} callback from the configured
* {@link BeanPostProcessor BeanPostProcessors}.
* <p>This callback will only be applied to bean definitions with a bean class.
* In particular, it will not be applied to beans with a factory method.
* <p>Post-processors may implement the extended
* {@link SmartInstantiationAwareBeanPostProcessor} interface in order
* to predict the type of the bean object that they are going to return here.
* <p>The default implementation returns {@code null}.
* @param beanClass the class of the bean to be instantiated
* @param beanName the name of the bean
* @return the bean object to expose instead of a default instance of the target bean,
* or {@code null} to proceed with default instantiation
* @throws org.springframework.beans.BeansException in case of errors
* @see #postProcessAfterInstantiation
* @see org.springframework.beans.factory.support.AbstractBeanDefinition#hasBeanClass
*/
@Nullable
default Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
return null;
}
InstantiationAwareBeanPostProcessor
接口的 postProcessBeforeInstantiation
有很多实现,我们测试代码的具体实现是 AbstractAutoProxyCreator
:
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
Object cacheKey = getCacheKey(beanClass, beanName);
if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
if (this.advisedBeans.containsKey(cacheKey)) {
return null;
}
if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return null;
}
}
// Create proxy here if we have a custom TargetSource.
// Suppresses unnecessary default instantiation of the target bean:
// The TargetSource will handle target instances in a custom fashion.
TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
if (targetSource != null) {
if (StringUtils.hasLength(beanName)) {
this.targetSourcedBeans.add(beanName);
}
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
return null;
}
上面的代码我们解析下:
(1)isInfrastructureClass
/**
* Return whether the given bean class represents an infrastructure class
* that should never be proxied.
* <p>The default implementation considers Advices, Advisors and
* AopInfrastructureBeans as infrastructure classes.
* @param beanClass the class of the bean
* @return whether the bean represents an infrastructure class
*/
protected boolean isInfrastructureClass(Class<?> beanClass) {
boolean retVal = Advice.class.isAssignableFrom(beanClass) ||
Pointcut.class.isAssignableFrom(beanClass) ||
Advisor.class.isAssignableFrom(beanClass) ||
AopInfrastructureBean.class.isAssignableFrom(beanClass);
if (retVal && logger.isTraceEnabled()) {
logger.trace("Did not attempt to auto-proxy infrastructure class [" + beanClass.getName() + "]");
}
return retVal;
}
这个方法判断传入的类是不是Advice/Pointcut/Advisor/AopInfrastructureBean的类或子类。
(2)shouldSkip
@Override
protected boolean shouldSkip(Class<?> beanClass, String beanName) {
// TODO: Consider optimization by caching the list of the aspect names
List<Advisor> candidateAdvisors = findCandidateAdvisors();
for (Advisor advisor : candidateAdvisors) {
if (advisor instanceof AspectJPointcutAdvisor &&
((AspectJPointcutAdvisor) advisor).getAspectName().equals(beanName)) {
return true;
}
}
return super.shouldSkip(beanClass, beanName);
}
先获取所有候选的Advisor,我们的测试代码有5个通知,for循环里面,如果beanName为AspectJPointAdvisor直接返回true。一般这个方法都返回false,即不该跳过整体的方法,继续执行下面的流程。
(3)getCustomTargetSource
/**
* Create a target source for bean instances. Uses any TargetSourceCreators if set.
* Returns {@code null} if no custom TargetSource should be used.
* <p>This implementation uses the "customTargetSourceCreators" property.
* Subclasses can override this method to use a different mechanism.
* @param beanClass the class of the bean to create a TargetSource for
* @param beanName the name of the bean
* @return a TargetSource for this bean
*/
@Nullable
protected TargetSource getCustomTargetSource(Class<?> beanClass, String beanName) {
// We can't create fancy target sources for directly registered singletons.
if (this.customTargetSourceCreators != null &&
this.beanFactory != null && this.beanFactory.containsBean(beanName)) {
for (TargetSourceCreator tsc : this.customTargetSourceCreators) {
TargetSource ts = tsc.getTargetSource(beanClass, beanName);
if (ts != null) {
// Found a matching TargetSource.
if (logger.isTraceEnabled()) {
logger.trace("TargetSourceCreator [" + tsc +
"] found custom TargetSource for bean with name '" + beanName + "'");
}
return ts;
}
}
}
// No custom TargetSource found.
return null;
}
如果有配置TargetSource,则使用TargetSource定义的规则生成bean的代理。
3.2 实例化
SmartInstantiationAwareBeanPostProcessor
# determineCandidateConstructors
前面在实例化之前,我们是从 createBean
这个方法出发的,它里面的 resolveBeforeInstantiation
方法是在做实例化前的操作的,往下走就开始实例化操作,主要的方法是 doCreateBean
,完整的调用链如下 :refresh
#finishBeanFactoryInitialization
#preInstantiateSingletons
#getBean
#doGetBean
#createBean
#doCreateBean
#createBeanInstance
/**
* Create a new instance for the specified bean, using an appropriate instantiation strategy:
* factory method, constructor autowiring, or simple instantiation.
* @param beanName the name of the bean
* @param mbd the bean definition for the bean
* @param args explicit arguments to use for constructor or factory method invocation
* @return a BeanWrapper for the new instance
* @see #obtainFromSupplier
* @see #instantiateUsingFactoryMethod
* @see #autowireConstructor
* @see #instantiateBean
*/
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
// Make sure bean class is actually resolved at this point.
Class<?> beanClass = resolveBeanClass(mbd, beanName);
if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
}
Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
if (instanceSupplier != null) {
return obtainFromSupplier(instanceSupplier, beanName);
}
if (mbd.getFactoryMethodName() != null) {
return instantiateUsingFactoryMethod(beanName, mbd, args);
}
// Shortcut when re-creating the same bean...
boolean resolved = false;
boolean autowireNecessary = false;
if (args == null) {
synchronized (mbd.constructorArgumentLock) {
if (mbd.resolvedConstructorOrFactoryMethod != null) {
resolved = true;
autowireNecessary = mbd.constructorArgumentsResolved;
}
}
}
if (resolved) {
if (autowireNecessary) {
return autowireConstructor(beanName, mbd, null, null);
}
else {
return instantiateBean(beanName, mbd);
}
}
// Candidate constructors for autowiring?
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
return autowireConstructor(beanName, mbd, ctors, args);
}
// Preferred constructors for default construction?
ctors = mbd.getPreferredConstructors();
if (ctors != null) {
return autowireConstructor(beanName, mbd, ctors, null);
}
// No special handling: simply use no-arg constructor.
return instantiateBean(beanName, mbd);
}
上面的代码就是实例化bean的过程,方法的注释告诉我们实例化一个bean有很多方式:
InstanceSupplier
如果bean定义中存在 InstanceSupplier ,会使用这个回调接口创建对象- 通过工厂方法创建,根据配置的factoryMethodName或factory-mtehod创建bean
- 解析构造方法并进行实例化。
其中构造函数比较麻烦点,因为一个bean可能有多个构造器,所以需要根据配置文件中配置的参数或者传入的参数确定最终的构造器。并且Spring会将解析、确定好的构造函数缓存到BeanDefinition中的resolvedConstructorOrFactoryMethod
字段中。在下次创建相同bean的时候,会直接从RootBeanDefinition
中的属性resolvedConstructorOrFactoryMethod
缓存的值获取,避免再次解析。
3.2.1 obtainFromSupplier
/**
* Obtain a bean instance from the given supplier.
* @param instanceSupplier the configured supplier
* @param beanName the corresponding bean name
* @return a BeanWrapper for the new instance
* @since 5.0
*/
protected BeanWrapper obtainFromSupplier(Supplier<?> instanceSupplier, String beanName) {
Object instance;
String outerBean = this.currentlyCreatedBean.get();
this.currentlyCreatedBean.set(beanName);
try {
instance = instanceSupplier.get();
}
finally {
if (outerBean != null) {
this.currentlyCreatedBean.set(outerBean);
}
else {
this.currentlyCreatedBean.remove();
}
}
if (instance == null) {
instance = new NullBean();
}
BeanWrapper bw = new BeanWrapperImpl(instance);
initBeanWrapper(bw);
return bw;
}
AbstractBeandefinition
中有个 instanceSupplier
属性:
/**
* Specify a callback for creating an instance of the bean,
* as an alternative to a declaratively specified factory method.
* <p>If such a callback is set, it will override any other constructor
* or factory method metadata. However, bean property population and
* potential annotation-driven injection will still apply as usual.
* @since 5.0
*/
public void setInstanceSupplier(@Nullable Supplier<?> instanceSupplier) {
this.instanceSupplier = instanceSupplier;
}
根据其set方法的解释:就是替代工厂方法(包含静态工厂)或者构造器创建对象。
按照上面 createBeanInstance
方法的逻辑,这种实例化方式是优先考虑的、优先执行的。
为什么?
原因是:不管是静态工厂还是工厂方法,都需要通过反射调用目标方法创建对象,反射或多或少影响性能。而 instanceSupplier
不需要通过反射了,而是调用之前就set好的创建bean的方法。
例如我们个Address这个类提前设置好实例化方法并注入spring容器:
@ToString
@Getter
@Setter
@AllArgsConstructor
public class Address {
private String tel;
private String dec;
}
public class SupplierTest {
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
RootBeanDefinition beanDefinition = new RootBeanDefinition();
beanDefinition.setBeanClass(Address.class);
beanDefinition.setInstanceSupplier(SupplierTest::getAddress);
applicationContext.registerBeanDefinition(Address.class.getSimpleName(), beanDefinition);
applicationContext.refresh();
System.out.println(applicationContext.getBean(Address.class).toString());
}
private static Address getAddress() {
return new Address("18888888", "地球");
}
}
Address(tel=18888888, dec=地球)
上面的这个测试方法也会走到 obtainFromSupplier
里面,打个断点看下:
这里很有意思,instanceSupplier
的值就是我们自己注入的Address的实例化方法,中间的 “::” 双冒号还被转成了lambda 。。。
再进入 obtainFromSupplier
中:
这里 instance = instanceSupplier.get()
再进去看看:
这个get方法调用的就是 上面的我们自己写的方法。
3.2.2 instantiateUsingFactoryMethod
/**
* Instantiate the bean using a named factory method. The method may be static, if the
* mbd parameter specifies a class, rather than a factoryBean, or an instance variable
* on a factory object itself configured using Dependency Injection.
* @param beanName the name of the bean
* @param mbd the bean definition for the bean
* @param explicitArgs argument values passed in programmatically via the getBean method,
* or {@code null} if none (-> use constructor argument values from bean definition)
* @return a BeanWrapper for the new instance
*/
protected BeanWrapper instantiateUsingFactoryMethod(
String beanName, RootBeanDefinition mbd, @Nullable Object[] explicitArgs) {
return new ConstructorResolver(this).instantiateUsingFactoryMethod(beanName, mbd, explicitArgs);
}
/**
* Instantiate the bean using a named factory method. The method may be static, if the
* bean definition parameter specifies a class, rather than a "factory-bean", or
* an instance variable on a factory object itself configured using Dependency Injection.
* <p>Implementation requires iterating over the static or instance methods with the
* name specified in the RootBeanDefinition (the method may be overloaded) and trying
* to match with the parameters. We don't have the types attached to constructor args,
* so trial and error is the only way to go here. The explicitArgs array may contain
* argument values passed in programmatically via the corresponding getBean method.
* @param beanName the name of the bean
* @param mbd the merged bean definition for the bean
* @param explicitArgs argument values passed in programmatically via the getBean
* method, or {@code null} if none (-> use constructor argument values from bean definition)
* @return a BeanWrapper for the new instance
*/
public BeanWrapper instantiateUsingFactoryMethod(
String beanName, RootBeanDefinition mbd, @Nullable Object[] explicitArgs) {
BeanWrapperImpl bw = new BeanWrapperImpl();
// 初始化BeanWrapperImpl 向BeanWrapper对象中添加ConversionService对象和属性编辑器PropertyEditor对象
this.beanFactory.initBeanWrapper(bw);
// 获得factoryBean、factoryClass、isStatic、factoryBeanName属性
Object factoryBean;
Class<?> factoryClass;
boolean isStatic;
String factoryBeanName = mbd.getFactoryBeanName();
if (factoryBeanName != null) {
// 如果工厂名和beanName相等,则抛出BeanDefinitionStoreException异常
if (factoryBeanName.equals(beanName)) {
throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName,
"factory-bean reference points back to the same bean definition");
}
// 获取工厂实例
factoryBean = this.beanFactory.getBean(factoryBeanName);
// 如果是单例模式,并且已经缓存中已经存在beanName则抛出异常
if (mbd.isSingleton() && this.beanFactory.containsSingleton(beanName)) {
throw new ImplicitlyAppearedSingletonException();
}
factoryClass = factoryBean.getClass();
isStatic = false;
}
else {
// 工厂名为空,则其可能是一个静态工厂
// 静态工厂创建bean,必须要提供工厂的全类名
// It's a static factory method on the bean class.
if (!mbd.hasBeanClass()) {
throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName,
"bean definition declares neither a bean class nor a factory-bean reference");
}
factoryBean = null;
factoryClass = mbd.getBeanClass();
isStatic = true;
}
// 获得factoryMethodToUse、argsHolderToUse、argsToUse属性
Method factoryMethodToUse = null;
ArgumentsHolder argsHolderToUse = null;
Object[] argsToUse = null;
// 如果指定了构造参数则直接使用
// 在调用getBean方法的时候指定方法参数
if (explicitArgs != null) {
argsToUse = explicitArgs;
}
else {
// 没有指定,则尝试从配置文件中解析
Object[] argsToResolve = null;
synchronized (mbd.constructorArgumentLock) {
// 获取缓存中的构造函数或者工厂方法
factoryMethodToUse = (Method) mbd.resolvedConstructorOrFactoryMethod;
if (factoryMethodToUse != null && mbd.constructorArgumentsResolved) {
// 获取缓存中的构造参数
// Found a cached factory method...
argsToUse = mbd.resolvedConstructorArguments;
if (argsToUse == null) {
argsToResolve = mbd.preparedConstructorArguments;
}
}
}
// 缓存中存在,则解析存储在BeanDefinition中的参数
// 如给定方法的构造函数 f(int ,int),通过此方法后就会把配置文件中的("1","1")转换为(1,1)
// 缓存中的值可能是原始值,也可能是最终值
if (argsToResolve != null) {
argsToUse = resolvePreparedArguments(beanName, mbd, bw, factoryMethodToUse, argsToResolve, true);
}
}
if (factoryMethodToUse == null || argsToUse == null) {
// Need to determine the factory method...
// Try all methods with this name to see if they match the given arguments.
// 获取工厂方法的类的全类名
factoryClass = ClassUtils.getUserClass(factoryClass);
// 如果工厂方法为空,则通过getCandidateMethods获取所有的待定方法
Method[] rawCandidates = getCandidateMethods(factoryClass, mbd);
List<Method> candidateList = new ArrayList<>();
for (Method candidate : rawCandidates) {
// 查找到与工厂方法同名的候选方法,没有@Bean的同名方法不被考虑
if (Modifier.isStatic(candidate.getModifiers()) == isStatic && mbd.isFactoryMethod(candidate)) {
candidateList.add(candidate);
}
}
// 通过工厂方法创建bean
if (candidateList.size() == 1 && explicitArgs == null && !mbd.hasConstructorArgumentValues()) {
Method uniqueCandidate = candidateList.get(0);
if (uniqueCandidate.getParameterCount() == 0) {
mbd.factoryMethodToIntrospect = uniqueCandidate;
synchronized (mbd.constructorArgumentLock) {
mbd.resolvedConstructorOrFactoryMethod = uniqueCandidate;
mbd.constructorArgumentsResolved = true;
mbd.resolvedConstructorArguments = EMPTY_ARGS;
}
bw.setBeanInstance(instantiate(beanName, mbd, factoryBean, uniqueCandidate, EMPTY_ARGS));
return bw;
}
}
Method[] candidates = candidateList.toArray(new Method[0]);
// 排序构造函数
// public构造函数优先参数数量降序,非public构造函数参数数量降序
AutowireUtils.sortFactoryMethods(candidates);
// 用于承载解析后的构造函数参数的值
ConstructorArgumentValues resolvedValues = null;
boolean autowiring = (mbd.getResolvedAutowireMode() == AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR);
int minTypeDiffWeight = Integer.MAX_VALUE;
Set<Method> ambiguousFactoryMethods = null;
int minNrOfArgs;
if (explicitArgs != null) {
minNrOfArgs = explicitArgs.length;
}
else {
// We don't have arguments passed in programmatically, so we need to resolve the
// arguments specified in the constructor arguments held in the bean definition.
// getBean没有传递参数,则需要解析保存在BeanDefinition构造函数中指定的参数
if (mbd.hasConstructorArgumentValues()) {
// 构造函数参数
ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
resolvedValues = new ConstructorArgumentValues();
// 解析构造函数参数
// 将bean的构造函数解析为resolvedValues对象,其中会涉及到其他的bean
minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
}
else {
minNrOfArgs = 0;
}
}
// 记录UnsatisfiedDependencyException异常集合
LinkedList<UnsatisfiedDependencyException> causes = null;
for (Method candidate : candidates) {
Class<?>[] paramTypes = candidate.getParameterTypes();
if (paramTypes.length >= minNrOfArgs) {
ArgumentsHolder argsHolder;
if (explicitArgs != null) {
// Explicit arguments given -> arguments length must match exactly.
// 显示给定参数,参数长度必须完全匹配
if (paramTypes.length != explicitArgs.length) {
continue;
}
// 根据参数创建参数持有者ArgumentsHolder对象
argsHolder = new ArgumentsHolder(explicitArgs);
}
else {
// 根据提供的参数,解析构造函数
// Resolved constructor arguments: type conversion and/or autowiring necessary.
try {
String[] paramNames = null;
// 获取ParameterNameDiscoverer对象
// ParameterNameDiscoverer用于解析方法和构造函数的参数名,为参数名称探测器
ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();
// 获取指定构造函数的参数名
if (pnd != null) {
paramNames = pnd.getParameterNames(candidate);
}
// 在已解析构造函数参数值的情况下,创建一个参数持有者ArgumentsHolder对象
argsHolder = createArgumentArray(beanName, mbd, resolvedValues, bw,
paramTypes, paramNames, candidate, autowiring, candidates.length == 1);
}
catch (UnsatisfiedDependencyException ex) {
if (logger.isTraceEnabled()) {
logger.trace("Ignoring factory method [" + candidate + "] of bean '" + beanName + "': " + ex);
}
// Swallow and try next overloaded factory method.
if (causes == null) {
causes = new LinkedList<>();
}
// 发生UnsatisfiedDependencyException异常,添加到causes中
causes.add(ex);
continue;
}
}
// isLenientConstructorResolution判断解析构造函数的时候是否以宽松模式还是严格模式
// 宽松模式:使用具有"最接近的模式"进行匹配
// 严格模式:解析构造函数时,必须所有的都需要匹配,否则抛出异常
int typeDiffWeight = (mbd.isLenientConstructorResolution() ?
argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes));
// Choose this factory method if it represents the closest match.
// 代表最接近的类型匹配,选择作为构造函数
if (typeDiffWeight < minTypeDiffWeight) {
factoryMethodToUse = candidate;
argsHolderToUse = argsHolder;
argsToUse = argsHolder.arguments;
minTypeDiffWeight = typeDiffWeight;
ambiguousFactoryMethods = null;
}
// Find out about ambiguity: In case of the same type difference weight
// for methods with the same number of parameters, collect such candidates
// and eventually raise an ambiguity exception.
// However, only perform that check in non-lenient constructor resolution mode,
// and explicitly ignore overridden methods (with the same parameter signature).
// 如果具有相同参数数量的方法具有相同的类型差异权重,则收集此类型选项
// 但是仅在非宽松模式构造函数解析模式下执行该检查,并显示忽略重写方法(具有相同的参数签名)
else if (factoryMethodToUse != null && typeDiffWeight == minTypeDiffWeight &&
!mbd.isLenientConstructorResolution() &&
paramTypes.length == factoryMethodToUse.getParameterCount() &&
!Arrays.equals(paramTypes, factoryMethodToUse.getParameterTypes())) {
// 查找多个可匹配的方法
if (ambiguousFactoryMethods == null) {
ambiguousFactoryMethods = new LinkedHashSet<>();
ambiguousFactoryMethods.add(factoryMethodToUse);
}
ambiguousFactoryMethods.add(candidate);
}
}
}
// 没有可执行的工厂方法,则抛出异常
if (factoryMethodToUse == null) {
if (causes != null) {
UnsatisfiedDependencyException ex = causes.removeLast();
for (Exception cause : causes) {
this.beanFactory.onSuppressedException(cause);
}
throw ex;
}
List<String> argTypes = new ArrayList<>(minNrOfArgs);
if (explicitArgs != null) {
for (Object arg : explicitArgs) {
argTypes.add(arg != null ? arg.getClass().getSimpleName() : "null");
}
}
else if (resolvedValues != null) {
Set<ValueHolder> valueHolders = new LinkedHashSet<>(resolvedValues.getArgumentCount());
valueHolders.addAll(resolvedValues.getIndexedArgumentValues().values());
valueHolders.addAll(resolvedValues.getGenericArgumentValues());
for (ValueHolder value : valueHolders) {
String argType = (value.getType() != null ? ClassUtils.getShortName(value.getType()) :
(value.getValue() != null ? value.getValue().getClass().getSimpleName() : "null"));
argTypes.add(argType);
}
}
String argDesc = StringUtils.collectionToCommaDelimitedString(argTypes);
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"No matching factory method found: " +
(mbd.getFactoryBeanName() != null ?
"factory bean '" + mbd.getFactoryBeanName() + "'; " : "") +
"factory method '" + mbd.getFactoryMethodName() + "(" + argDesc + ")'. " +
"Check that a method with the specified name " +
(minNrOfArgs > 0 ? "and arguments " : "") +
"exists and that it is " +
(isStatic ? "static" : "non-static") + ".");
}
else if (void.class == factoryMethodToUse.getReturnType()) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Invalid factory method '" + mbd.getFactoryMethodName() +
"': needs to have a non-void return type!");
}
else if (ambiguousFactoryMethods != null) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Ambiguous factory method matches found in bean '" + beanName + "' " +
"(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities): " +
ambiguousFactoryMethods);
}
// 将解析的构造函数加入缓存
if (explicitArgs == null && argsHolderToUse != null) {
mbd.factoryMethodToIntrospect = factoryMethodToUse;
argsHolderToUse.storeCache(mbd, factoryMethodToUse);
}
}
Assert.state(argsToUse != null, "Unresolved factory method arguments");
// 创建bean对象,并设置到BeanWrapperImpl中
bw.setBeanInstance(instantiate(beanName, mbd, factoryBean, factoryMethodToUse, argsToUse));
return bw;
}
instantiateUsingFactoryMethod
太长了,要实现的是使用工厂方法实例化 bean。具体的注释已在代码上进行了添加。先打个断点:
可以看到 factoryBeanName
和 beanName
的值,那这个长方法的前面一部分的意图就很好了解了。
- 首先,如果
factoryBeanName
与beanName
一样,则抛出BeanDefinitionStoreException
异常 - 然后,通过
DefaultListableBeanFactory
的getBean
方法获取工厂实例对象(factoryBean) - 若要实例化的bean为单例模式,且
this.singletonObjects.containsKey(beanName)
,即已经缓存了这个bean,则抛出异常。因为单例模式下且缓存中存在是不需要再次创建bean对象的,单例模式的bean只会实例化一次。
工厂对象确认后,需确认构造参数。断点往下走,接着往下看:
怎么确认构造参数呢?首先,explicitArgs
是调用 getBean
方法的入参,如果该参数不为null,则可以确定构造函数的参数就是它了。所以,如果 explicitArgs
存在,则直接使用该参数。
接下来,若没有传入构造参数,那就要去Definition缓存中看看有没有,即解析存储在给定 bean 定义中的准备好的参数。也就是如果 argsToResolve
不为空,则对构造函数参数进行解析,通过 resolvePreparedArguments
进行转换:
/**
* Resolve the prepared arguments stored in the given bean definition.
*/
private Object[] resolvePreparedArguments(String beanName, RootBeanDefinition mbd, BeanWrapper bw,
Executable executable, Object[] argsToResolve, boolean fallback) {
TypeConverter customConverter = this.beanFactory.getCustomTypeConverter();
TypeConverter converter = (customConverter != null ? customConverter : bw);
BeanDefinitionValueResolver valueResolver =
new BeanDefinitionValueResolver(this.beanFactory, beanName, mbd, converter);
Class<?>[] paramTypes = executable.getParameterTypes();
// 保存解析后的参数
Object[] resolvedArgs = new Object[argsToResolve.length];
// 遍历缓存中获取到的每一个构造方法的参数
for (int argIndex = 0; argIndex < argsToResolve.length; argIndex++) {
Object argValue = argsToResolve[argIndex];
// 为给定的方法或构造函数创建一个新的 MethodParameter。这是一个方便的工厂方法,适用于以通用方式处理方法或构造函数引用的场景。
MethodParameter methodParam = MethodParameter.forExecutable(executable, argIndex);
GenericTypeResolver.resolveParameterType(methodParam, executable.getDeclaringClass());
if (argValue instanceof AutowiredArgumentMarker) {
argValue = resolveAutowiredArgument(methodParam, beanName, null, converter, fallback);
}
else if (argValue instanceof BeanMetadataElement) {
argValue = valueResolver.resolveValueIfNecessary("constructor argument", argValue);
}
else if (argValue instanceof String) {
argValue = this.beanFactory.evaluateBeanDefinitionString((String) argValue, mbd);
}
Class<?> paramType = paramTypes[argIndex];
try {
resolvedArgs[argIndex] = converter.convertIfNecessary(argValue, paramType, methodParam);
}
catch (TypeMismatchException ex) {
throw new UnsatisfiedDependencyException(
mbd.getResourceDescription(), beanName, new InjectionPoint(methodParam),
"Could not convert argument value of type [" + ObjectUtils.nullSafeClassName(argValue) +
"] to required type [" + paramType.getName() + "]: " + ex.getMessage());
}
}
return resolvedArgs;
}
由于缓存中的值可能是最终值,也可能不是最终值。比如构造函数中的类型为Integer类型的1,但缓存中的类型有可能是String类型的"1",所以即便是从缓存中得到了构造参数,也需要经过一番的类型转换才能确保参数类型完全对应。例如:给定方法的构造函数 A(int,int)则通过上面的方法就会把配置中的(“1”,“1”)转换为(1,1) 。
如果缓存不存在呢,则需要解析构造函数参数,以确定使用哪一个构造函数来进行实例化:
可以看到 getCandidateMethods
方法把 factoryClass
的所有方法都获取到了。通过循环过滤,最后把不是static修饰且与beanName相同的候选方法留下来,也就是对应的构造方法,放入 candidateList
中:
有了这个构造方法,接下来就是实例化了,方法是 instantiate
:
private Object instantiate(String beanName, RootBeanDefinition mbd,
@Nullable Object factoryBean, Method factoryMethod, Object[] args) {
try {
if (System.getSecurityManager() != null) {
return AccessController.doPrivileged((PrivilegedAction<Object>) () ->
this.beanFactory.getInstantiationStrategy().instantiate(
mbd, beanName, this.beanFactory, factoryBean, factoryMethod, args),
this.beanFactory.getAccessControlContext());
}
else {
return this.beanFactory.getInstantiationStrategy().instantiate(
mbd, beanName, this.beanFactory, factoryBean, factoryMethod, args);
}
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Bean instantiation via factory method failed", ex);
}
}
@Override
public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner,
@Nullable Object factoryBean, final Method factoryMethod, Object... args) {
try {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
ReflectionUtils.makeAccessible(factoryMethod);
return null;
});
}
else {
ReflectionUtils.makeAccessible(factoryMethod);
}
Method priorInvokedFactoryMethod = currentlyInvokedFactoryMethod.get();
try {
currentlyInvokedFactoryMethod.set(factoryMethod);
Object result = factoryMethod.invoke(factoryBean, args);
if (result == null) {
result = new NullBean();
}
return result;
}
finally {
if (priorInvokedFactoryMethod != null) {
currentlyInvokedFactoryMethod.set(priorInvokedFactoryMethod);
}
else {
currentlyInvokedFactoryMethod.remove();
}
}
}
catch (IllegalArgumentException ex) {
throw new BeanInstantiationException(factoryMethod,
"Illegal arguments to factory method '" + factoryMethod.getName() + "'; " +
"args: " + StringUtils.arrayToCommaDelimitedString(args), ex);
}
catch (IllegalAccessException ex) {
throw new BeanInstantiationException(factoryMethod,
"Cannot access factory method '" + factoryMethod.getName() + "'; is it public?", ex);
}
catch (InvocationTargetException ex) {
String msg = "Factory method '" + factoryMethod.getName() + "' threw exception";
if (bd.getFactoryBeanName() != null && owner instanceof ConfigurableBeanFactory &&
((ConfigurableBeanFactory) owner).isCurrentlyInCreation(bd.getFactoryBeanName())) {
msg = "Circular reference involving containing bean '" + bd.getFactoryBeanName() + "' - consider " +
"declaring the factory method as static for independence from its containing instance. " + msg;
}
throw new BeanInstantiationException(factoryMethod, msg, ex.getTargetException());
}
}
上面的过程说的是如果在缓存中未到构造参数,则尝试通过native方法获取工厂方法类的全类名,如果得到工厂方法只有一个时,则通过instantiate方法实例化bean,然后注入到BeanWrapperImpl中,直接返回。result就是实例化的结果。
3.2.3 解析在 bean 定义中保存的构造函数参数中指定的参数,确定构造参数
We don’t have arguments passed in programmatically, so we need to resolve the arguments specified in the constructor arguments held in the bean definition.
也就是没有传入的参数,我们就需要解析在 bean 定义中保存的构造函数参数中指定的参数。
Method[] candidates = candidateList.toArray(new Method[0]);
AutowireUtils.sortFactoryMethods(candidates);
ConstructorArgumentValues resolvedValues = null;
boolean autowiring = (mbd.getResolvedAutowireMode() == AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR);
int minTypeDiffWeight = Integer.MAX_VALUE;
Set<Method> ambiguousFactoryMethods = null;
int minNrOfArgs;
if (explicitArgs != null) {
// 如果入参中带有构造参数,则直接获取构造参数的个数
minNrOfArgs = explicitArgs.length;
}
else {
// We don't have arguments passed in programmatically, so we need to resolve the
// arguments specified in the constructor arguments held in the bean definition.
if (mbd.hasConstructorArgumentValues()) {
ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
resolvedValues = new ConstructorArgumentValues();
minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
}
else {
minNrOfArgs = 0;
}
}
上面因为有多个工厂方法,所以:
- 首先对工厂方法进行排序,排序规则:public工厂方法优先,参数数量降序,然后非public工厂方法优先,参数数量降序。
- 如果入参中带有构造参数,则直接获取构造参数的个数。
- 否则需从BeanDefinition中获取构造函数,并进行解析。
- 然后通过resolveConstructorArguments解析构造函数,返回构造参数的最小个数。
3.2.4 确定构造方法
for (Method candidate : candidates) {
Class<?>[] paramTypes = candidate.getParameterTypes();
if (paramTypes.length >= minNrOfArgs) {
// 保存参数对象
ArgumentsHolder argsHolder;
if (explicitArgs != null) {
// 参数长度必须完全匹配
if (paramTypes.length != explicitArgs.length) {
continue;
}
argsHolder = new ArgumentsHolder(explicitArgs);
}
else {
// Resolved constructor arguments: type conversion and/or autowiring necessary.
// 根据提供的参数,解析构造函数
try {
String[] paramNames = null;
// ParameterNameDiscoverer用于解析方法和构造函数的参数名,为参数名称探测器
ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();
// 获取指定构造函数的参数名
if (pnd != null) {
paramNames = pnd.getParameterNames(candidate);
}
// 在已解析构造函数参数值的情况下,创建一个参数持有者ArgumentsHolder对象
argsHolder = createArgumentArray(beanName, mbd, resolvedValues, bw,
paramTypes, paramNames, candidate, autowiring, candidates.length == 1);
}
catch (UnsatisfiedDependencyException ex) {
if (logger.isTraceEnabled()) {
logger.trace("Ignoring factory method [" + candidate + "] of bean '" + beanName + "': " + ex);
}
// Swallow and try next overloaded factory method.
if (causes == null) {
causes = new LinkedList<>();
}
causes.add(ex);
continue;
}
}
// isLenientConstructorResolution判断解析构造函数的时候是否以宽松模式还是严格模式
// 宽松模式:使用具有"最接近的模式"进行匹配
// 严格模式:解析构造函数时,必须所有的都需要匹配,否则抛出异常
int typeDiffWeight = (mbd.isLenientConstructorResolution() ?
argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes));
// Choose this factory method if it represents the closest match.
// 代表最接近的类型匹配,选择作为构造函数
if (typeDiffWeight < minTypeDiffWeight) {
factoryMethodToUse = candidate;
argsHolderToUse = argsHolder;
argsToUse = argsHolder.arguments;
minTypeDiffWeight = typeDiffWeight;
ambiguousFactoryMethods = null;
}
// Find out about ambiguity: In case of the same type difference weight
// for methods with the same number of parameters, collect such candidates
// and eventually raise an ambiguity exception.
// However, only perform that check in non-lenient constructor resolution mode,
// and explicitly ignore overridden methods (with the same parameter signature).
// 如果具有相同参数数量的方法具有相同的类型差异权重,则收集此类型选项
// 但是仅在非宽松模式构造函数解析模式下执行该检查,并显示忽略重写方法(具有相同的参数签名)
else if (factoryMethodToUse != null && typeDiffWeight == minTypeDiffWeight &&
!mbd.isLenientConstructorResolution() &&
paramTypes.length == factoryMethodToUse.getParameterCount() &&
!Arrays.equals(paramTypes, factoryMethodToUse.getParameterTypes())) {
// 查找多个可匹配的方法
if (ambiguousFactoryMethods == null) {
ambiguousFactoryMethods = new LinkedHashSet<>();
ambiguousFactoryMethods.add(factoryMethodToUse);
}
ambiguousFactoryMethods.add(candidate);
}
}
}
上面的代码:
- 遍历所有构造函数。
- 如果方法体参数大于等于最小参数个数,则判断是否传入了构造参数,如果是,则根据入参创建参数持有者对象ArgumentsHolder;否则通过方法体获取指定构造函数的参数,并创建参数持有者对象ArgumentsHolder。
- 构造函数的解析是使用宽松模式还是严格模式。严格模式:解析构造函数时,必须所有参数都需要匹配,否则抛出异常。宽松模式:使用具有”最接近的模式”进行匹配。
3.2.5 根据确定的构造参数及构造方法实例化bean
这一步在参数与工厂构造函数确认好后,就可以进行bean的实例化了:
- 如果工厂方法为空或构造参数为空,经过一系列异常判断后,最后会将解析的构造函数加入缓存。
- 然后通过instantiate方法创建bean对象,并注入到BeanWrapperImpl中,最后返回bw。这个流程和上面的实例化一样,调用的是同一个
instantiate
方法。
3.3 实例化后处理
上面介绍完了实例化的流程,接下来就要进行实例化后处理。这个时候我们要回到 doCreateBean
方法。
MergedBeanDefinitionPostProcessor
# postProcessMergedBeanDefinition
完整的调用链如下 :refresh
#finishBeanFactoryInitialization
#preInstantiateSingletons
#getBean
#doGetBean
#createBean
#doCreateBean
#applyMergedBeanDefinitionPostProcessors
/**
* Apply MergedBeanDefinitionPostProcessors to the specified bean definition,
* invoking their {@code postProcessMergedBeanDefinition} methods.
* @param mbd the merged bean definition for the bean
* @param beanType the actual type of the managed bean instance
* @param beanName the name of the bean
* @see MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition
*/
protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class<?> beanType, String beanName) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof MergedBeanDefinitionPostProcessor) {
MergedBeanDefinitionPostProcessor bdp = (MergedBeanDefinitionPostProcessor) bp;
bdp.postProcessMergedBeanDefinition(mbd, beanType, beanName);
}
}
}
以上将 MergedBeanDefinitionPostProcessors 应用于指定的 bean 定义, 调用它们的 postProcessMergedBeanDefinition
方法。
可以看到 MergedBeanDefinitionPostProcessor
# postProcessMergedBeanDefinition
有多个实现类,那就有不同的实现方式,下面是其中一种实现:
还有几个实现,如下:
(1)AutowiredAnnotationBeanPostProcessor
# postProcessMergedBeanDefinition
方法。
该方法来解析 @Autowired
,@Value
,@Inject
,并将相关的信息保存下来,后续对Bean属性进行赋值的时候要用
(2)CommonAnnotationBeanPostProcessor
# postProcessMergedBeanDefinition
方法。
该方法来解析 @WebServiceRef
,@EJB
,@Resource
,@PostConstruct
,@PreDestroy
,并将相关信息保存下来,后续对Bean属性赋值(@WebServiceRef
,@EJB
,@Resource
),生命周期(@PostConstruct
,@PreDestroy
)支持要用。
四、Bean属性赋值
Bean属性赋值也分为三个阶段:属性赋值前阶段、属性赋值阶段、Bean Aware接口回调阶段。
/**
* Populate the bean instance in the given BeanWrapper with the property values
* from the bean definition.
* @param beanName the name of the bean
* @param mbd the bean definition for the bean
* @param bw the BeanWrapper with bean instance
*/
@SuppressWarnings("deprecation") // for postProcessPropertyValues
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
if (bw == null) {
if (mbd.hasPropertyValues()) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
}
else {
// Skip property population phase for null instance.
return;
}
}
// Give any InstantiationAwareBeanPostProcessors the opportunity to modify the
// state of the bean before properties are set. This can be used, for example,
// to support styles of field injection.
// 给InstantiationAwareBeanPostProcessors最后一次机会在属性注入前修改Bean的属性值
// 具体通过调用postProcessAfterInstantiation方法,如果调用返回false,表示不必继续进行依赖注入,直接返回
boolean continueWithPropertyPopulation = true;
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;
}
// pvs是一个MutablePropertyValues实例,里面实现了PropertyValues接口,提供属性的读写操作实现,同时可以通过调用构造函数实现深拷贝
PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
// 根据Bean配置的依赖注入方式完成注入,默认是0,即不走以下逻辑,所有的依赖注入都需要在xml文件中有显式的配置
// 如果设置了相关的依赖装配方式,会遍历Bean中的属性,根据类型或名称来完成相应注入,无需额外配置
if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME || mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) {
// 深拷贝当前已有的配置
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
// Add property values based on autowire by name if applicable.
// 根据名称进行注入
if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);
}
// Add property values based on autowire by type if applicable.
// 根据类型进行注入
if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) {
autowireByType(beanName, mbd, bw, newPvs);
}
// 结合注入后的配置,覆盖当前配置
pvs = newPvs;
}
// 容器是否注册了InstantiationAwareBeanPostProcessor
boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
// 是否进行依赖检查
boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);
PropertyDescriptor[] filteredPds = null;
if (hasInstAwareBpps) {
if (pvs == null) {
pvs = mbd.getPropertyValues();
}
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
if (filteredPds == null) {
// 过滤出所有需要进行依赖检查的属性编辑器
filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
}
pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
return;
}
}
pvs = pvsToUse;
}
}
}
if (needsDepCheck) {
if (filteredPds == null) {
filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
}
// 检查是否满足相关依赖关系,对应的depends-on属性,需要确保所有依赖的Bean先完成初始化
checkDependencies(beanName, mbd, filteredPds, pvs);
}
if (pvs != null) {
// 将pvs上所有的属性填充到BeanWrapper对应的Bean实例中
applyPropertyValues(beanName, mbd, bw, pvs);
}
}
populateBean
方法是使用 bean 定义中的属性值填充给定 BeanWrapper 中的 bean 实例, 总体流程:
1、对Bean进行判空逻辑
2、在设置属性前去修改Bean状态,也可以控制是否继续给Bean设置属性值(如果Bean不是Spring限制的 || 具有感知Bean实例化的后置处理器){执行配置上的后置处理器} ,在设置属性前去修改Bean的状态,也可以控制是否继续填充Bean
3、如果前面代码设置了continueWithPropertyPopulation = false,表示用户可能已经自己填充了,此时直接返回Bean
4、从BeanDefinition里面获取到能为Bean设置上的属性值
5、根据Bean配置的依赖注入方式完成注入,
6、对Bean解析完未设置的属性进行再处理(重新检查是否注册了感知Bean实例化的后置处理器,如果注册了,则重新获取propertyValues(属性集合)然后进行依赖注入)
4.1 属性赋值前
InstantiationAwareBeanPostProcessor
# postProcessAfterInstantiation
对象已经被实例化,但属性还未被设置,都是null。该方法返回false,会忽略属性值的设置。返回true,会按正常流程设置默认属性值。
完整的调用链如下 :
refresh
#finishBeanFactoryInitialization
#preInstantiateSingletons
#getBean
#doGetBean
#createBean
#doCreateBean
#populateBean
#postProcessAfterInstantiation
default boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
return true;
}
4.2 属性赋值
4.2.1 autowireByName
在具体分析源码如何将将pvs上所有的属性填充到BeanWrapper对应的Bean实例中之前,先看看autowireByName和autowireByType这两步是怎么实现的。如果 autowire 设置为“byName”,则使用对该工厂中其他 bean 的引用填充任何缺失的属性值:
/**
* Fill in any missing property values with references to
* other beans in this factory if autowire is set to "byName".
* @param beanName the name of the bean we're wiring up.
* Useful for debugging messages; not used functionally.
*/
protected void autowireByName(
String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
// 根据bw的PropertyDescriptors,遍历出所有可写的(即set方法存在),存在于BeanDefinition里的PropertyValues
String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
for (String propertyName : propertyNames) {
if (containsBean(propertyName)) {
// 递归初始化bean,会调用doGetBean 来 获取bean
Object bean = getBean(propertyName);
// 根据名称添加到pvs中
pvs.add(propertyName, bean);
// 注册依赖关系,将依赖关系保存到 Map<String, Set<String>> dependentBeanMapdependentBeanMap 中,
// key是 bean,value是 转化后的 propertyName
registerDependentBean(propertyName, beanName);
if (logger.isTraceEnabled()) {
logger.trace("Added autowiring by name from bean name '" + beanName +
"' via property '" + propertyName + "' to bean named '" + propertyName + "'");
}
}
else {
if (logger.isTraceEnabled()) {
logger.trace("Not autowiring property '" + propertyName + "' of bean '" + beanName +
"' by name: no matching bean found");
}
}
}
}
可以看到,byName 的处理逻辑很简单,一句话概括,获取需要注入的bean然后递归调用getBean获取bean进行注入。
/**
* Abstract method defining "autowire by type" (bean properties by type) behavior.
* <p>This is like PicoContainer default, in which there must be exactly one bean
* of the property type in the bean factory. This makes bean factories simple to
* configure for small namespaces, but doesn't work as well as standard Spring
* behavior for bigger applications.
*/
protected void autowireByType(
String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
// 获取类型转换器
TypeConverter converter = getCustomTypeConverter();
if (converter == null) {
converter = bw;
}
Set<String> autowiredBeanNames = new LinkedHashSet<>(4);
// 类似的,过滤出满足装配条件的Bean属性
String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
for (String propertyName : propertyNames) {
try {
PropertyDescriptor pd = bw.getPropertyDescriptor(propertyName);
// Don't try autowiring by type for type Object: never makes sense,
// even if it technically is a unsatisfied, non-simple property.
// 如果是Object类型不进行装配
if (Object.class != pd.getPropertyType()) {
// 获取相关的写方法参数
MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);
// Do not allow eager init for type matching in case of a prioritized post-processor.
// 定义是否允许懒加载
boolean eager = !PriorityOrdered.class.isInstance(bw.getWrappedInstance());
DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(methodParam, eager);
// 这里会根据传入desc里的入参类型,作为依赖装配的类型
// 再根据这个类型在BeanFacoty中查找所有类或其父类相同的BeanName
// 最后根据BeanName获取或初始化相应的类,然后将所有满足条件的BeanName填充到autowiredBeanNames中。
Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter);
if (autowiredArgument != null) {
pvs.add(propertyName, autowiredArgument);
}
for (String autowiredBeanName : autowiredBeanNames) {
// 注册依赖
registerDependentBean(autowiredBeanName, beanName);
if (logger.isTraceEnabled()) {
logger.trace("Autowiring by type from bean name '" + beanName + "' via property '" +
propertyName + "' to bean named '" + autowiredBeanName + "'");
}
}
autowiredBeanNames.clear();
}
}
catch (BeansException ex) {
throw new UnsatisfiedDependencyException(mbd.getResourceDescription(), beanName, propertyName, ex);
}
}
}
unsatisfiedNonSimpleProperties
在 autowireByName
和 autowireByType
方法中,都有如下一行代码:
String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
protected String[] unsatisfiedNonSimpleProperties(AbstractBeanDefinition mbd, BeanWrapper bw) {
Set<String> result = new TreeSet<>();
// 获取bean 的property 属性
PropertyValues pvs = mbd.getPropertyValues();
// 获取 bw 中的属性描述
PropertyDescriptor[] pds = bw.getPropertyDescriptors();
for (PropertyDescriptor pd : pds) {
// if pd属性具有set方法 && 依赖检查中没有被忽略 && 没有被配置成 property 属性 && 不是简单类型
if (pd.getWriteMethod() != null && !isExcludedFromDependencyCheck(pd) && !pvs.contains(pd.getName()) &&
!BeanUtils.isSimpleProperty(pd.getPropertyType())) {
// 添加到需要装配的集合中
result.add(pd.getName());
}
}
// 返回需要自动装配的bean集合
return StringUtils.toStringArray(result);
}
在 unsatisfiedNonSimpleProperties
方法中,对Bean 的属性进行了过滤,得到了需要自动装配的属性。我们来详细看看里面的内容。
protected String[] unsatisfiedNonSimpleProperties(AbstractBeanDefinition mbd, BeanWrapper bw) {
Set<String> result = new TreeSet<>();
// 获取bean 的property 属性
PropertyValues pvs = mbd.getPropertyValues();
// 获取 bw 中的属性描述
PropertyDescriptor[] pds = bw.getPropertyDescriptors();
for (PropertyDescriptor pd : pds) {
// if pd属性具有set方法 && 依赖检查中没有被忽略 && 没有被配置成 property 属性 && 不是简单类型
if (pd.getWriteMethod() != null && !isExcludedFromDependencyCheck(pd) && !pvs.contains(pd.getName()) &&
!BeanUtils.isSimpleProperty(pd.getPropertyType())) {
// 添加到需要装配的集合中
result.add(pd.getName());
}
}
// 返回需要自动装配的bean集合
return StringUtils.toStringArray(result);
}
public static boolean isSimpleValueType(Class<?> type) {
return (Void.class != type && void.class != type &&
(ClassUtils.isPrimitiveOrWrapper(type) ||
Enum.class.isAssignableFrom(type) ||
CharSequence.class.isAssignableFrom(type) ||
Number.class.isAssignableFrom(type) ||
Date.class.isAssignableFrom(type) ||
Temporal.class.isAssignableFrom(type) ||
URI.class == type ||
URL.class == type ||
Locale.class == type ||
Class.class == type));
}
可以看到过滤条件
- 装配 属性具有set 方法: 因为后面的装配是通过set方法装配
- 依赖检查中没有被忽略
- 没有被设置成property 属性,因为这里property 会被单独处理,不需要在这里保存
- 不是简单类型,即不属于Void、void、 Enum、CharSequence、Number、Date、Temporal、URI、URL、Locale、Class 和 八大基本数据类型及其包装类型。可以看到如下代码,ClassUtils.isPrimitiveOrWrapper(type) 判断是type是否属于基本数据类型或者其包装类型。
上面只是将属性保存了起来,并未真正设置到bean中,这里设置到bean中:
/**
* Apply the given property values, resolving any runtime references
* to other beans in this bean factory. Must use deep copy, so we
* don't permanently modify this property.
*/
protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {
if (pvs.isEmpty()) {
return;
}
if (System.getSecurityManager() != null && bw instanceof BeanWrapperImpl) {
((BeanWrapperImpl) bw).setSecurityContext(getAccessControlContext());
}
MutablePropertyValues mpvs = null;
List<PropertyValue> original;
if (pvs instanceof MutablePropertyValues) {
mpvs = (MutablePropertyValues) pvs;
if (mpvs.isConverted()) {
// Shortcut: use the pre-converted values as-is.
// 如果已被设置转换完成,直接完成配置
try {
bw.setPropertyValues(mpvs);
return;
}
catch (BeansException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Error setting property values", ex);
}
}
original = mpvs.getPropertyValueList();
}
else {
original = Arrays.asList(pvs.getPropertyValues());
}
TypeConverter converter = getCustomTypeConverter();
if (converter == null) {
converter = bw;
}
// 创建BeanDefinitionValueResolver解析器,用来解析未被解析的PropertyValue
BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this, beanName, mbd, converter);
// Create a deep copy, resolving any references for values.
// 开始遍历检查original中的属性,对未被解析的先解析/已解析的直接加入deepCopy中,最后再填充到具体的Bean实例中
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();
// 核心逻辑,解析获取实际的值
// 对于RuntimeReference,会解析拿到具体的beanName,最终通过getBean(beanName)拿到具体的对象
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();
}
// Set our (possibly massaged) deep copy.
try {
bw.setPropertyValues(new MutablePropertyValues(deepCopy));
}
catch (BeansException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Error setting property values", ex);
}
}
五、 Bean初始化
前面属性赋值阶段都已经给bean的属性注入相关的值了,为啥还要初始化呢?
因为Bean的初始化阶spring允许用户可以自定义初始化方法,在初始化方法前后也能增加逻辑。
Bean的初始化阶段也分为:初始化前、初始化、初始化后、初始化完成。
5.1 Aware 接口回调阶段
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory
#invokeAwareMethods
org.springframework.context.support.ApplicationContextAwareProcessor
#invokeAwareInterfaces
属性赋值完毕,回到 doCreateBean
方法,接下来就是bean的初始化流程:
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareMethods(beanName, bean);
return null;
}, getAccessControlContext());
}
else {
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
可以看到在初始化的最开始阶段,要完成 invokeAwareMethods
方法,即回调所有 Aware 接口:
private void invokeAwareMethods(final String beanName, final Object bean) {
if (bean instanceof Aware) {
if (bean instanceof BeanNameAware) {
((BeanNameAware) bean).setBeanName(beanName);
}
if (bean instanceof BeanClassLoaderAware) {
ClassLoader bcl = getBeanClassLoader();
if (bcl != null) {
((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
}
}
if (bean instanceof BeanFactoryAware) {
((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
}
}
}
依次回掉如下接口,注入相应的对象:
BeanNameAware
BeanClassLoaderAware
BeanFactoryAware
5.2 初始化前 —— postProcessBeforeInitialization
BeanPostProcessor
#postProcessBeforeInitialization
调用链:
refresh
#finishBeanFactoryInitialization
#preInstantiateSingletons
#getBean
#doGetBean
#createBean
#doCreateBean
#initializeBean
#applyBeanPostProcessorsBeforeInitialization
@Override
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor processor : getBeanPostProcessors()) {
Object current = processor.postProcessBeforeInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
不同的 processor 的 postProcessBeforeInitialization
也是不同的, 比如当 processor 为
它的 postProcessBeforeInitialization
为:
@Override
@Nullable
public Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException {
AccessControlContext acc = null;
if (System.getSecurityManager() != null &&
(bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)) {
acc = this.applicationContext.getBeanFactory().getAccessControlContext();
}
if (acc != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareInterfaces(bean);
return null;
}, acc);
}
else {
invokeAwareInterfaces(bean);
}
return bean;
}
具体的:
(1)ApplicationContextAwareProcessor#postProcessBeforeInitialization
用来回调ApplicationContext相关的一些接口。
(2)ConfigurationClassPostProcessor.ImportAwareBeanPostProcessor#postProcessBeforeInitialization
用来支持ImportAware接口。
(3)CommonAnnotationBeanPostProcessor#postProcessBeforeInstantiation
执行@PostConstruct标注的方法。
(4)AutowiredAnnotationBeanPostProcessor#postProcessBeforeInstantiation
(5)ApplicationListenerDetector#postProcessBeforeInitialization
直接return bean,没有做任何操作。
除此之外,还可以自定义 postProcessBeforeInitialization
,只要实现 BeanPostProcessor
接口就行,可以参考sprig中怎么指定一个bean的初始化和销毁方法?一下子都搞懂!:
这里我们让 Person类去实现 BeanPostProcessor
,并实现它的两个方法:postProcessBeforeInitialization()
和postProcessAfterInitialization()
。
public class Person implements BeanPostProcessor {
public Person() {
Console.log("构造方法!");
}
public void init(){
Console.log("初始化方法!");
}
public void destroy(){
Console.log("销毁方法!");
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
Console.log("postProcessBeforeInitialization 在初始化方法前执行" + beanName + "###" + bean);
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
Console.log("postProcessAfterInitialization 在初始化方法后执行" + beanName + "###" + bean);
return bean;
}
}
@EnableAspectJAutoProxy
@Configuration
public class AopOneConfig {
@Bean
public AopOne aopOne() {
return new AopOne();
}
@Bean(initMethod = "init", destroyMethod = "destroy")
public Person person() {
return new Person();
}
@Bean
// @ConditionalOnBean(name = "aopOne") // 如果aopOne存在才实例化AopOneAspect
public AopOneAspect aopOneAspect() {
return new AopOneAspect();
}
}
可以看到其中有个 processor 就是 Person 类,然后调用的是 Person.postProcessBeforeInitialization
。
5.3 初始化 —— invokeInitMethods
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory
#invokeInitMethods
调用链:
refresh
#finishBeanFactoryInitialization
#preInstantiateSingletons
#getBean
#doGetBean
#createBean
#doCreateBean
#initializeBean
#invokeInitMethods
/**
* Give a bean a chance to react now all its properties are set,
* and a chance to know about its owning bean factory (this object).
* This means checking whether the bean implements InitializingBean or defines
* a custom init method, and invoking the necessary callback(s) if it does.
* 现在给一个 bean 一个反应的机会,它的所有属性都已设置,并有机会了解它拥有的 bean 工厂(这个对象)。
* 这意味着检查 bean 是否实现了 InitializingBean 或定义了一个自定义的 init 方法,如果是,则调用必要的回调。
*/
protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd)
throws Throwable {
boolean isInitializingBean = (bean instanceof InitializingBean);
if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
if (logger.isTraceEnabled()) {
logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
}
if (System.getSecurityManager() != null) {
try {
AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
((InitializingBean) bean).afterPropertiesSet();
return null;
}, getAccessControlContext());
}
catch (PrivilegedActionException pae) {
throw pae.getException();
}
}
else {
((InitializingBean) bean).afterPropertiesSet();
}
}
if (mbd != null && bean.getClass() != NullBean.class) {
String initMethodName = mbd.getInitMethodName();
if (StringUtils.hasLength(initMethodName) &&
!(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
!mbd.isExternallyManagedInitMethod(initMethodName)) {
invokeCustomInitMethod(beanName, bean, mbd);
}
}
}
若获取到我们自定义的初始化方法,这里自定义方法叫 ‘init’,下面就开始调用这个初始化方法:
/**
* Invoke the specified custom init method on the given bean.
* Called by invokeInitMethods.
* <p>Can be overridden in subclasses for custom resolution of init
* methods with arguments.
* @see #invokeInitMethods
*/
protected void invokeCustomInitMethod(String beanName, final Object bean, RootBeanDefinition mbd)
throws Throwable {
String initMethodName = mbd.getInitMethodName();
Assert.state(initMethodName != null, "No init method set");
final Method initMethod = (mbd.isNonPublicAccessAllowed() ?
BeanUtils.findMethod(bean.getClass(), initMethodName) :
ClassUtils.getMethodIfAvailable(bean.getClass(), initMethodName));
if (initMethod == null) {
if (mbd.isEnforceInitMethod()) {
throw new BeanDefinitionValidationException("Could not find an init method named '" +
initMethodName + "' on bean with name '" + beanName + "'");
}
else {
if (logger.isTraceEnabled()) {
logger.trace("No default init method named '" + initMethodName +
"' found on bean with name '" + beanName + "'");
}
// Ignore non-existent default lifecycle methods.
return;
}
}
if (logger.isTraceEnabled()) {
logger.trace("Invoking init method '" + initMethodName + "' on bean with name '" + beanName + "'");
}
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
ReflectionUtils.makeAccessible(initMethod);
return null;
});
try {
AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () ->
initMethod.invoke(bean), getAccessControlContext());
}
catch (PrivilegedActionException pae) {
InvocationTargetException ex = (InvocationTargetException) pae.getException();
throw ex.getTargetException();
}
}
else {
try {
ReflectionUtils.makeAccessible(initMethod);
initMethod.invoke(bean);
}
catch (InvocationTargetException ex) {
throw ex.getTargetException();
}
}
}
5.4 初始化后处理 —— applyBeanPostProcessorsAfterInitialization
BeanPostProcessor
#postProcessAfterInitialization
调用链:
refresh
#finishBeanFactoryInitialization
#preInstantiateSingletons
#getBean
#doGetBean
#createBean
#doCreateBean
#initializeBean
#applyBeanPostProcessorsAfterInitialization
@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor processor : getBeanPostProcessors()) {
Object current = processor.postProcessAfterInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
六、Bean 销毁
分为销毁前、销毁。
在容器关闭的时候就会走bean的销毁流程:
applicationContext.close();
调用链:
applicationContext.close()
#destroyBeans
#destroySingletons
#destroySingleton
#destroyBean
#destroy
#DisposableBeanAdapter
#destroy
@Override
public void destroy() {
if (!CollectionUtils.isEmpty(this.beanPostProcessors)) {
for (DestructionAwareBeanPostProcessor processor : this.beanPostProcessors) {
processor.postProcessBeforeDestruction(this.bean, this.beanName);
}
}
if (this.invokeDisposableBean) {
if (logger.isTraceEnabled()) {
logger.trace("Invoking destroy() on bean with name '" + this.beanName + "'");
}
try {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
((DisposableBean) this.bean).destroy();
return null;
}, this.acc);
}
else {
((DisposableBean) this.bean).destroy();
}
}
catch (Throwable ex) {
String msg = "Invocation of destroy method failed on bean with name '" + this.beanName + "'";
if (logger.isDebugEnabled()) {
logger.info(msg, ex);
}
else {
logger.info(msg + ": " + ex);
}
}
}
if (this.destroyMethod != null) {
invokeCustomDestroyMethod(this.destroyMethod);
}
else if (this.destroyMethodName != null) {
Method methodToCall = determineDestroyMethod(this.destroyMethodName);
if (methodToCall != null) {
invokeCustomDestroyMethod(methodToCall);
}
}
}
6.1 销毁前 —— postProcessBeforeDestruction
DestructionAwareBeanPostProcessor
#postProcessBeforeDestruction
/**
* Apply this BeanPostProcessor to the given bean instance before its
* destruction, e.g. invoking custom destruction callbacks.
* <p>Like DisposableBean's {@code destroy} and a custom destroy method, this
* callback will only apply to beans which the container fully manages the
* lifecycle for. This is usually the case for singletons and scoped beans.
* @param bean the bean instance to be destroyed
* @param beanName the name of the bean
*/
void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException;
postProcessBeforeDestruction
有5个实现类,主要是在销毁之前将此 BeanPostProcessor 应用到给定的 bean 实例。
6.2 销毁
若定义了销毁方法就会去执行自定义的销毁方法:
private void invokeCustomDestroyMethod(final Method destroyMethod) {
Class<?>[] paramTypes = destroyMethod.getParameterTypes();
final Object[] args = new Object[paramTypes.length];
if (paramTypes.length == 1) {
args[0] = Boolean.TRUE;
}
if (logger.isTraceEnabled()) {
logger.trace("Invoking destroy method '" + this.destroyMethodName +
"' on bean with name '" + this.beanName + "'");
}
try {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
ReflectionUtils.makeAccessible(destroyMethod);
return null;
});
try {
AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () ->
destroyMethod.invoke(this.bean, args), this.acc);
}
catch (PrivilegedActionException pax) {
throw (InvocationTargetException) pax.getException();
}
}
else {
ReflectionUtils.makeAccessible(destroyMethod);
destroyMethod.invoke(this.bean, args);
}
}
catch (InvocationTargetException ex) {
String msg = "Destroy method '" + this.destroyMethodName + "' on bean with name '" +
this.beanName + "' threw an exception";
if (logger.isDebugEnabled()) {
logger.info(msg, ex.getTargetException());
}
else {
logger.info(msg + ": " + ex.getTargetException());
}
}
catch (Throwable ex) {
logger.info("Failed to invoke destroy method '" + this.destroyMethodName +
"' on bean with name '" + this.beanName + "'", ex);
}
}
依次调用如下方法:
@PreDestory
标注方法- 实现
DisposableBean
接口的destory()
方法 - 自定义销毁方法