系列文章目录
文章目录
- 系列文章目录
- 前言
- 一、整体流程
- 二、Bean实例化过程
-
- [1. doGetBean获取实例对象](#1. doGetBean获取实例对象)
- [2. createBean方法创建bean](#2. createBean方法创建bean)
- [3. createBeanInstance方法实例化bean](#3. createBeanInstance方法实例化bean)
-
- [3.1 推断构造方法](#3.1 推断构造方法)
- [3.2 autowireConstructor()方法](#3.2 autowireConstructor()方法)
- [4. 填充属性](#4. 填充属性)
-
- [4.1 查找注入点](#4.1 查找注入点)
- [4.2 populateBean方法填充属性](#4.2 populateBean方法填充属性)
- 总结
前言
上一篇讲了配置类是如何解析的,各种Bean是如何生成的的。这一章将详细介绍getBean方法是如何创建bean的,创建Bean的过程中是如何执行Bean的生命周期方法的。
一、整体流程
之前讲过在refresh方法中通过finishBeanFactoryInitialization(beanFactory)实例化所有单例的非懒加载bean,所以从这个方法看一下整体流程
1)获取所有的beanDefinitionNames,for循环beanDefinitionNames进行2/3步的处理
2)合并BeanDefinition
上一章介绍过,BeanDefinition时可以通过设置parent属性继承父BeanDefinition的,所以这里通过合并BeanDefinition,将父BeanDefinition的属性copy到子BeanDefinition来(会递归父BD,并控制死循环父BD),得到的结果会缓存到mergedBeanDefinitions中
3)如果是非懒加载的单例bean,创建bean
a.如果是FactoryBean,调用getBean(&beanName)方法,也就是获取的是FactoryBean的实例;FactroyBean就是用来创建bean的,比如配置类中的@Bean注解就会生成一个FactroyBean,@Bean注解的方法就是getObject调用的方法。
b.如果不是FactoryBean,调用getBean(beanName)方法获取bean的实例
3)getBean方法完成了创建bean的生命周期:实例化前->实例化->实例化后->填充属性->执行aware方法->初始化前->初始化->初始化后
4)执行afterSingletonsInstantiated方法
for循环beanDefinitionNames获取所有已创建的单例bean,如果实现了SmartInitializingSingleton接口,调用afterSingletonsInstantiated方法
SmartInitializingSingleton接口主要用于在IoC容器基本启动完成时进行扩展,这时非Lazy的Singleton都已被初始化完成。所以,在该扩展点执行ListableBeanFactory#getBeansOfType()等方法不会出现因过早getBean出现副作用
二、Bean实例化过程
1. doGetBean获取实例对象
1)将&name或者别名,会转换成name
2)尝试从单例池中获取name对应的对象
3)如果单例池中存在beanInstance,调用getObjectForBeanInstance方法获取对象
在getObjectForBeanInstance这个方法里,如果想拿的是FactoryBean(&name),直接返回beanInstance;如果想拿的是bean,此时如果beanInstance不是FactoryBean,直接返回,如果beanInstance是FactoryBean,从FactoryBean的getObject方法中获取对象
这里简单介绍一下NullBean:如果工厂方法返回null或者FactoryBean的getObject方法返回null
就会生成NullBean类型的对象,每个NullBean类型的对象都不相等,但是equal(null)返回的是ture
c
protected Object getObjectForBeanInstance(
Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
// Don't let calling code try to dereference the factory if the bean isn't a factory.
//如果想拿的是FactoryBean
if (BeanFactoryUtils.isFactoryDereference(name)) {
if (beanInstance instanceof NullBean) {
return beanInstance;
}
if (!(beanInstance instanceof FactoryBean)) {
throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass());
}
if (mbd != null) {
mbd.isFactoryBean = true;
}
return beanInstance;
}
// Now we have the bean instance, which may be a normal bean or a FactoryBean.
// If it's a FactoryBean, we use it to create a bean instance, unless the
// caller actually wants a reference to the factory.
//如果想拿的是bean
//如果对象不是FactoryBean,直接返回,否则后续从FactoryBean的getObject方法中获取
if (!(beanInstance instanceof FactoryBean)) {
return beanInstance;
}
Object object = null;
if (mbd != null) {
mbd.isFactoryBean = true;
}
else {
object = getCachedObjectForFactoryBean(beanName);
}
if (object == null) {
// Return bean instance from factory.
FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
// Caches object obtained from FactoryBean if it is a singleton.
if (mbd == null && containsBeanDefinition(beanName)) {
mbd = getMergedLocalBeanDefinition(beanName);
}
boolean synthetic = (mbd != null && mbd.isSynthetic());
object = getObjectFromFactoryBean(factory, beanName, !synthetic);
}
return object;
}
这里要特别介绍一下从FactoryBean的getObject方法中获取对象的过程
a.先从factoryBeanObjectCache缓存中获取,getObject方法中获取的对象都会放在factoryBeanObjectCache中
b.如果缓存中没有,调用getObjectFromFactoryBean方法,在这个方法中也会执行BPP的postProcessAfterInitialization方法,使bean的生命周期完整,代码如下:
c
protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
if (factory.isSingleton() && containsSingleton(beanName)) {
synchronized (getSingletonMutex()) {
Object object = this.factoryBeanObjectCache.get(beanName);
if (object == null) {
object = doGetObjectFromFactoryBean(factory, beanName);
// Only post-process and store if not put there already during getObject() call above
// (e.g. because of circular reference processing triggered by custom getBean calls)
Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
if (alreadyThere != null) {
object = alreadyThere;
}
else {
//执行postProcess相关方法
if (shouldPostProcess) {
//如果有其他线程正在调用这段代码,直接返回,不执行postProcess方法
if (isSingletonCurrentlyInCreation(beanName)) {
// Temporarily return non-post-processed object, not storing it yet..
return object;
}
beforeSingletonCreation(beanName);
try {
//执行BPP的postProcessAfterInitialization方法
object = postProcessObjectFromFactoryBean(object, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(beanName,
"Post-processing of FactoryBean's singleton object failed", ex);
}
finally {
afterSingletonCreation(beanName);
}
}
if (containsSingleton(beanName)) {
this.factoryBeanObjectCache.put(beanName, object);
}
}
}
return object;
}
}
else {
Object object = doGetObjectFromFactoryBean(factory, beanName);
if (shouldPostProcess) {
try {
object = postProcessObjectFromFactoryBean(object, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);
}
}
return object;
}
}
4)如果单例池中不存在beanInstance
a. 如果当前BeanFactory的beanDefinitionNames没有该name,而父BeanFactory不为空,从父BeanFactory中获取Bean
b. 如果当前BeanFactory的beanDefinitionNames含有该name
首先,获取合并的BeanDefinition
然后,检查合并的BeanDefinition中的dependsOn属性,如果dependsOn不为空,先实例化dependsOn的类。
再通过createBean方法创建bean,根据不同的scope(singleton、prototype、其他定义的scope)进行创建
最后通过getObjectForBeanInstance方法直接获取刚刚创建的bean或者调用BeanFactory的getObject方法获取bean(上面讲过)
2. createBean方法创建bean
1)加载BeanClass
2)检查lookup标签或注解
3)执行实例化前方法
如果如果容器中有InstantiationAwareBeanPostProcessor(前面介绍过的CommonAnnotationBeanPostProcessor就是),执行所有InstantiationAwareBeanPostProcessor的postProcessBeforeInstantiation方法
在这里,可以对bd做一些操作,甚至直接创建bean,如果直接创建了bean对象,后续不会再实例化
c
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.
// NOTE-M 加载BeanClass
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.
//NOTE-K 实例化前
//可以对bd做一些操作,甚至直接创建bean,如果直接创建了bean对象,后续不会再实例化
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 {
//NOTE-K doCreateBean方法
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);
}
}
我们看下CommonAnnotationBeanPostProcessor的postProcessMergedBeanDefinition方法,直接返回null
c
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
return null;
}
4)执行createBeanInstance方法创建bean,也就是实例化bean
5)执行BeanDefinition的后置处理(主要是查找注入点)
如果如果容器中有MergedBeanDefinitionPostProcessor(前面说过CommonAnnotationBeanPostProcessor和AutowiredAnnotationBeanPostProcessor都是),执行所有MergedBeanDefinitionPostProcessor的postProcessMergedBeanDefinition方法
简单介绍CommonAnnotationBeanPostProcessor和AutowiredAnnotationBeanPostProcessor查找注入点:(后面会详细介绍查找注入点的过程)
先看CommonAnnotationBeanPostProcessor的
a.调用父类的的方法,也就是去找寻当前bean是否实现了PostConstruct注解和PreDestroy注解,放入缓存中
b.查找注入点,寻找方法上是否有@Resource注解,生成InjectionMetadata,放入缓存中
c
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
super.postProcessMergedBeanDefinition(beanDefinition, beanType, beanName);
//NOTE-M 处理@Resource注解
InjectionMetadata metadata = findResourceMetadata(beanName, beanType, null);
metadata.checkConfigMembers(beanDefinition);
}
再看AutowiredAnnotationBeanPostProcessor的
实现的是查找注入点的逻辑,查找出field或方法上有@Autowired、@Value、@Inject的且不是static的,生成InjectionMetadata并放到缓存injectionMetadataCache中,用于后续的属性填充
c
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
//NOTE-M 查找注入点的逻辑 field或方法上有@Autowired、@Value、@Inject的且不是static的,并放到缓存中
InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
metadata.checkConfigMembers(beanDefinition);
}
6)判断是否需要早期暴露
如果是单例,允许循环依赖,且正在创建中(只要是通过getBean调用进来的,就在创建中),则将EarlyBeanReference放入三级缓存中。
7)populateBean方法填充属性
a. 执行实例化后方法
如果当前实例化的BeanDefinition不是合成bean,且容器中有InstantiationAwareBeanPostProcessor,执行InstantiationAwareBeanPostProcessor的postProcessAfterInstantiation方法
b.注入属性
先处理xml配置的自动注入模式,再处理@Autowired、@Resource、@Value等注解,再处理xml中的注入。后面单独介绍依赖注入
8)执行aware方法
9)执行初始化前方法
执行所有BeanPostProcessor的postProcessBeforeInitialization方法
例如InitDestroyAnnotationBeanPostProcessor执行@PostConstruct注解的方法就是在这一步执行
10)执行初始方法
执行实现了InitializingBean的初始化方法和init-method指定的初始化方法
11)执行初始化后方法
执行所有BeanPostProcessor的postProcessAfterInitialization方法
例如aop就是在这一步执行
3. createBeanInstance方法实例化bean
先贴一下代码:
c
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());
}
//NOTE-M 使用Supplier实例化对象
Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
if (instanceSupplier != null) {
return obtainFromSupplier(instanceSupplier, beanName);
}
//NOTE-M 使用FactoryMethod实例化对象
if (mbd.getFactoryMethodName() != null) {
return instantiateUsingFactoryMethod(beanName, mbd, args);
}
// Shortcut when re-creating the same bean...
//NOTE-M 从resolvedConstructorOrFactoryMethod中获取缓存的已解析的构造方法,如果有就不用解析了
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?
//NOTE-M 推断构造方法
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.
//NOTE-M 无参实例化bean
return instantiateBean(beanName, mbd);
}
1)使用Supplier实例化对象
如果BeanDefinition中的InstanceSupplier有值,那么就用InstanceSupplier来实例化bean。写了一个demo,如下,注意spring的版本要5.X,否则没有setInstanceSupplier这个方法
c
public class TestSupplier {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
//创建一个BeanDefinition
GenericBeanDefinition carBD = new GenericBeanDefinition();
carBD.setBeanClass(Car.class);
carBD.setInstanceSupplier(()->{
System.out.println("用Supplier创建");
return new Car();
});
context.registerBeanDefinition("car",carBD);
context.refresh();
}
}
打印结果
c
用Supplier创建
2)使用FactoryMethod实例化对象
工厂方法配置的BeanDefinition有FactoryName和FactoryMethodName这两个值,会调用工厂的方法来实例化对象
前面介绍过@Bean注解产生的BeanDefinition跟XML配置工厂方法一样,有FactoryName和FactoryMethodName
3)从BeanDefinition的缓存resolvedConstructorOrFactoryMethod中获取已解析的构造方法,如果有就不用解析了,调用autowireConstructor()自动构造一个对象。
4)如果缓存没有就推断构造方法。如果有可用的构造方法,或者当前BeanDefinition的autowired模式是AUTOWIRE_CONSTRUCTOR,或者BeanDefinition中指定了构造方法参数值(xml配置constructor-arg),或者获取Bean的时候指定了构造方法参数值(getBean方法传了构造方法的参数值),那么就调用autowireConstructor()方法自动构造一个对象~~(后面会单独详细介绍autowireConstructor()方法、autowire属性、autowire set方法这三种自动注入的方式)~~ 。
5)如果上面的都没有,直接用无参构造方法实例化bean
3.1 推断构造方法
如果容器中有SmartInstantiationAwareBeanPostProcessor类型的BeanPostProcessor(前面介绍过的AutowiredAnnotationBeanPostProcessor就是),执行SmartInstantiationAwareBeanPostProcessor的determineCandidateConstructors方法
c
protected Constructor<?>[] determineConstructorsFromBeanPostProcessors(@Nullable Class<?> beanClass, String beanName)
throws BeansException {
if (beanClass != null && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
Constructor<?>[] ctors = ibp.determineCandidateConstructors(beanClass, beanName);
if (ctors != null) {
return ctors;
}
}
}
}
return null;
}
determineCandidateConstructors方法太长了,就不贴出来了,推断的过程大概如下:
1)先找是否有自动注入注解的构造方法(被@AutoWired、@Value、@Inject注解),如果有自动注入注解的构造方法,判断@AutoWired的required属性是否为true,只允许有一个@Autowired(requierd=true)注解的构造方法(requierd默认为true),否则就报错。如果@AutoWired的required属性都不为true,那么必须有无参构造方法(因为需要无参构造作为备选)。
有点绕,反正最后,候选的构造方法为被@AutoWired、@Value、@Inject注解的构造方法+无参构造(如果@AutoWired的required属性都不为true)
2)如果只有唯一的构造方法,且参数个数>0,候选的构造方法为这个构造方法
3)如果有2个构造方法,且一个是@Primary注解的,一个是无参的,那么候选的构造方法为@Primary注解的+无参的
4)如果只有1个构造方法,且是@Primary注解的,那么候选的构造方法为@Primary注解的
5)如果以上都不是,候选的构造方法为空
3.2 autowireConstructor()方法
1)先确定候选的构造方法:如果推断构造方法的结果不为空,候选的构造方法为推断构造方法的结果;如果推断构造方法的结果为空,获取class中所有声明的构造方法
2)如果只有1个候选的构造方法,且无参数。用这个无参构造方法实例化bean
3)如果候选的构造方法大于1个,按修饰符和参数个数排序,public修饰>非public修饰,参数多>参数少
4)排序后,遍历候选的构造方法
a. 如果通过getBean方法传了参数,那么遍历的构造方法中的参数个数必须≥传入的参数个数(通过xml配置的参数个数不会多,否则生成bean时解析不了),否则就报错
b. 如果没有指定参数值(通过getBean方法传入、通过xml配置),先判断有没有@Vaule的值,如果有就使用@value的值,如果没有,就通过resolveAutowiredArgument方法自动注入参数(最终是调用beanFactory.resolveDependency方法,与后面讲填充属性时自动注入的过程一样,后面再讲);如果指定了参数值,则使用指定的参数值
c. 根据参数的值和构造方法类型进行匹配程度的打分,选出得分最少的。如果得分最少的有2个,则抛错
5)用最后选出的构造方法及参数实例化bean
小结:
看源码确实挺复杂的,看了很多遍,有些细节也不能理解。但是大致可以这样理解
-
首先要认识有哪些配置或者方式来决定构造方法的执行
1)通过xml配置constructor-arg属性,指定构造参数和参数值
2)通过xml配置autowire="constructor"
3)通过@AutoWired注解在构造方法上、通过@Value注解在构造参数上,通过@Pramary注解在构造方法上
4)getBean方法调用时传参
-
再来梳理一下
1)先通过推断构造方法逻辑,筛选一下构造方法,筛选出@AutoWired、@Primary等注解的构造方法,此时跟参数值无关。
2)如果推断构造方法结果不为空,或者通过xml配置autowire="constructor",或者通过xml配置了constructor-arg属性的参数和参数值,或者调用getBean方法传了构造方法的参数值,那么就调用autowireConstructor()方法来构造,那么怎么构造呢?先看候选的构造方法是否唯一,如果不唯一,通过计算各个构造方法与参数值的匹配程度(评分的过程),找出最终的构造方法(得分最低的)。用这个构造方法实例化bean,如果没有指定参数值,就自动注入。
3)如果步骤2中不符合,则用无参构造实例化bean
4. 填充属性
上面介绍过,CommonAnnotationBeanPostProcessor和AutowiredAnnotationBeanPostProcessor这两个BPP在执行BeanDefinition的后置处理时,进行了注入点的查找,这样在填充属性时才能根据注入点进行填充,下面来详细看看注入点的查找和如何填充属性
4.1 查找注入点
CommonAnnotationBeanPostProcessor
1)遍历class里的属性
a. 如果属性上有@webServiceRefClass,且不是static,将该属性封装成WebServiceRefElement对象后放到currElements这个lsit中
b. 如果属性上有@EJB注解,且不是static,将该属性封装成EjbRefElement对象后放到currElements这个lsit中
c. 如果属性上有@Resource注解,且不是static,且不在ignoredResourceTypes中,将该属性封装成ResourceElement对象后放到currElements这个lsit中
最终都放到缓存injectionMetadataCache中
2)遍历class里的方法
a. 如果方法上有@webServiceRefClass,且不是static,且参数只有1个,将该属性封装成WebServiceRefElement对象后放到currElements这个lsit中
b. 如果方法上有@EJB注解,且不是static,且参数只有1个,将该属性封装成EjbRefElement对象后放到currElements这个lsit中
c. 如果方法上有@Resource注解,且不是static,且参数只有1个,且不在ignoredResourceTypes中,将该属性封装成ResourceElement对象后放到currElements这个lsit中
最终都放到缓存injectionMetadataCache中
3)如果有父类,继续遍历父类的class中的属性和方法
用一句话来说,这里主要就是把加了@Resource注解的属性和只有1个参数的方法找出来作为注入点
clike
private InjectionMetadata findResourceMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs) {
// Fall back to class name as cache key, for backwards compatibility with custom callers.
String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
// Quick check on the concurrent map first, with minimal locking.
InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);
if (InjectionMetadata.needsRefresh(metadata, clazz)) {//没有查找过
synchronized (this.injectionMetadataCache) {
metadata = this.injectionMetadataCache.get(cacheKey);
if (InjectionMetadata.needsRefresh(metadata, clazz)) {//双重判断
if (metadata != null) {
metadata.clear(pvs);
}
metadata = buildResourceMetadata(clazz);
this.injectionMetadataCache.put(cacheKey, metadata);
}
}
}
return metadata;
}
private InjectionMetadata buildResourceMetadata(Class<?> clazz) {
if (!AnnotationUtils.isCandidateClass(clazz, resourceAnnotationTypes)) {
return InjectionMetadata.EMPTY;
}
List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();
Class<?> targetClass = clazz;
do {
final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>();
//遍历属性
ReflectionUtils.doWithLocalFields(targetClass, field -> {
if (webServiceRefClass != null && field.isAnnotationPresent(webServiceRefClass)) {
if (Modifier.isStatic(field.getModifiers())) {
throw new IllegalStateException("@WebServiceRef annotation is not supported on static fields");
}
currElements.add(new WebServiceRefElement(field, field, null));
}
else if (ejbClass != null && field.isAnnotationPresent(ejbClass)) {
if (Modifier.isStatic(field.getModifiers())) {
throw new IllegalStateException("@EJB annotation is not supported on static fields");
}
currElements.add(new EjbRefElement(field, field, null));
}
else if (field.isAnnotationPresent(Resource.class)) {
if (Modifier.isStatic(field.getModifiers())) {
throw new IllegalStateException("@Resource annotation is not supported on static fields");
}
if (!this.ignoredResourceTypes.contains(field.getType().getName())) {
currElements.add(new ResourceElement(field, field, null));
}
}
});
//遍历方法
ReflectionUtils.doWithLocalMethods(targetClass, method -> {
Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
return;
}
if (method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
if (webServiceRefClass != null && bridgedMethod.isAnnotationPresent(webServiceRefClass)) {
if (Modifier.isStatic(method.getModifiers())) {
throw new IllegalStateException("@WebServiceRef annotation is not supported on static methods");
}
if (method.getParameterCount() != 1) {
throw new IllegalStateException("@WebServiceRef annotation requires a single-arg method: " + method);
}
PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
currElements.add(new WebServiceRefElement(method, bridgedMethod, pd));
}
else if (ejbClass != null && bridgedMethod.isAnnotationPresent(ejbClass)) {
if (Modifier.isStatic(method.getModifiers())) {
throw new IllegalStateException("@EJB annotation is not supported on static methods");
}
if (method.getParameterCount() != 1) {
throw new IllegalStateException("@EJB annotation requires a single-arg method: " + method);
}
PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
currElements.add(new EjbRefElement(method, bridgedMethod, pd));
}
else if (bridgedMethod.isAnnotationPresent(Resource.class)) {
if (Modifier.isStatic(method.getModifiers())) {
throw new IllegalStateException("@Resource annotation is not supported on static methods");
}
Class<?>[] paramTypes = method.getParameterTypes();
if (paramTypes.length != 1) {
throw new IllegalStateException("@Resource annotation requires a single-arg method: " + method);
}
if (!this.ignoredResourceTypes.contains(paramTypes[0].getName())) {
PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
currElements.add(new ResourceElement(method, bridgedMethod, pd));
}
}
}
});
elements.addAll(0, currElements);
targetClass = targetClass.getSuperclass();
}
while (targetClass != null && targetClass != Object.class);
return InjectionMetadata.forElements(elements, clazz);
}
AutowiredAnnotationBeanPostProcessor
代码与上面的极其相似,我就不贴代码了
1)遍历属性,如果属性上有@AutoWired注解,且不是static,且不在ignoredResourceTypes中,将该属性封装成ResourceElement对象后放到currElements这个lsit中
2)遍历方法,如果方法上有@AutoWired注解,且不是static,且不在ignoredResourceTypes中,将该属性封装成ResourceElement对象后放到currElements这个lsit中。
最终都放到缓存injectionMetadataCache中
@AutoWired注解没有限制只能用在1个参数的方法上,但是如果没有参数会打印一个logo告诉你应该用在有参数的方法上,例如下面代码,给无参方法加@Autowired注解,也会形成一个注入点:
clike
@Component
public class Animal extends Species{
private String name;
@Autowired
public String getName() {
System.out.println("autowired用在无参方法");
return name;
}
public void setName(String name) {
this.name = name;
}
}
容器启动后,打印结果为:
clike
信息: Autowired annotation should only be used on methods with parameters: public java.lang.String com.zcl.ioc.bean.constructBean.entity.Animal.getName()
autowired用在无参方法
思考:
根据上面的介绍,我们可以看到,注入点是从class对象中来查找的,所以
4.2 populateBean方法填充属性
1)处理自动注入模式
解析所有的property,如果有set方法,且参数只有一个的,不是SimpleProperty的,在执行autoWireByName或autoWireByType的resolveDependency方法时生成依赖bean的对象,并将propertyName和生成的Bean放到BD的propertyValues中,propertyValues是一个map,key是propertyName,value是找到的Bean对象
autoWireByName:是将setXXX方法的XXX作为name调用getBean方法获取bean对象
autoWireByType:是根据参数类型在spring容器中找到合适的bean对象,怎么找的,通过resolveDependency方法,下面跟处理@AtuoWired和@Resource一起说
c
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
...
PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
//NOTE-M 处理自动注入模式
//解析所有的property,如果有set方法,且参数只有一个的,不是SimpleProperty的
//在autoWireByName或autoWireByType的resolveDependency方法时生成依赖bean的对象
//将所有依赖的bean关系放入BeanFactory的dependentBeanMap中,所有被依赖的关系放入dependenciesForBeanMap中
int resolvedAutowireMode = mbd.getResolvedAutowireMode();
if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
// Add property values based on autowire by name if applicable.
if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);
}
// Add property values based on autowire by type if applicable.
if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
autowireByType(beanName, mbd, bw, newPvs);
}
pvs = newPvs;
}
boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);
//NOTE-M 注入属性,处理@Autowired、@Resource、@Value等注解
//如果是field会注入,如果是method会跳过在pvs中的属性,因为后续会通过pvs注入
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);
}
checkDependencies(beanName, mbd, filteredPds, pvs);
}
if (pvs != null) {
applyPropertyValues(beanName, mbd, bw, pvs);
}
}
2)处理@Autowired、@Resource、@Value等注解
前面说过在通过查找注入点,已经解析好了所有的@Autowired、@Resource、@Value等注解放到缓存injectionMetadataCache中,现在从缓存中拿出来进行注入,调用流程如下:
可以看出,关键步骤是找到候选对象名findAutowireCandidates方法
clike
public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
if (Optional.class == descriptor.getDependencyType()) {
return createOptionalDependency(descriptor, requestingBeanName);
}
else if (ObjectFactory.class == descriptor.getDependencyType() ||
ObjectProvider.class == descriptor.getDependencyType()) {
return new DependencyObjectProvider(descriptor, requestingBeanName);
}
else if (javaxInjectProviderClass == descriptor.getDependencyType()) {
return new Jsr330Factory().createDependencyProvider(descriptor, requestingBeanName);
}
else {
//如果有lazy注解,使用代理对象
Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
descriptor, requestingBeanName);
if (result == null) {
//如果没有lazy注解,获取依赖的bean
result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
}
return result;
}
}
clike
public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
try {
Object shortcut = descriptor.resolveShortcut(this);
if (shortcut != null) {
return shortcut;
}
Class<?> type = descriptor.getDependencyType();
//获取@Value注解的值
Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);
if (value != null) {
if (value instanceof String) {
String strVal = resolveEmbeddedValue((String) value);
BeanDefinition bd = (beanName != null && containsBean(beanName) ?
getMergedBeanDefinition(beanName) : null);
value = evaluateBeanDefinitionString(strVal, bd);
}
TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
try {
return converter.convertIfNecessary(value, type, descriptor.getTypeDescriptor());
}
catch (UnsupportedOperationException ex) {
// A custom TypeConverter which does not support TypeDescriptor resolution...
return (descriptor.getField() != null ?
converter.convertIfNecessary(value, type, descriptor.getField()) :
converter.convertIfNecessary(value, type, descriptor.getMethodParameter()));
}
}
Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
if (multipleBeans != null) {
return multipleBeans;
}
//找到候选的对象
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
if (matchingBeans.isEmpty()) {
if (isRequired(descriptor)) {
raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
}
return null;
}
String autowiredBeanName;
Object instanceCandidate;
if (matchingBeans.size() > 1) {
//先按@Primary和@Priority来选择,如果都没有,再按名称是否匹配来选择
autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
if (autowiredBeanName == null) {
if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {
return descriptor.resolveNotUnique(descriptor.getResolvableType(), matchingBeans);
}
else {
// In case of an optional Collection/Map, silently ignore a non-unique case:
// possibly it was meant to be an empty collection of multiple regular beans
// (before 4.3 in particular when we didn't even look for collection beans).
return null;
}
}
instanceCandidate = matchingBeans.get(autowiredBeanName);
}
else {
// We have exactly one match.
Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
autowiredBeanName = entry.getKey();
instanceCandidate = entry.getValue();
}
if (autowiredBeanNames != null) {
autowiredBeanNames.add(autowiredBeanName);
}
if (instanceCandidate instanceof Class) {
instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
}
Object result = instanceCandidate;
if (result instanceof NullBean) {
if (isRequired(descriptor)) {
raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
}
result = null;
}
if (!ClassUtils.isAssignableValue(type, result)) {
throw new BeanNotOfRequiredTypeException(autowiredBeanName, type, instanceCandidate.getClass());
}
return result;
}
finally {
ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
}
}
我们来看看findAutowireCandidates方法:
1)找出BeanFactory容器中类型为要注入的类型(requiredType)的所有的Bean的名字,这里并不是从单例池里面查找,而是遍历beanDefinition,因为beanDefinition就包含了类型
2)从resolvableDependencies中找(在启动流程的prepareBeanFactory时放了4个元素进去,分别是BeanFactory.class、ResourceLoader.class、ApplicationEventPublisher.class和ApplicationContext.class),把key为requiredType的对象找出来并添加到result中
3)分为三种情况找候选bean:
首先,不是自循环(注入自己或者自己的工厂bean),且autowireCandidate属性为ture(默认是true),继续判断
a.判断当前type是不是泛型,如果是泛型会把容器中所有的beanName找出来的,然后获取到泛型的真正类型,然后进行匹配,如果当前beanName和当前泛型对应的真实类型匹配,那么则继续判断
b.如果当前DependencyDescriptor上存在@Qualifier注解,那么则要判断当前beanName上是否
定义了Qualifier,并且value属性是否和当前DependencyDescriptor上的Qualifier相等,相等则匹配
c.判断完,把beanName的class对象加入到result中
然后,如果没有找到,判断依赖的类型是不是multiple类型,也就是Map、Collection类型的的,这种情况,会把所有符合的类型组装成Map或者Collection
最后,就是自循环的情况。如果第一种情况没有找到候选的,依赖的类型也不是multiple类型,那么就只能找自循环的候选类了
clike
protected Map<String, Object> findAutowireCandidates(
@Nullable String beanName, Class<?> requiredType, DependencyDescriptor descriptor) {
//找出BeanFactory中类型为type的所有的Bean的名字
String[] candidateNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this, requiredType, true, descriptor.isEager());
Map<String, Object> result = new LinkedHashMap<>(candidateNames.length);
//先从缓存resolvableDependencies中找,把key为type的对象找出来并添加到result中
for (Map.Entry<Class<?>, Object> classObjectEntry : this.resolvableDependencies.entrySet()) {
Class<?> autowiringType = classObjectEntry.getKey();
if (autowiringType.isAssignableFrom(requiredType)) {
Object autowiringValue = classObjectEntry.getValue();
autowiringValue = AutowireUtils.resolveAutowiringValue(autowiringValue, requiredType);
if (requiredType.isInstance(autowiringValue)) {
result.put(ObjectUtils.identityToString(autowiringValue), autowiringValue);
break;
}
}
}
for (String candidate : candidateNames) {
//判断是否能自动注入
if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, descriptor)) {
addCandidateEntry(result, candidate, descriptor, requiredType);
}
}
if (result.isEmpty()) {
boolean multiple = indicatesMultipleBeans(requiredType);
// Consider fallback matches if the first pass failed to find anything...
DependencyDescriptor fallbackDescriptor = descriptor.forFallbackMatch();
for (String candidate : candidateNames) {
if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, fallbackDescriptor) &&
(!multiple || getAutowireCandidateResolver().hasQualifier(descriptor))) {
addCandidateEntry(result, candidate, descriptor, requiredType);
}
}
if (result.isEmpty() && !multiple) {
// Consider self references as a final pass...
// but in the case of a dependency collection, not the very same bean itself.
for (String candidate : candidateNames) {
if (isSelfReference(beanName, candidate) &&
(!(descriptor instanceof MultiElementDescriptor) || !beanName.equals(candidate)) &&
isAutowireCandidate(candidate, fallbackDescriptor)) {
addCandidateEntry(result, candidate, descriptor, requiredType);
}
}
}
}
return result;
}
这里再介绍一下对@Qualifier注解的判断逻辑,其实就是注入的时候能找到对应那个需要注入的bean,比如下面代码:
clike
//首先在 Bean 注入的时候,添加 @Qualifier 注解:
@Configuration
@ComponentScan
public class JavaConfig {
@Bean(value = "b1")
@Qualifier
B b1() {
return new B();
}
@Bean("b2")
B b2() {
return new B();
}
}
//然后在需要进行 B 对象注入的地方,也添加 @Qualifier 注解
@Component
public class A {
@Autowired
@Qualifier
B b;
}
最后,找到候选的beanName以后
a.如果候选的beanName有多个,那么根据@Pramary和@Priority注解来选择,如果都没有,根据名字来匹配,如果最后还是选不出来报NoUniqueBeanDefinitionException异常。
b.选出来以后,实例化依赖的bean,也是通过beanFactory.getBean(beanName, args)来获取
c.最后使用获取到的bean注入
总结
- bean的类型分为FactroyBean和普通bean,实例化bean时,FactroyBean类型的beanName是生成的FactroyBean类型的实例,放入单例池,而我们调用getBean获取的时候,先是获取到FactroyBean类型的实例,再调用它的getObject方法,最终获取到想要的bean对象,并且缓存到factoryBeanObjectCache中。所以单例池中并没有我们想要的FactroyBean生成的那个bean
- bean的生命周期:实例化前->实例化->实例化后->填充属性->执行aware方法->初始化前->初始化->初始化后
FactroyBean产生的对象也有生命周期,getObject方法之后会调用BeanPostProcessor的postProcessAfterInitialization方法,因为代理是在初始化后方法中进行的,如果FactroyBean产生的对象没有这个生命周期,就没法代理了。 - createBeanInstance实例化对象时,如果没有通过xml指定构造方法,先要推断构造方法得到候选的构造方法,再筛选出构造方法,再实例化。实例化时,如果指定了参数值,则使用指定的参数值,如果没有指定,就自动自动注入参数(跟填充属性时自动注入的过程一样);
- 自动注入的过程:通过CommonAnnotationBeanPostProcessor和AutowiredAnnotationBeanPostProcessor这两个BPP来实现的,在生命周期的实例化完成后,查找注入点,分别查找属性和方法上的@Resource和@AutoWired注解,生成InjectionMetadata。在生命周期的填充属性阶段,找到候选的填充对象,完成属性填充;
- 自动注入的优先级:先处理XML和注解中的显式配置(如XML的或@Value)。
再处理自动注入(如@Autowired),最后是xml配置的自动注入模式(如autowire="byType"),但是自动注入模式不会覆盖@Autowired和@Resource(因为@Autowired注入后会删除对应的自动注入模式生成的PropertyValues),也就是说@Autowired和@Resource的优先级最高