在我们前面两章,我们讲完了Spring如何加载、解析资源文件以及如何将其转化为BeanDefinition
的(标签的解析)流程。那么接下来我们来看下Bean
的一个加载过程。我们来从这段代码为切入口:
public static void main(String[] args) {
ClassPathResource resource = new ClassPathResource("test.xml");
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);
reader.loadBeanDefinitions(resource);
GetNameTest getNameTest = (GetNameTest) factory.getBean("getNameTest");
getNameTest.getName();
}
Spring中对于bean的加载功能,普遍的调用方式为factory.getBean(beanName);
那我们来看下这个方法到底做了什么事情,再根据每一个步骤进行展开来细说。
GetNameTest getNameTest = (GetNameTest) factory.getBean("getNameTest");
↓↓↓↓↓↓
public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory {
@Override
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}
↓↓↓↓↓↓
protected <T> T doGetBean(
String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
throws BeansException {
// 1.提取对应的beanName
String beanName = transformedBeanName(name);
Object beanInstance;
// 2.检查缓存中或者实例工厂中是否有对应的实例
/**
* 背景:在创建单例bean的时候,存在依赖注入的情况。
* 目的:为了避免循环依赖的产生,Spring再创建bean的时候,并不会等待bean创建完成,而是会在 bean 创建完成之前提早曝光这个 ObjectFactory。
* 即:将 ObjectFactory 加入到Map缓存中,下一个bean创建的时候,若需要依赖上一个bean,那么就可以直接使用这个 ObjectFactory 对象。
* 缓存:this.singletonObjects
* 提前暴露的单利工厂。this.singletonFactories。其还有另外一个熟悉的名称:三级工厂。具体的分析,在下文展开
*/
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
if (logger.isTraceEnabled()) {
if (isSingletonCurrentlyInCreation(beanName)) {
logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
"' that is not fully initialized yet - a consequence of a circular reference");
}
else {
logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
}
}
// 3.返回对应的实例,因为有时候如BeanFactory的情况,并不是直接返回实例本身。而是返回指定方法返回的实例对象。
beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
else {
// 4.若出现循环依赖的情况,则抛异常
/**
* A类、B类必须为单例
* A类有B对象作为其属性。
* B类有A对象作为其属性。
*/
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
// 5.若BeanDefinitionMap中(存储已经加载好的类)不包含beanName。那么尝试从父BeanDefinition中去检测。即父工厂
BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
String nameToLookup = originalBeanName(name);
if (parentBeanFactory instanceof AbstractBeanFactory abf) {
return abf.doGetBean(nameToLookup, requiredType, args, typeCheckOnly);
}
// 递归到beanFactory中去寻找。
else if (args != null) {
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else if (requiredType != null) {
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
else {
return (T) parentBeanFactory.getBean(nameToLookup);
}
}
// 6.若不是仅仅做类型检查。那么就是创建bean。这里做一个mark(标记),做记录。
if (!typeCheckOnly) {
markBeanAsCreated(beanName);
}
StartupStep beanCreation = this.applicationStartup.start("spring.beans.instantiate")
.tag("beanName", name);
try {
if (requiredType != null) {
beanCreation.tag("beanType", requiredType::toString);
}
// 7.我们从Spring解析标签的过程中可以得知。XML的一些具体配置都存储于 GenericBeanDefinition 中
// 这里则是将 GenericBeanDefinition 转化为 RootBeanDefinition。
// 若指定的 beanName 是子Bean的话,还会合并父子BeanDefinition。
RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
// 8.检测合并后的类型。合并后的BeanDefinition肯定不是AbstractBeanDefinition,若是,则其肯定是abstract类型的,此时抛异常
checkMergedBeanDefinition(mbd, beanName, args);
// 9.若存在依赖,那么开始递归实例化依赖的Bean。(属性注入(包括实例化))
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dep : dependsOn) {
if (isDependent(beanName, dep)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
registerDependentBean(dep, beanName);
try {
getBean(dep);
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
}
}
}
// 10.若依赖都注入完了。就开始实例化本身,创建单例模式,注意这里是第一次实例化(因为单例缓存中不存在,才会走到该分支)
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, () -> {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
destroySingleton(beanName);
throw ex;
}
});
beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
else if (mbd.isPrototype()) {
// 多例,创建个新的实例
Object prototypeInstance = null;
try {
beforePrototypeCreation(beanName);
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
beanInstance = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}
else {
// 或者根据指定的scope进行实例化
String scopeName = mbd.getScope();
if (!StringUtils.hasLength(scopeName)) {
throw new IllegalStateException("No scope name defined for bean '" + beanName + "'");
}
Scope scope = this.scopes.get(scopeName);
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
}
try {
Object scopedInstance = scope.get(beanName, () -> {
beforePrototypeCreation(beanName);
try {
return createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
});
beanInstance = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
}
catch (IllegalStateException ex) {
throw new ScopeNotActiveException(beanName, scopeName, ex);
}
}
}
catch (BeansException ex) {
// ...
}
finally {
beanCreation.end();
}
}
// 11.检查需要的类型是否符合bean的实际类型
return adaptBeanInstance(name, beanInstance, requiredType);
}
}
上述代码可以做个总结,其大致步骤如下:
beanName
,传入的参数可能是别名、FactoryBean
。因此需要进行进一步的转换解析。bean
的实例化。ParentBeanFactory
,进行递归。GenericBeanDefinition
转化为 RootBeanDefinition
,若当前bean
为子bean
,则合并父子BeanDefinition
。scope
进行bean
的创建。大胆点,我们再简化一下,Bean
的一个加载三步走:
Bean
的实例化。Bean
的相关依赖注入。Bean
的初始化。对应写出个伪代码:
Object dfs(beanName){
// 1.实例化
Object bean = getBeanInstance(beanName);
// 2.递归依赖注入(若存在)
String[] depends = getDependsOn(bean);
for(String name:depends){
dfs(name);
}
// 3.初始化
return initBean(bean);
}
背景:Spring通过反射机制利用bean
的class
属性指定实现类来实例化bean
。但是传统的方式下,需要在
标签里面配置大量的信息,而XML
配置的这种方式是有局限性的。 若可以通过编码的方式来进行实例化,就能更加自由地实例化一些复杂的bean
。FactoryBean
这个接口就是用来让用户定制自定义实例化的逻辑的。
public interface FactoryBean<T> {
String OBJECT_TYPE_ATTRIBUTE = "factoryBeanObjectType";
// 返回由FactoryBean创建的bean实例,如果isSingleton()返回true
// 那么该实例则会放到单例缓存池里面。
@Nullable
T getObject() throws Exception;
// 返回FactoryBean创建的bean实例的类型
@Nullable
Class<?> getObjectType();
// 返回由 FactoryBean 创建的bean实例的作用域,是singleton还是prototype
default boolean isSingleton() {
return true;
}
}
若配置文件中的
标签的class
属性配置的实现类是FactoryBean
的实现类的时候,那么通过getBean()
返回的则是FactoryBean.getObject()
方法返回的对象。相当于其代理了getBean
的方法。
public class User {
private String name;
private String address;
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
UserFactoryBean
类,需要实现FactoryBean
类,进行自定义加载Bean。
import org.springframework.beans.factory.FactoryBean;
public class UserFactoryBean implements FactoryBean<User> {
private String userInfo;
@Override
public User getObject() throws Exception {
User user = new User();
String[] infos = userInfo.split(",");
user.setName(infos[0]);
user.setAddress(infos[1]);
return user;
}
@Override
public Class<User> getObjectType() {
return User.class;
}
@Override
public boolean isSingleton() {
return false;
}
public String getUserInfo() {
return userInfo;
}
public void setUserInfo(String userInfo) {
this.userInfo = userInfo;
}
}
user.xml
文件:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id="user" class="com.mytest.factorytest.UserFactoryBean">
<property name="userInfo" value="你好,上海"/>
bean>
beans>
Test
类:
public class Test {
public static void main(String[] args) {
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);
ClassPathResource resource = new ClassPathResource("/factorytest/user.xml");
reader.loadBeanDefinitions(resource);
User user = (User) factory.getBean("user");
System.out.println(user.getName());
System.out.println(user.getAddress());
}
}
代码运行结果如下:
可见确实如上文所说FactoryBean.getObject()
方法代理了getBean()
方法,负责Bean
的加载。
Spring在获取bean
的时候,会先从单例缓存中去尝试获取,若还没有,则再去singletonFactories
中加载。
我们来看下这个方法:Object sharedInstance = getSingleton(beanName);
public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
public Object getSingleton(String beanName) {
// true设置为:允许早期依赖(就是我们说的,为了避免循环依赖,不等bean创建完成就会将创建bean的ObjectFactory提早曝光)
return getSingleton(beanName, true);
}
↓↓↓↓↓↓
@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
// 1.先检查一级缓存中是否存在,若存在,则直接返回。这里的bean都是已经创建完成的。
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
// 2.尝试从二级缓存中获取,这里的bean都是完成实例化,但是没有进行属性注入和初始化的对象或者代理对象
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
synchronized (this.singletonObjects) {
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null) {
// 3.singletonFactories:提前暴露的单例工厂,二级缓存中存储的对象,就是从该工厂中获取到的对象
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
// 4.创建bean
singletonObject = singletonFactory.getObject();
// 5.earlySingletonObjects和singletonFactories互斥
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
}
}
return singletonObject;
}
}
我们可以看出来,这里Spring有三级的缓存,用来解决循环依赖问题,具体的在下文展开。在此先解释下几种缓存代表的意义:
singletonObjects
:保存beanName
和bean
实例(初始化完成的)之间的关系。earlySingletonObjects
:同样保存beanName
和bean
实例之间的关系。循环对象依赖列表,用于存储那些发生了循环依赖的对象。singletonFactories
:保存beanName
和创建bean
的工厂ObjectFactory
之间的关系。注意和前两者的区别,其存储的并不是bean
,而是负责创建它的工厂。接下来我会用大篇幅来讲这个循环依赖的问题,也希望尽量将这一块难题啃下来,也方便日后自己复习,这里参考了这位博主的文章(第二次看了)
我们先来看下循环依赖的一个示意图:这里的类都是单例。
或者是更简单粗暴的:
@Component
public class A{
@Autowired
private A a;
}
那么在这种情况下,就是所谓的循环依赖了。
我们以A
,B
两个类之间的依赖来讲解Spring解决循环依赖的过程。
整体过程如下:
A
。A
的属性B
进行注入。B
进行实例化。B
进行属性注入。B
完成初始化方法。A
注入完成。则完成初始化方法。Spring先对A
进行实例化(第一次),那么最终最终会走代码中的第十步:
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, () -> {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
destroySingleton(beanName);
throw ex;
}
});
beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
该代码走的则是getSingleton
的重载方法:
getSingleton(String beanName, ObjectFactory<?> singletonFactory)
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(beanName, "Bean name must not be null");
synchronized (this.singletonObjects) {
// 1.同样先去单例缓存中去拿
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
// ..日志记录等
// 2.在创建单例对象之前先做一个标记处理。将beanName放入singletonsCurrentlyInCreation集合中。
// 代表这个bean正在被创建中,如果一个单例Bean被多次创建,那么会在这里抛出异常
beforeSingletonCreation(beanName);
boolean newSingleton = false;
boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
if (recordSuppressedExceptions) {
this.suppressedExceptions = new LinkedHashSet<>();
}
try {
// 3.这里则执行外部传入的参数,是一个lambda表达式,调用上文的createBean方法
singletonObject = singletonFactory.getObject();
newSingleton = true;
}
// ...catch
finally {
if (recordSuppressedExceptions) {
this.suppressedExceptions = null;
}
// 3.创建完成后,将对应的beanName从singletonsCurrentlyInCreation中删除
afterSingletonCreation(beanName);
}
if (newSingleton) {
// 4.添加到一级缓存中,注意到这一步为止,该单例bena已经创建完成了。即完成了初始化了。
addSingleton(beanName, singletonObject);
}
}
return singletonObject;
}
}
从代码中我们可以发现,类的实例化由singletonObject = singletonFactory.getObject();
来完成。我们又知道,外部传入的lambda
表达式只执行了createBean
方法。我们来跟进:
public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory
implements AutowireCapableBeanFactory {
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
// ...省略
try {
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
// ...
return beanInstance;
}
// ...catch
}
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
// 创建实例
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
Object bean = instanceWrapper.getWrappedInstance();
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
mbd.resolvedTargetType = beanType;
}
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
// log...
// 先将beanName->工厂方法,加入到三级缓存中,因为可能会发生循环依赖
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
// 三级缓存中添加完成后,在进行属性注入和初始化
Object exposedObject = bean;
try {
// 属性注入
populateBean(beanName, mbd, instanceWrapper);
// 初始化
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
if (earlySingletonExposure) {
// 这里再一次调用了getSingleton方法,并且禁用了三级缓存。
// 在属性注入阶段,B的属性注入阶段中,已经将A从三级缓存工厂取出,并加入到了二级缓存。
// 因此这里取出来的是A的一个代理对象。
Object earlySingletonReference = getSingleton(beanName, false);
// ...
}
}
}
在这里做个总结,A
类的加载做了什么事情getBean(beanNameA)
开始:
A
完成了实例化。beanNameA
对应的工厂方法加入到了三级缓存。A
完成属性注入populateBean(beanName, mbd, instanceWrapper);
。A
完成初始化exposedObject = initializeBean(beanName, exposedObject, mbd);
。那么对于B
类的加载,则发生在A
类加载阶段的第三步:属性注入阶段。
注意:属性注入阶段对于A
类的属性B
而言,也只不过是完成了三个步骤:实例化、B
类的属性注入、初始化。
对于B
而言,其加载同样是从getBean(beanNameB)
开始的,同样的:
B
完成了实例化。beanNameB
对应的工厂方法加入到了三级缓存。B
类下面有个A属性,那么对A
进行属性注入。 开始调用getBean(beanNameA)
。B
完成初始化。但是,这里的getBean
则会走不同的分支了,我们这里可以接上1.1节源码的第二步:Object sharedInstance = getSingleton(beanName);
(与A
类的加载过程进行区分,参数传的不一样,并且在A
类的加载过程中,已经将相关的工厂加入到了三级缓存中了。)此时跟进代码,我们会走入该环节:
结合上述代码,我们可以发现注入到B
中的A
对象是通过addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
提前暴露出去的,我们来跟进下getEarlyBeanReference
:
public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory
implements AutowireCapableBeanFactory {
// 获取后置处理器,即通过@EnableAspectJAutoProxy注解导入的AnnotationAwareAspectJAutoProxyCreator对象
protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
Object exposedObject = bean;
// 若有AOP的相关配置逻辑,才会走这段代码,若没有,本代码实则上并没有什么作用。也就是说三级工厂在无AOP的情况下是没有实质作用的。
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (SmartInstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().smartInstantiationAware) {
exposedObject = bp.getEarlyBeanReference(exposedObject, beanName);
}
}
return exposedObject;
}
}
那么在无AOP的情况下:
B
的时候,给B
注入了一个未完成初始化的对象A
,但是A将其引用加入到了三级缓存。B
中的是A
的一个引用。在B
完成初始化后,会根据这个引用对A
进行初始化。在开启AOP的情况下,则会走代码exposedObject = bp.getEarlyBeanReference(exposedObject, beanName);
:
public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware {
@Override
public Object getEarlyBeanReference(Object bean, String beanName) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
this.earlyProxyReferences.put(cacheKey, bean);
// 若需要代理,返回代理对象。
// 若不需要代理,则返回当前这个bean。
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
在这里插入代码片
类的注入的属性是A
的代理对象,但是不管是cglib
还是jdk
代理,内部都存储一个目标类的引用。而A
的代理对象就是A
的一个引用。因此代理对象完成了初始化,A
类自然而然完成了初始化。B
加载环节,就需要其相关属性完成AOP代理。而Spring希望AOP在bena
初始化之后再进行。 因此,通过一个三级缓存,返回一个代理对象(没有完成AOP操作的),让bean
之间完成初始化操作并解决循环依赖问题。最后再遵循Spring的原则,进行AOP代理。getBean
有两种用途:
Bean
,并将其工厂方法存入三级缓存。bean
。此外,我们可以发现,二级缓存就能够实现解决Spring循环依赖的需求,而三级缓存的存在仅仅是提供了一个能够生成代理对象的工厂方法。 那么其目的是什么?
假设我们没有三级缓存,我们的对象并且是单例的。若A
对象依赖的B对象存在AOP机制,即B
对象需要被代理。那么在属性注入的时候,再加入二级缓存之前都需要被代理。这并不合适。 那么如果能够通过第三方的工厂方法,生成一个代理对象丢给二级缓存,就能解决这个问题。
问题来了:为何在存在AOP的情况下,我的实例再加入二级缓存之前就一定要完成代理呢?
那么请问:代理对象和二级缓存中的对象不是一个东西,引用不同。那么这种情况下完成对代理对象的初始化之后,原对象完成了吗?
没有,那么通过三级缓存,直接将代理对象(其引用和Spring想要加载的bean
的引用是同一个)返回给二级缓存。那么此时即满足AOP的代理条件,又能够满足Spring的一个初始化过程。
言归正传,到此为止,在讲解bean
的循环依赖的过程中,其实已经顺带把bean
加载的一个过程给过了一遍。但是里面的一些方法我们还没有详细的去了解。
我们在getBean
方法中可以发现,getObjectForBeanInstance
这个方法调用了多次。在这两种大情况下,都会调用该方法:
bean
。scope
策略加载bean
。而该方法的目的就是为了检测bean
的正确性。主要用于检测当前bean
是否是FactoryBean
类型的bean
。 如果是,则会调用对应实例中的getObject()
方法作为返回值(参考1.1小节的案例)。我们可以从侧面发现,无论从缓存中还是策略加载的bean
都是最原始的bean
。我们还需要做进一步的处理,来看下其源码:
public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory {
protected Object getObjectForBeanInstance(
Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
// 1.若指定的name是工厂相关的,并且&开头
if (BeanFactoryUtils.isFactoryDereference(name)) {
if (beanInstance instanceof NullBean) {
return beanInstance;
}
// 若不是 FactoryBean 类型,则验证不通过。前后if矛盾
if (!(beanInstance instanceof FactoryBean)) {
throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass());
}
if (mbd != null) {
mbd.isFactoryBean = true;
}
// 若是 FactoryBean ,我们就用它创建实例。
return beanInstance;
}
// 2.若是bean本身,则直接返回
if (!(beanInstance instanceof FactoryBean)) {
return beanInstance;
}
Object object = null;
if (mbd != null) {
mbd.isFactoryBean = true;
}
else {
// 3.尝试从缓存中加载bean
object = getCachedObjectForFactoryBean(beanName);
}
if (object == null) {
// 4.若是BeanFactory类型的实例。且缓存中不存在
FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
// 5.在所有已经加载的bean中检测,是否存在相同的bean
if (mbd == null && containsBeanDefinition(beanName)) {
mbd = getMergedLocalBeanDefinition(beanName);
}
// 6.是否是用户定义的,而非程序本身定义。
boolean synthetic = (mbd != null && mbd.isSynthetic());
// 7.核心代码,获取实例对象。
object = getObjectFromFactoryBean(factory, beanName, !synthetic);
}
return object;
}
}
再从最后一步的核心代码出发,来看下展开的源码:
protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
// 1.若是单例模式
if (factory.isSingleton() && containsSingleton(beanName)) {
// 2.锁住singletonObjects对象,一级缓存
synchronized (getSingletonMutex()) {
// 3.factoryBeanObjectCache存储一些已经创建好的,并且由factoryBean创建出来的bean。
Object object = this.factoryBeanObjectCache.get(beanName);
if (object == null) {
object = doGetObjectFromFactoryBean(factory, beanName);
// 发生循环引用时可能也会有提早暴露的对象(代理)
Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
if (alreadyThere != null) {
object = alreadyThere;
}
else {
// 若需要对bean进行后续处理
if (shouldPostProcess) {
// 若该bean还在创建过程中,则不做处理直接返回
if (isSingletonCurrentlyInCreation(beanName)) {
return object;
}
// 创建bean前预处理
beforeSingletonCreation(beanName);
try {
object = postProcessObjectFromFactoryBean(object, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(beanName,
"Post-processing of FactoryBean's singleton object failed", ex);
}
finally {
// 创建bean后处理
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;
}
}
可以发现最外层的if/else
分支,都调用了doGetObjectFromFactoryBean
方法:
private Object doGetObjectFromFactoryBean(FactoryBean<?> factory, String beanName) throws BeanCreationException {
Object object;
try {
// 权限验证
if (System.getSecurityManager() != null) {
AccessControlContext acc = getAccessControlContext();
try {
object = AccessController.doPrivileged((PrivilegedExceptionAction<Object>) factory::getObject, acc);
}
catch (PrivilegedActionException pae) {
throw pae.getException();
}
}
else {
object = factory.getObject();
}
}
// catch..
// ...
return object;
}
可以发现无论怎么样,都会执行FactoryBean
的getObject
方法来获取实例对象。本小节实质上并不是特别复杂,通过简化也就是:
beanInstance
对象,他是bean
类型还是FactoryBean
类型的实例?FactoryBean
类型的,并且以&
为开头,说明用户希望直接获取工厂实例而非工厂方法创建出来的实例对象。bean
类型,直接返回。FactoryBean
类型,不以&
开头,那么就调用其getObject()
方法并返回实例。bean
实例进行后续处理。即后处理器的调用。Spring在获取
bean
的时候有这么一个规则:尽可能保证所有bean
初始化完成后都会调用注册的BeanPostProcessor
的postProcessAfterInitialization
方法进行处理。
紧接着,我们需要将注意力几种在Bean
的一个创建过程。即实例化、属性注入、初始化的这么一个过程。
上述文章中,一大片篇幅其实都是在讲Spring如何从缓存中加载Bean
(1.2节)以及如何将原始bean
进行转换的(1.3节)。但是我们都没有具体的去看过Spring在第一次的时候(无缓存)是怎么创建Bean
的。
一切还是该从这段代码走起,来再回忆一遍:
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, () -> {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
destroySingleton(beanName);
throw ex;
}
});
beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
createBean
则是创建Bean
的入口函数,最终的实现在AbstractAutowireCapableBeanFactory
类中完成:
@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
// ...
RootBeanDefinition mbdToUse = mbd;
// 1.锁定class,根据设置的class属性或者根据className来解析
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
mbdToUse = new RootBeanDefinition(mbd);
mbdToUse.setBeanClass(resolvedClass);
}
// 2.验证和准备覆盖的方法。
try {
mbdToUse.prepareMethodOverrides();
}
// ...catch
try {
// 3.提供机会,用BeanPostProcessors返回的代理对象来替代实例
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
}
// ...catch
try {
// 4.创建bean
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
if (logger.isTraceEnabled()) {
logger.trace("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;
}
// ...catch
}
一共有4步:
class
属性或者根据className
来解析Class
。override
属性进行标记验证。如XML
配置中的lookup-method
和replaced-method
标签。bean
是否存在初始化前的短路操作。bean
。XML
配置中的lookup-method
和replaced-method
标签。经过Spring容器的读取和转换后,将其存放在BeanDefinition
中的methodOverrides
属性中,而下面的操作就是针对该属性来进行的。
mbdToUse.prepareMethodOverrides();
↓↓↓↓↓
public void prepareMethodOverrides() throws BeanDefinitionValidationException {
// 判断methodOverrides是否为空
if (hasMethodOverrides()) {
// 遍历处理
getMethodOverrides().getOverrides().forEach(this::prepareMethodOverride);
}
}
↓↓↓↓↓
protected void prepareMethodOverride(MethodOverride mo) throws BeanDefinitionValidationException {
// 获取对应类中和该名称同名的方法的个数
int count = ClassUtils.getMethodCountForName(getBeanClass(), mo.getMethodName());
// 若没有,抛出异常,说明XML配置肯定出问题啦,配置了一个不存在的方法
if (count == 0) {
throw new BeanDefinitionValidationException(
"Invalid method override: no method with name '" + mo.getMethodName() +
"' on class [" + getBeanClassName() + "]");
}
else if (count == 1) {
// 标记methodOverride暂时没有被覆盖,避免参数类型检查带来的开销
mo.setOverloaded(false);
}
}
在后续bean
实例化的阶段,若检查到对应的methodOverride
属性,则会动态的为当前bean
生成代理,并使用拦截器为bean
做增强处理(下文介绍)。
Spring-AOP的功能就是基于此进行的,我们来看下这个方法的调用入口:
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
// 为什么要加这个判断?
// 若经过前置处理的返回结果不是null,那么我们就将其替代原有的bean,直接返回。以达到逻辑增强的插拔效果。
if (bean != null) {
return bean;
}
来看下resolveBeforeInstantiation
方法的源码:
public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory
implements AutowireCapableBeanFactory {
@Nullable
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
Object bean = null;
// 没被处理过的情况下
if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
Class<?> targetType = determineTargetType(beanName, mbd);
if (targetType != null) {
// 调用 InstantiationAwareBeanPostProcessor 的 postProcessBeforeInstantiation 方法
bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
if (bean != null) {
// 调用 BeanPostProcessor 的 postProcessAfterInitialization方法
bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
}
}
}
mbd.beforeInstantiationResolved = (bean != null);
}
return bean;
}
}
备注:
postProcessBeforeInstantiation
方法:在Bean
的自定义初始化方法之前执行。postProcessAfterInitialization
方法:在Bean
的自定义初始化方法之后执行。紧接着就是最后一个步骤了:
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
代码的展开在上文已经有提及,本章只围绕着三个重点来讲:
createBeanInstance()
:创建实例。populateBean()
:属性注入。initializeBean()
:初始化。源码如下:
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
// 1.根据Class属性来解析Class
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());
}
// 2.一个bean的回调函数,用来代替工厂方法。 若不为空,那么调用回调函数并直接将结果返回。
Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
if (instanceSupplier != null) {
return obtainFromSupplier(instanceSupplier, beanName);
}
// 3.若工厂方法不为空,那么使用工厂方法来进行初始化。
// 若RootBeanDefinition中配置了factoryMethodName属性,说明配置文件中配置了factory-method的方法
if (mbd.getFactoryMethodName() != null) {
return instantiateUsingFactoryMethod(beanName, mbd, args);
}
boolean resolved = false;// 构造函数是否解析过
boolean autowireNecessary = false;// 构造函数其中的参数是否解析过
if (args == null) {
// 由于一个类中可能有多种构造函数,每个构造函数有着不同的参数。因此需要锁定构造函数
synchronized (mbd.constructorArgumentLock) {
// resolvedConstructorOrFactoryMethod :一个用于缓存 已解析的构造函数或者工厂方法。
// 因为构造函数的多样性,定位到一个准确的构造函数并进行实例化是一个耗时的过程,因此采用缓存来标记。
if (mbd.resolvedConstructorOrFactoryMethod != null) {
resolved = true;
// constructorArgumentsResolved属性:标记这个构造函数参数已经解析过了
autowireNecessary = mbd.constructorArgumentsResolved;
}
}
}
// 若已经解析过,那么使用解析好的构造函数
if (resolved) {
if (autowireNecessary) {
return autowireConstructor(beanName, mbd, null, null);
}else {
// 使用默认的构造函数
return instantiateBean(beanName, mbd);
}
}
// 根据参数来解析构造函数
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
// 构造函数注入
return autowireConstructor(beanName, mbd, ctors, args);
}
// 构造函数注入
ctors = mbd.getPreferredConstructors();
if (ctors != null) {
return autowireConstructor(beanName, mbd, ctors, null);
}
// 若以上都不命中,则使用默认构造来创建
return instantiateBean(beanName, mbd);
}
总结下就是:
Class
对象并校验。factory-method
,则调用并返回。同时我们可以注意到,代码中除了第二、第三点这样的特殊情况。对于实例的创建分为了两大类:
autowireConstructor
。instantiateBean
。源码如下:
public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory implements AutowireCapableBeanFactory {
protected BeanWrapper autowireConstructor(String beanName, RootBeanDefinition mbd, @Nullable Constructor<?>[] ctors, @Nullable Object[] explicitArgs) {
return new ConstructorResolver(this).autowireConstructor(beanName, mbd, ctors, explicitArgs);
}
↓↓↓↓↓↓
public BeanWrapper autowireConstructor(String beanName, RootBeanDefinition mbd,
@Nullable Constructor<?>[] chosenCtors, @Nullable Object[] explicitArgs) {
BeanWrapperImpl bw = new BeanWrapperImpl();
this.beanFactory.initBeanWrapper(bw);
Constructor<?> constructorToUse = null;
ArgumentsHolder argsHolderToUse = null;
Object[] argsToUse = null;
// explicitArgs由调用getBean方法的时候传入
if (explicitArgs != null) {
argsToUse = explicitArgs;
}
else {
// 若getBean调用的时候,并没有传入相关的参数,那么会尝试去配置文件中寻找
Object[] argsToResolve = null;
// 同理,这里用了缓存去存放解析好的构造函数参数
synchronized (mbd.constructorArgumentLock) {
constructorToUse = (Constructor<?>) mbd.resolvedConstructorOrFactoryMethod;
if (constructorToUse != null && mbd.constructorArgumentsResolved) {
// Found a cached constructor...
argsToUse = mbd.resolvedConstructorArguments;
if (argsToUse == null) {
argsToResolve = mbd.preparedConstructorArguments;
}
}
}
/**
* 若缓存中存在,那么对参数值进行转换。
* 例如构造函数A(int a,int b),而配置文件中配的是字符串("1","2")
* 那么该方法调用后,结果转化为(1,2)
*/
if (argsToResolve != null) {
argsToUse = resolvePreparedArguments(beanName, mbd, bw, constructorToUse, argsToResolve);
}
}
// 若缓存中没有
if (constructorToUse == null || argsToUse == null) {
// 若getBean的时候传了构造相关参数,则使用它
Constructor<?>[] candidates = chosenCtors;
// 若没有传入,则通过反射来获取相关的构造器
if (candidates == null) {
Class<?> beanClass = mbd.getBeanClass();
try {
candidates = (mbd.isNonPublicAccessAllowed() ?
beanClass.getDeclaredConstructors() : beanClass.getConstructors());
}
// catch...
}
// 调用无参构造
if (candidates.length == 1 && explicitArgs == null && !mbd.hasConstructorArgumentValues()) {
Constructor<?> uniqueCandidate = candidates[0];
if (uniqueCandidate.getParameterCount() == 0) {
synchronized (mbd.constructorArgumentLock) {
mbd.resolvedConstructorOrFactoryMethod = uniqueCandidate;
mbd.constructorArgumentsResolved = true;
mbd.resolvedConstructorArguments = EMPTY_ARGS;
}
bw.setBeanInstance(instantiate(beanName, mbd, uniqueCandidate, EMPTY_ARGS));
return bw;
}
}
// 是否需要解析构造函数
boolean autowiring = (chosenCtors != null ||
mbd.getResolvedAutowireMode() == AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR);
ConstructorArgumentValues resolvedValues = null;
int minNrOfArgs;
if (explicitArgs != null) {
minNrOfArgs = explicitArgs.length;
}
else {
// 提取配置文件中配置的构造函数参数
ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
// 创建一个用于装在 cargs 的一个对象
resolvedValues = new ConstructorArgumentValues();
// 能够解析到的参数个数
minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
}
// 对给定的构造函数进行排序,public类型的构造函数优先。非public的构造则根据参数个数降序排序
AutowireUtils.sortConstructors(candidates);
int minTypeDiffWeight = Integer.MAX_VALUE;
Set<Constructor<?>> ambiguousConstructors = null;
Deque<UnsatisfiedDependencyException> causes = null;
for (Constructor<?> candidate : candidates) {
// 每个构造函数对应的参数个数
int parameterCount = candidate.getParameterCount();
// 若缓存中存在已经解析好的构造函数,同时 解析好的参数的个数(不重复) >当前构造函数所需的参数个数
// 说明当前构造函数无需继续解析,跳出循环即可
if (constructorToUse != null && argsToUse != null && argsToUse.length > parameterCount) {
break;
}
// 个数不相等,跳过本次循环
if (parameterCount < minNrOfArgs) {
continue;
}
ArgumentsHolder argsHolder;
Class<?>[] paramTypes = candidate.getParameterTypes();
// resolvedValues存储了上文读取XML配置的一些参数配置
if (resolvedValues != null) {
try {
// 注释上获取参数名称
String[] paramNames = ConstructorPropertiesChecker.evaluate(candidate, parameterCount);
if (paramNames == null) {
// 获取参数名称处理器。
ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();
if (pnd != null) {
// 获取指定构造函数的参数名称
paramNames = pnd.getParameterNames(candidate);
}
}
// 根据名称和数据类型创建参数的持有者。
argsHolder = createArgumentArray(beanName, mbd, resolvedValues, bw, paramTypes, paramNames,
getUserDeclaredConstructor(candidate), autowiring, candidates.length == 1);
}
// catch...
}
else {
// Explicit arguments given -> arguments length must match exactly.
if (parameterCount != explicitArgs.length) {
continue;
}
// 若构造函数没有参数
argsHolder = new ArgumentsHolder(explicitArgs);
}
// 检验是否存在具有不确定性的构造函数。例如不同构造函数的参数为父子关系。
int typeDiffWeight = (mbd.isLenientConstructorResolution() ?
argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes));
// 若满足,说明当前的构造函数是最匹配的一个,那么它将作为最终的构造函数来调用。
if (typeDiffWeight < minTypeDiffWeight) {
constructorToUse = candidate;
argsHolderToUse = argsHolder;
argsToUse = argsHolder.arguments;
minTypeDiffWeight = typeDiffWeight;
ambiguousConstructors = null;
}
else if (constructorToUse != null && typeDiffWeight == minTypeDiffWeight) {
if (ambiguousConstructors == null) {
ambiguousConstructors = new LinkedHashSet<>();
ambiguousConstructors.add(constructorToUse);
}
ambiguousConstructors.add(candidate);
}
}
if (constructorToUse == null) {
if (causes != null) {
UnsatisfiedDependencyException ex = causes.removeLast();
for (Exception cause : causes) {
this.beanFactory.onSuppressedException(cause);
}
throw ex;
}
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Could not resolve matching constructor on bean class [" + mbd.getBeanClassName() + "] " +
"(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities)");
}
else if (ambiguousConstructors != null && !mbd.isLenientConstructorResolution()) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Ambiguous constructor matches found on bean class [" + mbd.getBeanClassName() + "] " +
"(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities): " +
ambiguousConstructors);
}
// 到这里,构造函数已经解析完成了,同时将其加入到缓存中。
if (explicitArgs == null && argsHolderToUse != null) {
argsHolderToUse.storeCache(mbd, constructorToUse);
}
}
Assert.state(argsToUse != null, "Unresolved constructor arguments");
// 将构建的实例加入到BeanWrapper中
bw.setBeanInstance(instantiate(beanName, mbd, constructorToUse, argsToUse));
return bw;
}
}
代码有点长,让我们来做个概括:
1.确定构造函数参数explicitArgs
:
getBean()
的时候是否传了参数,传了则使用它。XML
配置文件中读取。2.确定构造函数。根据构造函数的参数来匹配对应的构造函数。匹配的过程中会对构造函数进行排序:
public
修饰的在前。3.转换对应的参数类型,确保类型正确。
4.检验构造函数的不确定性。
5.根据实例化的策略和最终确定的构造函数(包括参数)进行实例化Bean
。
protected BeanWrapper instantiateBean(String beanName, RootBeanDefinition mbd) {
try {
Object beanInstance;
if (System.getSecurityManager() != null) {
// 根据实例化策略直接进行实例化
beanInstance = AccessController.doPrivileged(
(PrivilegedAction<Object>) () -> getInstantiationStrategy().instantiate(mbd, beanName, this),
getAccessControlContext());
}
else {
beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, this);
}
// 将实例化完成的对象封装为BeanWrapper
BeanWrapper bw = new BeanWrapperImpl(beanInstance);
// 初始化wrapper
initBeanWrapper(bw);
return bw;
}
// ..catch
}
我们可以发现,两种构造解析,最终对实例进行实例化的时候,都会调用instantiate()
方法。我们来看下这个方法做了什么事情:
public class SimpleInstantiationStrategy implements InstantiationStrategy {
@Override
public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) {
// 如果有 需要覆盖 或者 动态替换的方法 。即lookup和replaced方法
// 那么需要使用cglib进行动态代理,因为其可以再创建代理的同时将动态方法插入类中。
// 若没有,则通过 反射 进行实例化就可以。
if (!bd.hasMethodOverrides()) {
Constructor<?> constructorToUse;
synchronized (bd.constructorArgumentLock) {
constructorToUse = (Constructor<?>) bd.resolvedConstructorOrFactoryMethod;
if (constructorToUse == null) {
final Class<?> clazz = bd.getBeanClass();
if (clazz.isInterface()) {
throw new BeanInstantiationException(clazz, "Specified class is an interface");
}
try {
if (System.getSecurityManager() != null) {
constructorToUse = AccessController.doPrivileged(
(PrivilegedExceptionAction<Constructor<?>>) clazz::getDeclaredConstructor);
}
else {
constructorToUse = clazz.getDeclaredConstructor();
}
bd.resolvedConstructorOrFactoryMethod = constructorToUse;
}
// ..catch
}
}
return BeanUtils.instantiateClass(constructorToUse);
}
else {
// cglib动态代理
return instantiateWithMethodInjection(bd, beanName, owner);
}
}
}
总结下就是实例化分为两种情况:
lookup
和replaced
方法。则进行cglib
动态代理。接下来我们来讲下创建Bean
过程中的第二个重要环节,属性注入。其入口为populateBean()
函数:
public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory
implements AutowireCapableBeanFactory {
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
// 若beanWrapper为null,都不需要属性注入了。若XML配置了相关属性,则需要抛异常。因为不能给一个null对象进行属性注入。
if (bw == null) {
if (mbd.hasPropertyValues()) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
} else {
return;
}
}
// 给InstantiationAwareBeanPostProcessor最后一次机会,在设置属性之前来改变bean
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
if (!bp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
return;
}
}
}
PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
int resolvedAutowireMode = mbd.getResolvedAutowireMode();
// Spring的自动注入有两种方式,根据type。根据name
if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
// 根据名称自动注入
if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);
}
// 根据type自动注入
if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
autowireByType(beanName, mbd, bw, newPvs);
}
pvs = newPvs;
}
// 后处理器是否已经初始化
boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
// 是否需要依赖检查
boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);
PropertyDescriptor[] filteredPds = null;
if (hasInstAwareBpps) {
if (pvs == null) {
pvs = mbd.getPropertyValues();
}
for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
PropertyValues pvsToUse = bp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
if (filteredPds == null) {
filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
}
// 对所有属性进行后处理
pvsToUse = bp.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) {
// 将解析得到的属性封装到bean中
applyPropertyValues(beanName, mbd, bw, pvs);
}
}
}
对上述流程总结下就是:
Bean
进行相关的填充。Name/Type
提取依赖的bean
,并存储于PropertyValues
实例中。InstantiationAwareBeanPostProcessor
处理器对各个属性再进行处理。BeanWrapper
中。我们需要关注的是依赖的提取和处理操作,使用过@Autowired
和@Resource
注解的人我们都知道,一个是根据类型来属性注入,一个是根据名称来属性注入。那么碰巧的是,正好可以在这里对其原理做一个大概的了解。
autowireByName(beanName, mbd, bw, newPvs);
↓↓↓↓↓↓
protected void autowireByName(String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
// 寻找bw中存储的 需要依赖注入的属性
String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
for (String propertyName : propertyNames) {
if (containsBean(propertyName)) {
// 递归初始化bean,根据bean的名称
Object bean = getBean(propertyName);
pvs.add(propertyName, bean);
// 注册依赖
registerDependentBean(propertyName, beanName);
if (logger.isTraceEnabled()) {
logger.trace("Added autowiring by name from bean name '" + beanName +
"' via property '" + propertyName + "' to bean named '" + propertyName + "'");
}
}
else {
// log..
}
}
}
共三步:
getBean(name)
方法进行初始化。Set
集合中)。由于getBean
方法又是我们整篇文章要讲述的,因此我们只需要知道根据名称自动注入的过程中,存在getBean
方法的递归调用即可。
autowireByType(beanName, mbd, bw, newPvs);
↓↓↓↓↓↓
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);
// 1.同样,寻找bw需要依赖注入的属性
String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
for (String propertyName : propertyNames) {
try {
PropertyDescriptor pd = bw.getPropertyDescriptor(propertyName);
if (Object.class != pd.getPropertyType()) {
// 探测指定属性的set方法
MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);
boolean eager = !(bw.getWrappedInstance() instanceof PriorityOrdered);
DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(methodParam, eager);
/**
* 解析beanName匹配的值,并存储在 autowiredBeanNames 集合中。当属性存在多个bean的时候。例如
* @Autowired
* private List list;
* 那么此时会将所有匹配A类的bean注入进来
*/
Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter);
if (autowiredArgument != null) {
pvs.add(propertyName, autowiredArgument);
}
// 递归注册依赖
for (String autowiredBeanName : autowiredBeanNames) {
registerDependentBean(autowiredBeanName, beanName);
// log..
}
autowiredBeanNames.clear();
}
} catch (BeansException ex) {
throw new UnsatisfiedDependencyException(mbd.getResourceDescription(), beanName, propertyName, ex);
}
}
}
概括下就是:
bw
中需要依赖注入的属性。bean
。和通过Name
注入的方式不同的是第二步,我们来看下寻找类型匹配的方法做了什么操作:
Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter);
↓↓↓↓↓↓
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
// 若依赖的bean是Optional类型的
if (Optional.class == descriptor.getDependencyType()) {
return createOptionalDependency(descriptor, requestingBeanName);
}
// 若依赖的bean是ObjectFactory类型的
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 {
Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
descriptor, requestingBeanName);
if (result == null) {
result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
}
return result;
}
}
}
我们来看下通用的处理逻辑doResolveDependency
:
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
// 设置当前的 descriptor,其中存储了方法参数等信息。作为当前的切入点。
InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
try {
Object shortcut = descriptor.resolveShortcut(this);
if (shortcut != null) {
return shortcut;
}
// 从 descriptor 中获取属性类型
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;
}
// 查找符合注入类型的bean
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
if (matchingBeans.isEmpty()) {
// 当符合条件的bean是空的,但是注入的属性又是存在的,那么此时抛异常
if (isRequired(descriptor)) {
raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
}
return null;
}
String autowiredBeanName;
Object instanceCandidate;
// 若查找到多个符合注入类型的bean
if (matchingBeans.size() > 1) {
// 过滤,找到最优的beanName
autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
if (autowiredBeanName == null) {
// 同样,找不到最优的beanName,但是注入的属性又是必须的,同样抛异常
// 或者注入的属性非必须,未过滤前就有多个注入类型的bean。但是注入的属性不是集合,那么同样抛异常。
// 毕竟除集合外,怎么会有一个属性对应多个注入的bean呢?
if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {
return descriptor.resolveNotUnique(descriptor.getResolvableType(), matchingBeans);
}
else {
return null;
}
}
// 根据beanName获取的最优解,来创建属性实例的一个候选者instanceCandidate
instanceCandidate = matchingBeans.get(autowiredBeanName);
}
else {
// 若存在了一对一的情况,那么也不需要去寻找匹配了,直接就用当前的就可以了。
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) {
// 调用了getBean,进行初始化
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);
}
}
}
概括下:
@Value
注解、集合等类型的bean
做特殊处理。findAutowireCandidates
查找符合注入类型的bean
。determineAutowireCandidate
过滤, 找到最优的bean
的候选者。我们来大概了解下上述的两个方法:
protected Map<String, Object> findAutowireCandidates(
@Nullable String beanName, Class<?> requiredType, DependencyDescriptor descriptor) {
// 获取给定类型的所有beanName,包括在父工厂中定义的beanName
String[] candidateNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this, requiredType, true, descriptor.isEager());
Map<String, Object> result = CollectionUtils.newLinkedHashMap(candidateNames.length);
// 先尝试从缓存中寻找。这里的 resolvableDependencies 是已经解析过的缓存,
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;
}
}
}
/**
* isSelfReference:判断是否是自引用。即注入的属性是类本身
* isAutowireCandidate:判断是否有资格作为依赖注入的候选者
* @Bean(autowireCandidate = false)注解的bean就没有资格
*/
for (String candidate : candidateNames) {
if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, descriptor)) {
addCandidateEntry(result, candidate, descriptor, requiredType);
}
}
// 没有符合注入属性类型的beanName
if (result.isEmpty()) {
// 注入的属性是否是bean的集合类型
boolean multiple = indicatesMultipleBeans(requiredType);
// 使用 备用的依赖描述器 再去获取一遍符合注入属性类型的beanName
DependencyDescriptor fallbackDescriptor = descriptor.forFallbackMatch();
for (String candidate : candidateNames) {
if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, fallbackDescriptor) &&
(!multiple || getAutowireCandidateResolver().hasQualifier(descriptor))) {
addCandidateEntry(result, candidate, descriptor, requiredType);
}
}
// 若此时发现还是没有找到符合类型的beanName并且不是集合类型,考虑到自引用的存在
if (result.isEmpty() && !multiple) {
for (String candidate : candidateNames) {
if (isSelfReference(beanName, candidate) &&
(!(descriptor instanceof MultiElementDescriptor) || !beanName.equals(candidate)) &&
isAutowireCandidate(candidate, fallbackDescriptor)) {
addCandidateEntry(result, candidate, descriptor, requiredType);
}
}
}
}
return result;
}
以及determineAutowireCandidate
过滤:
protected String determineAutowireCandidate(Map<String, Object> candidates, DependencyDescriptor descriptor) {
// 1.获取代注入的属性类型
Class<?> requiredType = descriptor.getDependencyType();
// 2.匹配候选bean中是否存在@Primary
String primaryCandidate = determinePrimaryCandidate(candidates, requiredType);
// 3.若匹配成功直接返回
if (primaryCandidate != null) {
return primaryCandidate;
}
// 4.匹配失败,则通过@Priority进行优先级匹配,值越小,优先级越高
String priorityCandidate = determineHighestPriorityCandidate(candidates, requiredType);
if (priorityCandidate != null) {
return priorityCandidate;
}
// 5.若前两者都匹配失败,则匹配beanName是否一致
for (Map.Entry<String, Object> entry : candidates.entrySet()) {
String candidateName = entry.getKey();
Object beanInstance = entry.getValue();
if ((beanInstance != null && this.resolvableDependencies.containsValue(beanInstance)) ||
matchesBeanName(candidateName, descriptor.getDependencyName())) {
return candidateName;
}
}
// 6.否则匹配失败,返回null
return null;
}
总结下就是:
第一点:如何查找符合注入条件的bean
?
bean
。过滤@Qualifier
。以及过滤@Bean(autowireCandidate = false)
注解的bean
。matchingBeans
中。第二点:如何在集合matchingBeans
中匹配到最优解?
@Primary
。@Priority
进行优先级匹配,值越小,优先级越高beanName
是否一致。那么这些最优解得到后,完成初始化的工作,那么属性注入的工作也就完成了。最后一步,我们来看下初始化的过程。
配置bean
的时候,有一个init-method
属性,这个属性的作用是bean
在实例化前调用其指定的方法来完成初始化工作。
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
// 1.1执行aware方法
invokeAwareMethods(beanName, bean);
return null;
}, getAccessControlContext());
} else {
// 1.2对特殊的bean进行处理,例如:Aware、BeanClassLoaderAware、BeanFactoryAware
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
// 2.应用后处理
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
// 3.执行用户自定义的init方法
invokeInitMethods(beanName, wrappedBean, mbd);
}
// ..catch
if (mbd == null || !mbd.isSynthetic()) {
// 应用后处理
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
public class User {
void getName(){
System.out.println("User");
}
}
UserAware
类:需要实现接口BeanFactoryAware
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
public class UserAware implements BeanFactoryAware {
private BeanFactory beanFactory;
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
this.beanFactory=beanFactory;
}
void testAware(){
User user = (User) beanFactory.getBean("user");
user.getName();
}
}
Test
类:
public class Test {
public static void main(String[] args) {
BeanFactory factory = new DefaultListableBeanFactory();
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader((BeanDefinitionRegistry) factory);
ClassPathResource resource = new ClassPathResource("/aware/test.xml");
reader.loadBeanDefinitions(resource);
UserAware user = (UserAware) factory.getBean("userAware");
user.testAware();
}
}
test.xml
文件:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id="userAware" class="com.mytest.aware.UserAware">
bean>
<bean id="user" class="com.mytest.aware.User">
bean>
beans>
Aware
接口的bean
后,可以取得一些相对应的资源。BeanFactoryAware
接口,那么在初始化后,Spring容器会注入BeanFactory
的实例。testAware
方法中,通过beanFactory
实例调用getBean
是可行的。初始化源码中,我们可以发现wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
这段代码执行了两遍,我们来看下他干了什么事情:
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
throws BeansException {
// 代码很简单,递归地调用BeanPostProcessor实现类的postProcessBeforeInitialization方法而已。
// 并将其返回结果作为替代来返回。
Object result = existingBean;
for (BeanPostProcessor processor : getBeanPostProcessors()) {
Object current = processor.postProcessBeforeInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
而至于BeanPostProcessor
处理器,本文就不多展开啦,无非就是在Spring调用自定义的初始化方法的前后时机,允许通过处理器来调用指定的逻辑,实现插拔。
BeanPostProcessor.postProcessBeforeInitialization()
BeanPostProcessor.postProcessAfterInitialization()
调用入口为
invokeInitMethods(beanName, wrappedBean, mbd);
↓↓↓↓↓↓
protected void invokeInitMethods(String beanName, Object bean, @Nullable RootBeanDefinition mbd)
throws Throwable {
// 1.检查是否为InitializingBean,是则调用afterPropertiesSet方法
// 因为Bean可能实现了InitializingBean接口,并且重写了afterPropertiesSet方法。
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
} 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)) {
// 2.调用用户指定的自定义初始化方法。
invokeCustomInitMethod(beanName, bean, mbd);
}
}
}
总结:
Bean
实现了InitializingBean
接口,那么调用其afterPropertiesSet
方法。init-method
方法。Bean
的加载的流程如下getBean()
开始:
1.根据beanName
尝试去缓存中加载。
2.调用getObjectForBeanInstance
方法检测bean
的正确性。主要用于检测当前bean
是否是FactoryBean
类型的bean
。若是FactoryBean
类型,则需要调用其getObject
方法来返回对象。
3.开始创建Bean
,调用createBean
方法分为三大步骤:
创建实例:
createBeanInstance()
,返回BeanWrapper
对象。实例化的方式:
factory-method
,则调用并返回。而构造函数初始化的过程:
explicitArgs
:Bean
。lookup
和replaced
),则通过cglib
动态代理。属性注入:
1.根据Name
自动注入:
getBean(name)
方法进行初始化。Set
集合中)。2.根据Type
自动注入:
bw
中需要依赖注入的属性。bean
,其中的过程包括:查找、过滤1.先从已经解析好的缓存中寻找是否存在。
2.否则检查自引用和排除不符合的
bean
。过滤@Qualifier
。以及过滤@Bean(autowireCandidate = false)
注解的bean
。
3.将符合条件的封装起来,放到集合matchingBeans
中。
4.过滤操作则看是否配置了@Primary
以及@Priority
的大小。
初始化:
xxxAware
接口,则调用对应的方法。BeanPostProcessor
处理器,则在执行自定义初始化方法的前后执行对应的逻辑。init
方法(对应init-method
属性)。最后,我自己整理了下流程图:也希望大家能借此流程图加强对本文的理解。谢谢大家~