前言
在我们前面两章,我们讲完了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();
}
一. Bean的加载
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 {
String beanName = transformedBeanName(name);
Object beanInstance;
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 + "'");
}
}
beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
else {
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
String nameToLookup = originalBeanName(name);
if (parentBeanFactory instanceof AbstractBeanFactory abf) {
return abf.doGetBean(nameToLookup, requiredType, args, typeCheckOnly);
}
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);
}
}
if (!typeCheckOnly) {
markBeanAsCreated(beanName);
}
StartupStep beanCreation = this.applicationStartup.start("spring.beans.instantiate")
.tag("beanName", name);
try {
if (requiredType != null) {
beanCreation.tag("beanType", requiredType::toString);
}
RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dep : dependsOn) {
if (isDependent(beanName, dep)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
registerDependentBean(dep, beanName);
try {
getBean(dep);
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
}
}
}
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 {
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();
}
}
return adaptBeanInstance(name, beanInstance, requiredType);
}
}
上述代码可以做个总结,其大致步骤如下:
- 转换对应
beanName ,传入的参数可能是别名、FactoryBean 。因此需要进行进一步的转换解析。 - 尝试从缓存中加载单例,若有,则可以直接返回。
bean 的实例化。- 检测
ParentBeanFactory ,进行递归。 - 循环依赖检查。
- 将
GenericBeanDefinition 转化为 RootBeanDefinition ,若当前bean 为子bean ,则合并父子BeanDefinition 。 - 寻找依赖,对依赖项进行递归注入。
- 针对不同的
scope 进行bean 的创建。 - 类型转换。
大胆点,我们再简化一下,Bean 的一个加载三步走:
Bean 的实例化。Bean 的相关依赖注入。Bean 的初始化。
对应写出个伪代码:
Object dfs(beanName){
Object bean = getBeanInstance(beanName);
String[] depends = getDependsOn(bean);
for(String name:depends){
dfs(name);
}
return initBean(bean);
}
1.1 FactoryBean的使用
背景:Spring通过反射机制利用bean 的class 属性指定实现类来实例化bean 。但是传统的方式下,需要在<bean> 标签里面配置大量的信息,而XML 配置的这种方式是有局限性的。 若可以通过编码的方式来进行实例化,就能更加自由地实例化一些复杂的bean 。FactoryBean 这个接口就是用来让用户定制自定义实例化的逻辑的。
public interface FactoryBean<T> {
String OBJECT_TYPE_ATTRIBUTE = "factoryBeanObjectType";
@Nullable
T getObject() throws Exception;
@Nullable
Class<?> getObjectType();
default boolean isSingleton() {
return true;
}
}
若配置文件中的<bean> 标签的class 属性配置的实现类是FactoryBean 的实现类的时候,那么通过getBean() 返回的则是FactoryBean.getObject() 方法返回的对象。相当于其代理了getBean 的方法。
案例:FactoryBean的使用和定义
项目结构如下: User 类:
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 文件:
<?xml version="1.0" encoding="UTF-8"?>
<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 的加载。
1.2 缓存中获取单例Bean
Spring在获取bean 的时候,会先从单例缓存中去尝试获取,若还没有,则再去singletonFactories 中加载。
我们来看下这个方法:Object sharedInstance = getSingleton(beanName);
public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
public Object getSingleton(String beanName) {
return getSingleton(beanName, true);
}
↓↓↓↓↓↓
@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
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) {
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
}
}
return singletonObject;
}
}
我们可以看出来,这里Spring有三级的缓存,用来解决循环依赖问题,具体的在下文展开。在此先解释下几种缓存代表的意义:
singletonObjects :保存beanName 和bean 实例(初始化完成的)之间的关系。earlySingletonObjects :同样保存beanName 和bean 实例之间的关系。循环对象依赖列表,用于存储那些发生了循环依赖的对象。singletonFactories :保存beanName 和创建bean 的工厂ObjectFactory 之间的关系。注意和前两者的区别,其存储的并不是bean ,而是负责创建它的工厂。
1.2.1 Spring解决循环依赖的原理☆
接下来我会用大篇幅来讲这个循环依赖的问题,也希望尽量将这一块难题啃下来,也方便日后自己复习,这里参考了这位博主的文章(第二次看了)
我们先来看下循环依赖的一个示意图:这里的类都是单例。 或者是更简单粗暴的:
@Component
public class A{
@Autowired
private A a;
}
那么在这种情况下,就是所谓的循环依赖了。
我们以A ,B 两个类之间的依赖来讲解Spring解决循环依赖的过程。 整体过程如下:
- 实例化
A 。 - 对
A 的属性B 进行注入。 - 对
B 进行实例化。 - 对
B 进行属性注入。 B 完成初始化方法。A 注入完成。则完成初始化方法。
(1) 以A类的角度来观察bean的加载过程。
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) {
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
beforeSingletonCreation(beanName);
boolean newSingleton = false;
boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
if (recordSuppressedExceptions) {
this.suppressedExceptions = new LinkedHashSet<>();
}
try {
singletonObject = singletonFactory.getObject();
newSingleton = true;
}
finally {
if (recordSuppressedExceptions) {
this.suppressedExceptions = null;
}
afterSingletonCreation(beanName);
}
if (newSingleton) {
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;
}
}
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) {
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
Object exposedObject = bean;
try {
populateBean(beanName, mbd, instanceWrapper);
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
if (earlySingletonExposure) {
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 类的属性注入、初始化。
(2) 以B类的角度来观察bean的加载过程。
对于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 {
protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
Object exposedObject = bean;
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);
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
总结下就是: 注意:
- 初始化的时候我们都是对类本身进行初始化,但是在上述过程中,如容器给B
在这里插入代码片 类的注入的属性是A 的代理对象,但是不管是cglib 还是jdk 代理,内部都存储一个目标类的引用。而A 的代理对象就是A 的一个引用。因此代理对象完成了初始化,A 类自然而然完成了初始化。 - 只用二级缓存可以吗?为什么非要用三级缓存去存储一个工厂对象呢?若没有三级缓存,那么在
B 加载环节,就需要其相关属性完成AOP代理。而Spring希望AOP在bena 初始化之后再进行。 因此,通过一个三级缓存,返回一个代理对象(没有完成AOP操作的),让bean 之间完成初始化操作并解决循环依赖问题。最后再遵循Spring的原则,进行AOP代理。
1.2.2 小结
getBean 有两种用途:
- 生成
Bean ,并将其工厂方法存入三级缓存。 - 从单例缓存中去获取
bean 。
此外,我们可以发现,二级缓存就能够实现解决Spring循环依赖的需求,而三级缓存的存在仅仅是提供了一个能够生成代理对象的工厂方法。 那么其目的是什么?
假设我们没有三级缓存,我们的对象并且是单例的。若A 对象依赖的B对象存在AOP机制,即B 对象需要被代理。那么在属性注入的时候,再加入二级缓存之前都需要被代理。这并不合适。 那么如果能够通过第三方的工厂方法,生成一个代理对象丢给二级缓存,就能解决这个问题。
问题来了:为何在存在AOP的情况下,我的实例再加入二级缓存之前就一定要完成代理呢?
- Spring在创建对象的过程中,不知道对象什么时候会被代理, 因此无论当前对象是否需要被代理,总是会提前生成一个普通对象。
- 若二级缓存中存入的是半成品对象(只完成了实例化的),那么当被引用的时候,若发现了存在AOP代理,那么Spring又需要为其创建一个代理对象并返回。此时,二级缓存中的对象和代理对象并不是一个对象。
那么请问:代理对象和二级缓存中的对象不是一个东西,引用不同。那么这种情况下完成对代理对象的初始化之后,原对象完成了吗?
没有,那么通过三级缓存,直接将代理对象(其引用和Spring想要加载的bean 的引用是同一个)返回给二级缓存。那么此时即满足AOP的代理条件,又能够满足Spring的一个初始化过程。
言归正传,到此为止,在讲解bean 的循环依赖的过程中,其实已经顺带把bean 加载的一个过程给过了一遍。但是里面的一些方法我们还没有详细的去了解。
1.3 从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) {
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;
}
if (!(beanInstance instanceof FactoryBean)) {
return beanInstance;
}
Object object = null;
if (mbd != null) {
mbd.isFactoryBean = true;
}
else {
object = getCachedObjectForFactoryBean(beanName);
}
if (object == null) {
FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
if (mbd == null && containsBeanDefinition(beanName)) {
mbd = getMergedLocalBeanDefinition(beanName);
}
boolean synthetic = (mbd != null && mbd.isSynthetic());
object = getObjectFromFactoryBean(factory, beanName, !synthetic);
}
return object;
}
}
再从最后一步的核心代码出发,来看下展开的源码:
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);
Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
if (alreadyThere != null) {
object = alreadyThere;
}
else {
if (shouldPostProcess) {
if (isSingletonCurrentlyInCreation(beanName)) {
return object;
}
beforeSingletonCreation(beanName);
try {
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;
}
}
可以发现最外层的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();
}
}
return object;
}
可以发现无论怎么样,都会执行FactoryBean 的getObject 方法来获取实例对象。本小节实质上并不是特别复杂,通过简化也就是:
- 检验
beanInstance 对象,他是bean 类型还是FactoryBean 类型的实例? - 若是
FactoryBean 类型的,并且以& 为开头,说明用户希望直接获取工厂实例而非工厂方法创建出来的实例对象。 - 若是
bean 类型,直接返回。 - 若是
FactoryBean 类型,不以& 开头,那么就调用其getObject() 方法并返回实例。 - 并且根据条件(是否用户创建),来对该
bean 实例进行后续处理。即后处理器的调用。
Spring在获取bean 的时候有这么一个规则:尽可能保证所有bean 初始化完成后都会调用注册的BeanPostProcessor 的postProcessAfterInitialization 方法进行处理。
紧接着,我们需要将注意力几种在Bean 的一个创建过程。即实例化、属性注入、初始化的这么一个过程。
1.4 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;
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
mbdToUse = new RootBeanDefinition(mbd);
mbdToUse.setBeanClass(resolvedClass);
}
try {
mbdToUse.prepareMethodOverrides();
}
try {
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
}
try {
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
if (logger.isTraceEnabled()) {
logger.trace("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;
}
}
一共有4步:
- 根据设置的
class 属性或者根据className 来解析Class 。 - 对
override 属性进行标记验证。如XML 配置中的lookup-method 和replaced-method 标签。 - 应用初始化前的后处理器,解析指定的
bean 是否存在初始化前的短路操作。 - 创建
bean 。
1.4.1 处理override属性
XML 配置中的lookup-method 和replaced-method 标签。经过Spring容器的读取和转换后,将其存放在BeanDefinition 中的methodOverrides 属性中,而下面的操作就是针对该属性来进行的。
mbdToUse.prepareMethodOverrides();
↓↓↓↓↓
public void prepareMethodOverrides() throws BeanDefinitionValidationException {
if (hasMethodOverrides()) {
getMethodOverrides().getOverrides().forEach(this::prepareMethodOverride);
}
}
↓↓↓↓↓
protected void prepareMethodOverride(MethodOverride mo) throws BeanDefinitionValidationException {
int count = ClassUtils.getMethodCountForName(getBeanClass(), mo.getMethodName());
if (count == 0) {
throw new BeanDefinitionValidationException(
"Invalid method override: no method with name '" + mo.getMethodName() +
"' on class [" + getBeanClassName() + "]");
}
else if (count == 1) {
mo.setOverloaded(false);
}
}
在后续bean 实例化的阶段,若检查到对应的methodOverride 属性,则会动态的为当前bean 生成代理,并使用拦截器为bean 做增强处理(下文介绍)。
1.4.2 实例化的前置处理
Spring-AOP的功能就是基于此进行的,我们来看下这个方法的调用入口:
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
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) {
bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
if (bean != null) {
bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
}
}
}
mbd.beforeInstantiationResolved = (bean != null);
}
return bean;
}
}
备注:
postProcessBeforeInstantiation 方法:在Bean 的自定义初始化方法之前执行。postProcessAfterInitialization 方法:在Bean 的自定义初始化方法之后执行。
紧接着就是最后一个步骤了:
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
代码的展开在上文已经有提及,本章只围绕着三个重点来讲:
createBeanInstance() :创建实例。populateBean() :属性注入。initializeBean() :初始化。
1.4.3 bean实例的创建
源码如下:
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
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);
}
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);
}
}
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 。
(1) autowireConstructor解析
源码如下:
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;
if (explicitArgs != null) {
argsToUse = explicitArgs;
}
else {
Object[] argsToResolve = null;
synchronized (mbd.constructorArgumentLock) {
constructorToUse = (Constructor<?>) mbd.resolvedConstructorOrFactoryMethod;
if (constructorToUse != null && mbd.constructorArgumentsResolved) {
argsToUse = mbd.resolvedConstructorArguments;
if (argsToUse == null) {
argsToResolve = mbd.preparedConstructorArguments;
}
}
}
if (argsToResolve != null) {
argsToUse = resolvePreparedArguments(beanName, mbd, bw, constructorToUse, argsToResolve);
}
}
if (constructorToUse == null || argsToUse == null) {
Constructor<?>[] candidates = chosenCtors;
if (candidates == null) {
Class<?> beanClass = mbd.getBeanClass();
try {
candidates = (mbd.isNonPublicAccessAllowed() ?
beanClass.getDeclaredConstructors() : beanClass.getConstructors());
}
}
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();
resolvedValues = new ConstructorArgumentValues();
minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
}
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();
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);
}
}
else {
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");
bw.setBeanInstance(instantiate(beanName, mbd, constructorToUse, argsToUse));
return bw;
}
}
代码有点长,让我们来做个概括:
1.确定构造函数参数explicitArgs :
- 先看调用
getBean() 的时候是否传了参数,传了则使用它。 - 若未传参数,看缓存中是否存在已经解析好的,若有,则使用它。
- 若前两者都没有,则去
XML 配置文件中读取。
2.确定构造函数。根据构造函数的参数来匹配对应的构造函数。匹配的过程中会对构造函数进行排序:
public 修饰的在前。- 其余的根据参数个数进行排序。
3.转换对应的参数类型,确保类型正确。
4.检验构造函数的不确定性。
5.根据实例化的策略和最终确定的构造函数(包括参数)进行实例化Bean 。
(2) instantiateBean解析
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 bw = new BeanWrapperImpl(beanInstance);
initBeanWrapper(bw);
return bw;
}
}
我们可以发现,两种构造解析,最终对实例进行实例化的时候,都会调用instantiate() 方法。我们来看下这个方法做了什么事情:
public class SimpleInstantiationStrategy implements InstantiationStrategy {
@Override
public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) {
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;
}
}
}
return BeanUtils.instantiateClass(constructorToUse);
}
else {
return instantiateWithMethodInjection(bd, beanName, owner);
}
}
}
总结下就是实例化分为两种情况:
- 正常通过反射进行实例创建。
- 若有 需要覆盖 或者 动态替换的方法 。即
lookup 和replaced 方法。则进行cglib 动态代理。
1.4.4 属性注入
接下来我们来讲下创建Bean 过程中的第二个重要环节,属性注入。其入口为populateBean() 函数:
public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory
implements AutowireCapableBeanFactory {
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 {
return;
}
}
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();
if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);
}
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) {
applyPropertyValues(beanName, mbd, bw, pvs);
}
}
}
对上述流程总结下就是:
- 判断是否需要对
Bean 进行相关的填充。 - 根据
Name/Type 提取依赖的bean ,并存储于PropertyValues 实例中。 - 在填充属性前,通过
InstantiationAwareBeanPostProcessor 处理器对各个属性再进行处理。 - 将最终填充好的属性放到
BeanWrapper 中。
我们需要关注的是依赖的提取和处理操作,使用过@Autowired 和@Resource 注解的人我们都知道,一个是根据类型来属性注入,一个是根据名称来属性注入。那么碰巧的是,正好可以在这里对其原理做一个大概的了解。
(1) 根据Name自动注入
autowireByName(beanName, mbd, bw, newPvs);
↓↓↓↓↓↓
protected void autowireByName(String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
for (String propertyName : propertyNames) {
if (containsBean(propertyName)) {
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 {
}
}
}
共三步:
- 找到需要依赖的属性。
- 递归根据名称来调用
getBean(name) 方法进行初始化。 - 注册依赖(实际就是将对应的依赖名称保存到
Set 集合中)。
由于getBean 方法又是我们整篇文章要讲述的,因此我们只需要知道根据名称自动注入的过程中,存在getBean 方法的递归调用即可。
(2) 根据Type自动注入
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);
String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
for (String propertyName : propertyNames) {
try {
PropertyDescriptor pd = bw.getPropertyDescriptor(propertyName);
if (Object.class != pd.getPropertyType()) {
MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);
boolean eager = !(bw.getWrappedInstance() instanceof PriorityOrdered);
DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(methodParam, eager);
Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter);
if (autowiredArgument != null) {
pvs.add(propertyName, autowiredArgument);
}
for (String autowiredBeanName : autowiredBeanNames) {
registerDependentBean(autowiredBeanName, beanName);
}
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());
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 {
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 {
InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
try {
Object shortcut = descriptor.resolveShortcut(this);
if (shortcut != null) {
return shortcut;
}
Class<?> type = descriptor.getDependencyType();
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) {
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) {
autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
if (autowiredBeanName == null) {
if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {
return descriptor.resolveNotUnique(descriptor.getResolvableType(), matchingBeans);
}
else {
return null;
}
}
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) {
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) {
String[] candidateNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this, requiredType, true, descriptor.isEager());
Map<String, Object> result = CollectionUtils.newLinkedHashMap(candidateNames.length);
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);
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) {
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) {
Class<?> requiredType = descriptor.getDependencyType();
String primaryCandidate = determinePrimaryCandidate(candidates, requiredType);
if (primaryCandidate != null) {
return primaryCandidate;
}
String priorityCandidate = determineHighestPriorityCandidate(candidates, requiredType);
if (priorityCandidate != null) {
return priorityCandidate;
}
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;
}
}
return null;
}
总结下就是: 第一点:如何查找符合注入条件的bean ?
- 先从已经解析好的缓存中寻找是否存在。
- 否则检查自引用和排除不符合的
bean 。过滤@Qualifier 。以及过滤@Bean(autowireCandidate = false) 注解的bean 。 - 将符合条件的封装起来,放到集合
matchingBeans 中。
第二点:如何在集合matchingBeans 中匹配到最优解?
- 匹配
@Primary 。 - 匹配
@Priority 进行优先级匹配,值越小,优先级越高 - 匹配
beanName 是否一致。
那么这些最优解得到后,完成初始化的工作,那么属性注入的工作也就完成了。最后一步,我们来看下初始化的过程。
1.4.5 初始化
配置bean 的时候,有一个init-method 属性,这个属性的作用是bean 在实例化前调用其指定的方法来完成初始化工作。
protected Object initializeBean(String beanName, 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);
}
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
(1) Aware的使用
案例如下: User 类:
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 文件:
<?xml version="1.0" encoding="UTF-8"?>
<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>
结果如下: 什么意思呢?就是说:
- Spring加载了一些 实现了
Aware 接口的bean 后,可以取得一些相对应的资源。 - 例如实现
BeanFactoryAware 接口,那么在初始化后,Spring容器会注入BeanFactory 的实例。 - 因此
testAware 方法中,通过beanFactory 实例调用getBean 是可行的。
(2) 处理器的使用
初始化源码中,我们可以发现wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName); 这段代码执行了两遍,我们来看下他干了什么事情:
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;
}
而至于BeanPostProcessor 处理器,本文就不多展开啦,无非就是在Spring调用自定义的初始化方法的前后时机,允许通过处理器来调用指定的逻辑,实现插拔。
- 调用自定义初始化方法前:
BeanPostProcessor.postProcessBeforeInitialization() - 调用自定义初始化方法后:
BeanPostProcessor.postProcessAfterInitialization()
(3) 自定义init方法调用
调用入口为
invokeInitMethods(beanName, wrappedBean, mbd);
↓↓↓↓↓↓
protected void invokeInitMethods(String beanName, 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());
}
} 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);
}
}
}
总结:
- 初始化方法中我们可以发现,主要调用了两个方法(注意顺序)
- 若
Bean 实现了InitializingBean 接口,那么调用其afterPropertiesSet 方法。 - 最后调用自定义的
init-method 方法。
二. 大总结(带流程图)☆
Bean 的加载的流程如下getBean() 开始:
1.根据beanName 尝试去缓存中加载。
- 三级缓存的目的:在AOP调用的时候解决循环依赖问题。存放的是可以生成代理对象或者本身的工厂方法。
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 属性)。
最后,我自己整理了下流程图:也希望大家能借此流程图加强对本文的理解。谢谢大家~
|