PS:本文参照《Spring源码深度解析2》与spring官方,仅作个人学习
这章分析的是,从容器中获取bean
Student student = (Student)xmlBeanFactory.getBean("student");
@Override
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}
继续往下追踪
/**
* Return an instance, which may be shared or independent, of the specified bean.
* @param name the name of the bean to retrieve
* @param requiredType the required type of the bean to retrieve
* @param args arguments to use when creating a bean instance using explicit arguments
* (only applied when creating a new instance as opposed to retrieving an existing one)
* @param typeCheckOnly whether the instance is obtained for a type check,
* not for actual use
获取实例是否用于类型检查,而不是用于实际使用
* @return an instance of the bean
* @throws BeansException if the bean could not be created
*/
@SuppressWarnings("unchecked")
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
//这里干了两件事
//1、去掉了'&'前缀
//2、从别名映射的aliasMap中获取了当前的beanName。
final String beanName = transformedBeanName(name);
Object bean;
// Eagerly check singleton cache for manually registered singletons.
//从单例对象singletonObjects缓存中获取bean实例或者从singletonFactories的的ObjectFactory中获取
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 + "'");
}
}
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
else {
// Fail if we're already creating this bean instance:
// We're assumably within a circular reference.
//返回指定的原型bean是否正在创建中(在当前线程中)
if (isPrototypeCurrentlyInCreation(beanName)) {
//报错提示,当前Bean正在创建中
throw new BeanCurrentlyInCreationException(beanName);
}
// Check if bean definition exists in this factory.
//获取它的父bean工厂,用于bean继承支持
BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// Not found -> check parent.
String nameToLookup = originalBeanName(name);
if (parentBeanFactory instanceof AbstractBeanFactory) {
return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
nameToLookup, requiredType, args, typeCheckOnly);
}
else if (args != null) {
// Delegation to parent with explicit args.
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else if (requiredType != null) {
// No args -> delegate to standard getBean method.
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
else {
return (T) parentBeanFactory.getBean(nameToLookup);
}
}
//如果不仅仅是做类型检查,要做记录
if (!typeCheckOnly) {
markBeanAsCreated(beanName);
}
try {
//将存储XML配置文件的GernericBeanDefinition转换为RootBeanDefinition,如果指定
//BeanName是子Bean的话同时会合并父类的相关属性
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
// Guarantee initialization of beans that the current bean depends on.
//保证对当前依赖的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);
}
}
}
// Create bean instance.
//Singleton的创建
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, () -> {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
// Explicitly remove instance from singleton cache: It might have been put there
// eagerly by the creation process, to allow for circular reference resolution.
// Also remove any beans that received a temporary reference to the bean.
destroySingleton(beanName);
throw ex;
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
//Prototype模式的创建
else if (mbd.isPrototype模式的创建()) {
// It's a prototype -> create a new instance.
Object prototypeInstance = null;
try {
beforePrototypeCreation(beanName);
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}
else {
String scopeName = mbd.getScope();
final 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);
}
});
bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
}
catch (IllegalStateException ex) {
throw new BeanCreationException(beanName,
"Scope '" + scopeName + "' is not active for the current thread; consider " +
"defining a scoped proxy for this bean if you intend to refer to it from a singleton",
ex);
}
}
}
catch (BeansException ex) {
cleanupAfterBeanCreationFailure(beanName);
throw ex;
}
}
// Check if required type matches the type of the actual bean instance.
//检查需要的类型是否bean的实际类型
if (requiredType != null && !requiredType.isInstance(bean)) {
try {
T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
if (convertedBean == null) {
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
return convertedBean;
}
catch (TypeMismatchException ex) {
if (logger.isTraceEnabled()) {
logger.trace("Failed to convert bean '" + name + "' to required type '" +
ClassUtils.getQualifiedName(requiredType) + "'", ex);
}
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
}
return (T) bean;
}
归纳bean加载的大体思路
1、转换对应beanName
这里传入的可能是别名、或者是FactoryBean,所以需要进行转换的
2、尝试从缓存中加载单例
单例在Spring的同一个容器内只会被创建一次, 后续再获取bean,就直接从单例缓存中获取了。当然这里也只是尝试加载首先尝试从缓存中加载,如果加载不成功则再次尝试从singletonFactories中加载。因为在创建单例bean的时候会存在依赖注人的情况,而在创建依赖的时候为了避免循环依赖,在Spring中创建bean的原则是不等bean创建完成就会将创建bean的ObjectFactory提早曝光加入到缓存中,一旦下一个bean创建时候需要依赖上一个bean则直接使用ObjectFactory
3、Bean的实例化
如果从缓存中得到了bean 的原始状态,则需要对bean进行实例化。这里有必要强调- -下,缓存中记录的只是最原始bean状态,并不- -定 是我们最终想要的bean。举个例子,假如我们需要对工厂bean进行处理,那么这里得到的其实是工厂bean 的初始状态,但是我们真正需要的是工厂bean中定义的factory-method方法中返回的bean,getObjectForBeanInstance就是完成这个工作的,后续会详细讲解。
4、原型模式的依赖检查
只有在单例情况下才会尝试解决循环依赖,如果存在A中有B的属性,B中有A的属性,那么当依赖注入的时候,就会产生当A还未创建完的时候因为对于B的创建再次返回创建A,造成循环依赖,也就是情况: isPrototypeCurrentlyInCreation(beanName)判断 true。
5、检测parentBeanFactory
从代码上看,如果缓存没有数据的话直接转到父类工厂上去加载了 ,这是为什么呢?可能读者忽略了-个很重要的判断条件: parentBeanFactory != null && !containsBean Definition(beanName),parentBeanFactory != null。 parentBeanFactory 如果为空,则其他一切都是浮云,这个没什么说的,但是!containsBeanDefinition(beanName)就比较重要 了,它是在检测如果当前加载的XML配置文件中不包含beanName所对应的配置,就只能到parentBeanFactory去尝试下了,然后再去递归的调用getBean方法。
6.将存储XML配置文件的GernericBeanDefinition转换为RootBeanDefinition
因为从XML配置文件中读取到的bean信息是存储在GernericBeanDefinition 中的,但是所
有的bean后续处理都是针对于RootBeanDefinition的,所以这里需要进行一个转换 ,转换的同时
如果父类bean不为空的话,则会-并 合并父类的属性。
7.寻找依赖
因为bean的初始化过程中很可能会用到某些属性,而某些属性很可能是动态配置的,并且配置成依赖于其他的bean,那么这个时候就有必要先加载依赖的bean,所以,在Spring的加载顺寻中,在初始化某一个bean的时候首先会初始化这个bean所对应的依赖。
8.针对不同的scope进行bean的创建
我们都知道,在Spring中存在着不同的scope,其中默认的是singleton,但是还有些其他的配置诸如prototype、request之类的。在这个步骤中,Spring会根据不同的配置进行不同的初始化策略。
9.类型转换
程序到这里返回bean后已经基本结束了,通常对该方法的调用参数requiredType是为空的,但是可能会存在这样的情况,返回的bean其实是个String, 但是requiredType 却传人Integer类型,那么这时候本步骤就会起作用了,它的功能是将返回的bean转换为requiredType所指定的类型。当然,String 转换为Integer是最简单的一种转换, 在Spring中提供了各种各样的转换器,用户也可以自己扩展转换器来满足需求。
先看下源码
public interface FactoryBean<T> {
/**
* 获取当前对象
*/
@Nullable
T getObject() throws Exception;
/**
*获取当前对象类型
*/
@Nullable
Class<?> getObjectType();
/**
*是不是单例的
*/
default boolean isSingleton() {
return true;
}
FactoryBean
- 指的是特定于spring的FactoryBean实现类。
- 它是一个工厂Bean,且有泛型FactoryBean存在,则表示可以生成某一个指定类型的Bean。
从第二条我们就可以得出,FactoryBean 的主要目的就是暴露处理,让我们自定义创建Bean的过程
BeanFactory
当然我们在自己写案例之前呢,可以先随便找一个FactoryBean 的使用案例,毕竟人家有70多个实现类,先看下源码中是怎么对它使用的。
此处拿BeanListFactoryBean为例
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//
package org.springframework.plugin.core.support;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
public class BeanListFactoryBean<T> extends AbstractTypeAwareSupport<T> implements FactoryBean<List<T>> {
private static final Comparator<Object> COMPARATOR = new AnnotationAwareOrderComparator();
public BeanListFactoryBean() {
}
public List<T> getObject() {
//先创建了一个List对象
List<T> beans = new ArrayList();
beans.addAll(this.getBeans());
//对list中的bean进行排序
Collections.sort(beans, COMPARATOR);
//返回了创建的对象
return beans;
}
public Class<?> getObjectType() {
return List.class;
}
public boolean isSingleton() {
return true;
}
}
代码量是不是特别少,先了解下该类主要是干嘛的?
Simple factory for shared List instances. Allows for central setup of Lists via the “list” element in XML bean definitions.
这句话的大概意思就是说可以将XML中配置的List映射到Ben中
<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-2.5.xsd">
<bean id="BusBean" class="com.trg.common.Customer">
<property name="lists">
<bean class="org.springframework.beans.factory.config.ListFactoryBean">
<property name="targetListClass">
<value>java.util.ArrayList</value>
</property>
<property name="sourceList">
<list>
<value>bus1</value>
<value>bus2</value>
<value>bus3</value>
</list>
</property>
</bean>
</property>
</bean>
</beans>
就是类似与这种,可以加载到Bean中。
现在我们可以自定义一个实现了
先创建一个自定义组件
package com.trg.custom;
public class Person {
private String name;
private String height;
..../省略
}
再创建一个实现类
package com.trg.custom;
import org.springframework.beans.factory.FactoryBean;
public class CustomFactoryBean implements FactoryBean<Person> {
private String personInfo;
public String getPersonInfo() {
return personInfo;
}
public void setPersonInfo(String personInfo) {
this.personInfo = personInfo;
}
@Override
public Person getObject() throws Exception {
System.out.println("当前进入Bean的创建");
String[] split = personInfo.split(",");
Person person = new Person();
person.setName(split[0]);
person.setHeight(split[1]);
return person;
}
@Override
public Class<?> getObjectType() {
return Person.class;
}
@Override
public boolean isSingleton() {
return true;
}
}
进行配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:custom="http://www.trg.com/schema/user"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd>
<bean id="person" class="com.trg.custom.CustomFactoryBean" >
<property name="personInfo" value="trg,110"/>
</bean>
</beans>
测试
void testFactoryBean(){
XmlBeanFactory xmlBeanFactory = new XmlBeanFactory(new ClassPathResource("beanFactoryTest.xml"));
Person person = xmlBeanFactory.getBean(Person.class);
System.out.println(person);
}
结果
16:01:05.794 [main] DEBUG org.springframework.beans.factory.xml.XmlBeanFactory - Creating shared instance of singleton bean 'person'
当前进入Bean的创建
Person{name='trg', height='110'}
单例bean?
单例bean在spring的容器中只会创建一次,后续再获取bean直接从单例缓存中获取。
这里也只是尝试加载,首先尝试从缓存中加载,然后再次尝试从singletonFactories中加载。
因为在创建单例bean的时候会存在依赖注人的情况,而在创建依赖的时候为了避免循环依赖,
Spring创建bean的原则是不等bean创建完成就会将创建bean的ObjectFactory提早曝光加入到
缓存中,一旦下一个bean创建时需要依赖上个bean,则直接使用ObjectFactory。
上代码
public Object getSingleton(String beanName) {
//参数true标识允许早期依赖
return getSingleton(beanName, true);
}
继续追踪
@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
//首先从单例对象的缓存中去尝试性的获取
Object singletonObject = this.singletonObjects.get(beanName);
//没有获取到,且当前Bean正在创建中
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
synchronized (this.singletonObjects) {
//早期单例对象的缓存中去获取对象
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
//当某些方法在初始化的时候,会调用addSingletonFactory方法将singletonFactory存储起来
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
//取出单例对象
singletonObject = singletonFactory.getObject();
//存到缓存中
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
return singletonObject;
}
isSingletonCurrentlyInCreation(beanName)?
该bean是否在创建中。在Spring中,会有个专门的属性默认为DefaultSingletonBeanRegistry的singletonsCurrentlyInCreation来记录bean的加载状态,在bean开始创建前会将beanName记录在属性中,在bean创建结束后将beanName从属性中移除。这个状态是在哪里记录的呢?不同scope的记录位置并不一样,我们以singleton为例,在singleton下记录属性的函数是在DefaultSingletonBeanRegistry类的public Object getSingleton(String beanName, ObjectFactory singletonFactory)函数的beforeSingletonCreation(beanName)和 aftersingletonCreation(beanName)中,在这两段函数中分别由 this.singletonsCurrentlyInCreation.add(beanName) 与 this.singletonsCurrentlyInCreation.remove(beanName)来进行状态的记录与移除。
这段代码主要是从三个位置取获取了实例对象
先从singletonObjects中获取,获取不到则earlySingletonObjects中继续取获取,第三次获取是从singletonFactories中获取的,然后调用getObject()方法来创建bean的
上面有几个不同的Map,进行分析
singletonObjects:用于保存BeanName和创建bean实例之间的关系, bean name -> bean instance。
singletonFactories: 用于保存BeanName和创建bean的工厂之间的关系,bean name ->ObjectFactory。
earlySingletonObjects:也是保存BeanName 和创建bean 实例之间的关系,与singletonObjects的不同之处在于,当一个 单例bean被放到这里面后,那么当bean 还.在创建过程中,就可以通过getBean方法获取到了,其目的是 用来检测循环引用。
registeredSingletons:用来保存当前所有已注册的bean。
在getBean方法中,getObjectForBeanInstance 是个高频率使用的方法,无论是从缓存中获得bean还是根据不同的scope策略加载bean。总之,我们得到bean的实例后要做的第一步就是调用这个方法来检测一下正确性,其实就是用于检测当前bean 是否是FactoryBean类型的bean,如果是,那么需要调用该bean对应的FactoryBean 实例中的getObject()作为返回值
无论是从缓存中获取到的bean还是通过不同的scope策略加载的bean都只是最原始的bean状态,并不一定是我们最终想要的bean。举个例子,假如我们需要对工厂”bean 进行处理,那么这里得到的其实是工厂bean 的初始状态,但是我们真正需要的是工厂bean 中定义的factory-method方法中返回的bean,而getObjectForBeanInstance方法就是完成这个工作的。
追一下getObjectForBeanInstance()方法
/**
* Get the object for the given bean instance, either the bean
* instance itself or its created object in case of a FactoryBean.
* @param beanInstance the shared bean instance
* @param name name that may include factory dereference prefix
* @param beanName the canonical bean name
* @param mbd the merged bean definition
* @return the object to expose for the bean
*/
protected Object getObjectForBeanInstance(
Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
// Don't let calling code try to dereference the factory if the bean isn't a factory.
//这里是验证了指定的bean是不是工厂相关(&开头)且bean是不是为空
if (BeanFactoryUtils.isFactoryDereference(name)) {
if (beanInstance instanceof NullBean) {
return beanInstance;
}
if (!(beanInstance instanceof FactoryBean)) {
throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass());
}
if (mbd != null) {
mbd.isFactoryBean = true;
}
return beanInstance;
}
// Now we have the bean instance, which may be a normal bean or a FactoryBean.
// If it's a FactoryBean, we use it to create a bean instance, unless the
// caller actually wants a reference to the factory.
//校验beanInstance是不是FactoryBean的类型
if (!(beanInstance是不是 instanceof FactoryBean的)) {
return beanInstance;
}
//加载FactoryBean的
Object object = null;
if (mbd != null) {
mbd.isFactoryBean = true;
}
else {
//尝试从缓存中加载
object = getCachedObjectForFactoryBean(beanName);
}
if (object == null) {
//到这里已经明确知道beanInstance 一定是FactoryBean类型
// Return bean instance from factory.
FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
// Caches object obtained from FactoryBean if it is a singleton.
//containsBeanDefinition 检测beanDefinit ionMap中也就是在所有已经加载的类中检测
//是否定义beanName
if (mbd == null && containsBeanDefinition(beanName)) {
//将存储XML配置文件的GernericBeanDefinition转换为RootBeanDefinition,如
//果指定BeanName是子Bean的话同时会合并父类的相关属性
mbd = getMergedLocalBeanDefinition(beanName);
}
//是不是用户自定义的而不是程序本身的
boolean synthetic = (mbd != null && mbd.isSynthetic());
object = getObjectFromFactoryBean(factory, beanName, !synthetic);
}
return object;
}
当前函数主要的功能是?
我们继续追一下getObjectFromFactoryBean()函数
/**
* Obtain an object to expose from the given FactoryBean.
* @param factory the FactoryBean instance
* @param beanName the name of the bean
* @param shouldPostProcess whether the bean is subject to post-processing
* @return the object obtained from the FactoryBean
* @throws BeanCreationException if FactoryBean object creation failed
* @see org.springframework.beans.factory.FactoryBean#getObject()
*/
protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
synchronized (getSingletonMutex()) {
Object object = this.factoryBeanObjectCache.get(beanName);
if (object == null) {
object = doGetObjectFromFactoryBean(factory, beanName);
// Only post-process and store if not put there already during getObject() call above
// (e.g. because of circular reference processing triggered by custom getBean calls)
Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
if (alreadyThere != null) {
object = alreadyThere;
}
else {
if (shouldPostProcess) {
if (isSingletonCurrentlyInCreation(beanName)) {
// Temporarily return non-post-processed object, not storing it yet..
return object;
}
beforeSingletonCreation(beanName);
try {
object = postProcessObjectFromFactoryBean(object, beanName);
}
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);
}
}
return object;
}
}
在这个代码中我们还是没有看到想要看到的代码,在这个方法里只做了一件事情,就是返回的bean 如果是单例的,那就必须要保证全局唯一,同时,也因为是单例的,所以不必重复创建,可以使用缓存来提高性能,也就是说已经加载过就要记录下来以便于下次复用,否则的话就直接获取了。
在doGetObjectFromFactoryBean方法中我们终于看到了我们]想要看到的方法,也就是object =
factory.getObject(),是的,就是这句代码,我们的历程犹如剥洋葱- -样,一层一层的直到最内
部的代码实现,虽然很简单。
/**
* Obtain an object to expose from the given FactoryBean.
* @param factory the FactoryBean instance
* @param beanName the name of the bean
* @return the object obtained from the FactoryBean
* @throws BeanCreationException if FactoryBean object creation failed
* @see org.springframework.beans.factory.FactoryBean#getObject()
*/
private Object doGetObjectFromFactoryBean(final FactoryBean<?> factory, final 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 {
//直接调用getObject()方法
object = factory.getObject()方法();
}
}
// Do not accept a null value for a FactoryBean that's not fully
// initialized yet: Many FactoryBeans just return null then.
if (object == null) {
if (isSingletonCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(
beanName, "FactoryBean which is currently in creation returned null from getObject");
}
object = new NullBean();
}
return object;
}
上面我们已经讲述了FactoryBean 的调用方法,如果bean声明为FactoryBean 类型,则当提取bean时提取的并不是FactoryBean,而是FactoryBean 中对应的getObject方法返回的bean,而doGetObjectFromFactoryBean正是实现这个功能的。但是,我们看到在上面的方法中除了调用object = factory.getObjectO得 到我们想要的结果后并没有直接返回,而是接下来又做了些后处理的操作,这个又是做什么用的呢?于是我们跟踪进人AbstractAutowireCapableBeanFactory类的postProcessObjectFromFactoryBean方法:
对于后处理器的使用我们还未过多接触,后续章节会使用大量篇幅介绍,这里,我们只需
了解在Spring获取bean的规则中有这样- - 条:尽可能保证所有bean初始化后都会调用注册的
BeanPostProcessor的postProcessAfterlnitialization 方法进行处理,在实际开发过程中大可以针
对此特性设计自己的业务逻辑。
前面我们都是从缓存中获取单例的过程,如果缓存中不存在,则需要开始bean的加载了,而实现这个从操作的就是函数getSingleton()
/**返回在给定名称下注册的(原始)单例对象,如果还没有注册,则创建并注册一个新的单例对象。
* Return the (raw) singleton object registered under the given name,
* creating and registering a new one if none registered yet.
* @param beanName the name of the bean
* @param singletonFactory the ObjectFactory to lazily create the singleton
* with, if necessary
* @return the registered singleton object
*/
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(beanName, "Bean name must not be null");
synchronized (this.singletonObjects) {
//先检查单例对象的缓存中是否存在当前bean,存在则直接返回,不存在则进行创建并注册
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
//校验当前单例对象是否正在创建中
if (this.singletonsCurrentlyInDestruction) {
throw new BeanCreationNotAllowedException(beanName,
"Singleton bean creation not allowed while singletons of this factory are in destruction " +
"(Do not request a bean from a BeanFactory in a destroy method implementation!)");
}
if (logger.isDebugEnabled()) {
logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
}
//初始化bean之前的操作
beforeSingletonCreation(beanName);
boolean newSingleton = false;
boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
if (recordSuppressedExceptions) {
this.suppressedExceptions = new LinkedHashSet<>();
}
try {
//初始化bean
singletonObject = singletonFactory.getObject();
newSingleton = true;
}
finally {
if (recordSuppressedExceptions) {
this.suppressedExceptions = null;
}
//初始化之后的操作
afterSingletonCreation(beanName);
}
if (newSingleton) {
//加入到缓存中
addSingleton(beanName, singletonObject);
}
}
return singletonObject;
}
}
上面代码中可以知道,真正在获取单例 bean的方法不是在此方法中实现的,而是在ObjectFactory中的singletonFactory中实现的
那么以上代码主要干了那些事?
先检查了 singletonObjects缓存中是否已经被加载过了,若已加载,则直接返回
若没有加载,则记录beanName正在加载的状态
加载单例前记录加载状态
protected void beforeSingletonCreation(String beanName) {
if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
}
通过这里this.singletonsCurrentlyInCreation.add(beanName)对加载状态进行了 记录
4.通过方法的参数传人的ObjectFactory的个体Object方法实例化bean。
5.加载单例后的处理方法调用
这里与第三步挺相似的, 第三步是当初始化之前进行缓存,相当于mark,表面我要开始了,然后这里对第三步的缓存进行移除,表明我已经操作完成了。
protected void afterSingletonCreation(String beanName) {
if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.remove(beanName)) {
throw new IllegalStateException("Singleton '" + beanName + "' isn't currently in creation");
}
}
6.将初始化的bean进行记录,并且对删除bean加载过程中所记录的各种辅助状态
protected void addSingleton(String beanName, Object singletonObject) {
synchronized (this.singletonObjects) {
//对象缓存
this.singletonObjects.put(beanName, singletonObject);
//单例工厂的缓存
this.singletonFactories.remove(beanName);
//早期单例对象的缓存
this.earlySingletonObjects.remove(beanName);
//一组已注册的单例, 按注册顺序排列的bean名称。
this.registeredSingletons.add(beanName);
}
}
7.返回处理结果
本节主要研究这个函数createBean()
sharedInstance = getSingleton(beanName, () -> {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
destroySingleton(beanName);
throw ex;
}
});
/**
* Central method of this class: creates a bean instance,
* populates the bean instance, applies post-processors, etc.
* @see #doCreateBean
*/
@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
if (logger.isTraceEnabled()) {
logger.trace("Creating instance of bean '" + beanName + "'");
}
RootBeanDefinition mbdToUse = mbd;
// 根据提供的beanName来
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
mbdToUse = new RootBeanDefinition(mbd);
mbdToUse.setBeanClass(resolvedClass);
}
// Prepare method overrides.
try {
//验证及准备覆盖的方法
mbdToUse.prepareMethodOverrides();
}
try {
// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
}
catch (Throwable ex) {
throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
"BeanPostProcessor before instantiation of bean failed", ex);
}
try {
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
if (logger.isTraceEnabled()) {
logger.trace("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;
}
catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
// A previously detected exception with proper bean creation context already,
// or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.
throw ex;
}
catch (Throwable ex) {
throw new BeanCreationException(
mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
}
}
从代码中我们可以总结出函数完成的具体步骤及功能。
1.根据设置的class属性或者根据clasName来解析Class。
2.对override属性进行标记及验证。
很多读者可能会不知道这个方法的作用,因为在Spring的配置里面根本就没有诸如override-method之类的配置,那么这个方法到底是干什么用的呢?
其实在Spring中确实没有override-method这样的配置,但是如果读过前面的部分,可能会有所发现,在Spring配置中是存在lookup-method和replace -method的,而这两个配置的加载其实就是将配置统一存放 在BeanDefinition中的methodOverrides属性里,而这个函数的操作其实也就是针对于这两个配置的。
3.应用初始化前的后处理器,解析指定bean是否存在初始化前的短路操作。
4.创建bean。
我们首先查看下对override属性标记及验证的逻辑实现。
/**验证并准备为该bean定义的方法覆盖。检查是否存在具有指定名称的方法
* Validate and prepare the method overrides defined for this bean.
* Checks for existence of a method with the specified name.
* @throws BeanDefinitionValidationException in case of validation failure
*/
public void prepareMethodOverrides() throws BeanDefinitionValidationException {
// Check that lookup methods exist and determine their overloaded status.
//检查查找方法是否存在,并确定它们的重载状态
if (hasMethodOverrides()) {
getMethodOverrides().getOverrides().forEach(this::prepareMethodOverride);
}
}
/**
* Validate and prepare the given method override.
* Checks for existence of a method with the specified name,
* marking it as not overloaded if none found.
* @param mo the MethodOverride object to validate
* @throws BeanDefinitionValidationException in case of validation failure
*/
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) {
// Mark override as not overloaded, to avoid the overhead of arg type checking.
//标记MethodOverride暂未被覆盖,避免参数类型检查的开销。
mo.setOverloaded(false);
}
}
这里有必要先了解一下两个属性:
<lookup-method>lookup-method>
<replaced-method>replaced-method>
可以参考下:https://blog.csdn.net/qq_22912803/article/details/52503914
而这两个配置的加载其实就是将配置统一存放在BeanDefinition中的methodOverrides属性里,这两个功能实现原理其实是在bean实例化的时候如果检测到存在methodOverrides属性,会动态地为当前bean生成代理并使用对应的拦截器为bean做增强处理,相关逻辑实现在bean的实例化部分详细介绍。
但是,这里要提到的是,对于方法的匹配来讲,如果-一个类中存在若千个重载方法,那么,在函数调用及增强的时候还需要根据参数类型进行匹配,来最终确认当前调用的到底是哪个函数。但是,Spring 将-部分匹配工作在这里完成了,如果当前类中的方法只有一个,那么就设置重载该方法没有被重载,这样在后续调用的时候便可以直接使用找到的方法,而不需要进行方法的参数匹配验证了,而且还可以提前对方法存在性进行验证,正可谓- -箭双雕 。
//实例化的前置处理
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
这里当经过前置处理后,如果返回的bean不为空,则会忽略后面的创建而直接返回。
大概追一下这个前置处理的方法
/**:应用实例化之前的后处理器,解析指定bean是否有实例化之前的快捷方式
* Apply before-instantiation post-processors, resolving whether there is a
* before-instantiation shortcut for the specified bean.
* @param beanName the name of the bean
* @param mbd the bean definition for the bean
* @return the shortcut-determined bean instance, or {@code null} if none
*/
@Nullable
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
Object bean = null;
//如果尚未被解析
if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
// Make sure bean class is actually resolved at this point.
//确保bean类在此时已实际解析
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;
}
这里主要看下下面的两个方法
bean的实例化前调用,也就是将AbsractBeanDefinition转换为BeanWrapper前的处理。给子类一个修改BeanDefinition的机会,也就是说当程序经过这个方法后,bean 可能已经不是我们认为的bean了,而是或许成为了一个经过处理的代理bean,可能是通过cglib生成的,也可能是通过其他技术生成的。
protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
if (result != null) {
return result;
}
}
}
return null;
}
从缓存中获取单例bean的时候就提到过,Spring 中的规则是在bean的初始化后尽可能保证将注册的后处理器的postProcessAfterInitialization方法应用到该bean中,因为如果返回的bean不为空,那么便不会再次经历普通bean的创建过程,所以只能在这里应用后处理器的postProcessAfterInitialization方法。
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor processor : getBeanPostProcessors()) {
Object current = processor.postProcessAfterInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
先说下循环依赖和循环调用的区别:
循环调用是指A方法调用了B方法,B方法调用了C方法,然后C方法又调用了A方法,这种一旦开始调用,除非又终结条件,不然就是死循环了。
循环依赖指的是A类依赖了B类,B类依赖了C类,C又依赖了A类
注意:调用是指方法之间的关系,依赖是指类之间的关系
spring的循环依赖分类
如在创建TestA类时,构造器需要TestB类,那将去创建TestB,在创建TestB类时又发现需要TestC类,则又去创建TestC,最终在创建TestC时发现又需要TestA,从而形成一个环,没办法创建。
Spring容器将每一个正在创建的bean标识符放在-一个“当前创建bean池”中,bean标识符在创建过程中将一直保持在这 个池中,因此如果在创建bean过程中发现自己已经在“当前创建bean池”里时,将抛出BeanCurrentlyInCreationException异常表示循环依赖;而对于创建完毕的bean将从“当前创建bean池”中清除掉。
表示通过setter注入方式构成的循环依赖。对于setter注人造成的依赖是通过Spring容器提前暴露刚完成构造器注人但未完成其他步骤(如setter注人)的bean来完成的,而且只能解决单例作用域的bean循环依赖。通过提前暴露一个单例工厂 方法,从而使其他bean能引用到该bean
具体步骤如下。
对于“prototype" 作用域bean, Spring 容器无法完成依赖注人,因为Spring容器不进行缓存“prototype”作用域的bean,因此无法提前暴露一个创建中的 bean。
对于“singleton”作用域bean,可以通过“setAllowCircularReferences(false );”来禁用循环
引用。
/**
* Actually create the specified bean. Pre-creation processing has already happened
* at this point, e.g. checking {@code postProcessBeforeInstantiation} callbacks.
* Differentiates between default bean instantiation, use of a
* factory method, and autowiring a constructor.
* @param beanName the name of the bean
* @param mbd the merged bean definition for the bean
* @param args explicit arguments to use for constructor or factory method invocation
* @return a new instance of the bean
* @throws BeanCreationException if the bean could not be created
* @see #instantiateBean
* @see #instantiateUsingFactoryMethod
* @see #autowireConstructor
*/
protected Object doCreateBean(final String beanName, final RootBeanDefinition转换成 mbd, final @Nullable Object[] args)
throws BeanCreationException {
// Instantiate the bean.
BeanWrapper instanceWrapper = null;
//1、如果是单例,则需要清除缓存
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
//2、实例化bean,将BeanDefinition转换成BeanWrapper
if (instanceWrapper == null) {
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
final Object bean = instanceWrapper.getWrappedInstance();
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
mbd.resolvedTargetType = beanType;
}
// Allow post-processors to modify the merged bean definition.
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
try {
//3、bean合并后的处理,Autowired正是通过此方法实现诸如类型的预解析
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
}
mbd.postProcessed = true;
}
}
// Eagerly cache singletons to be able to resolve circular references
// even when triggered by lifecycle interfaces like BeanFactoryAware.
// 4、依赖处理
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
if (logger.isTraceEnabled()) {
logger.trace("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
// Initialize the bean instance.
Object exposedObject = bean;
try {
// 5、属性填充
populateBean(beanName, mbd, instanceWrapper);
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
catch (Throwable ex) {
if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
throw (BeanCreationException) ex;
}
else {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
}
}
if (earlySingletonExposure) {
Object earlySingletonReference = getSingleton(beanName, false);
//6、循环依赖检查
if (earlySingletonReference != null) {
if (exposedObject == bean) {
exposedObject = earlySingletonReference;
}
else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
String[] dependentBeans = getDependentBeans(beanName);
Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
for (String dependentBean : dependentBeans) {
if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
actualDependentBeans.add(dependentBean);
}
}
if (!actualDependentBeans.isEmpty()) {
}
}
}
}
// Register bean as disposable.
try {
// 7、注册DisposableBean。
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
return exposedObject;
}
以上函数的步骤:
1、如果是单例,则需要清除缓存
2、实例化bean,将BeanDefinition转换成BeanWrapper
3、bean合并后的处理,Autowired正是通过此方法实现诸如类型的预解析
4、依赖处理
在Spring中会有循环依赖的情况,例如,当A中含有B的属性,而B中又含有A的属性
时就会构成-一个循环依赖,此时如果A和B都是单例,那么在Spring中的处理方式就是当创
建B的时候,涉及自动注人A的步骤时,并不是直接去再次创建A,而是通过放人缓存中的
ObjectFactory来创建实例,这样就解决了循环依赖的问题。
5、属性填充。将所有属性填充至bean的实例中
6、循环依赖检查
在这个步骤里会检测已经加载的bean是否已经出现了依赖循环,并判断是否需要抛出异常
7、注册DisposableBean。
如果配置了destroy-method, 这里需要注册以便于在销毁时候调用。
8、完成创建并返回。
可以看到上面的步骤非常的繁琐,每一步 骤都使用了大量的代码来完成其功能,最复杂
也是最难以理解的当属循环依赖的处理,在真正进人doCreateBean前我们有必要先了解下循
环依赖。
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
// Make sure bean class is actually resolved at this point.
//将bean类名称解析为class并将解析后的class存储在bean定义中
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());
}
//获取供给型的接口,直接创建bean
Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
if (instanceSupplier != null) {
return obtainFromSupplier(instanceSupplier, beanName);
}
//通过构造方法创建对象
if (mbd.getFactoryMethodName() != null) {
return instantiateUsingFactoryMethod(beanName, mbd, args);
}
// Shortcut when re-creating the same bean...
//使用容器的自动装配方法进行实例化
boolean resolved = false;
boolean autowireNecessary = false;
if (args == null) {
synchronized (mbd.constructorArgumentLock) {
//一个类有多个构造函数,且每个构造函数有多个参数,所以调用先需要根据参数锁定构造函数或者对应的工厂方法。
if (mbd.resolvedConstructorOrFactoryMethod != null) {
resolved = true;
autowireNecessary = mbd.constructorArgumentsResolved;
}
}
}
// 如果已经解析过,则使用解析好的构造函数方法不需要再次锁定
if (resolved) {
if (autowireNecessary) {
//构造函数自动注入
return autowireConstructor(beanName, mbd, null, null);
}
else {
//使用默认构造函数构造
return instantiateBean(beanName, mbd);
}
}
// Candidate constructors for autowiring?
// 使用了Bean的构造方法进行实例化 | 需要根据参数解析构造函数
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
return autowireConstructor(beanName, mbd, ctors, args);
}
// Preferred constructors for default construction?
ctors = mbd.getPreferredConstructors();
if (ctors != null) {
//构造函数自动注入
return autowireConstructor(beanName, mbd, ctors, null);
}
//使用默认构造函数构造
// No special handling: simply use no-arg constructor.
return instantiateBean(beanName, mbd);
}
当我们在xml中配置 了factory-method后,factory-method的值会被记录到RootBeanDefinition的getFactoryMethodName()中,那么spring会尝试使用instantiateUsingFactoryMethod(beanName, mbd, args);方法根据RootBeanDefinition的配置去生成bean的实例。
可以使用java8提供的函数式接口编程,提供一个回调函数,直接调用回调函数,不再需要反射的方式创建bean的实例
这里可以参考下:https://blog.csdn.net/duxd185120/article/details/109224025
解析构造器并通过构造器进行实例化。
每个构造函数的参数不同,Spring在根据参数及类型去判断最终会使用哪个构造函数
进行实例化。但是,判断的过程是个比较消耗性能的步骤,所以采用缓存机制,如果已经解析过则
不需要重复解析而是直接从RootBeanDefinition中的属性resolvedConstructorOrFactoryMethod缓存
的值去取,否则需要再次解析,并将解析的结果添加至RootBeanDefinition 中的属性
resolvedConstructorOrFactoryMethod中。
以下对构造函数自动注入和默认构造函数的部分再进行追一下源码,看下他们的实现
先说下这里在调试的时候对应的配置,
xml配置中需要加入带参构造器注入的配置,如下
<bean id="student" class="com.trg.entity.Student" >
<constructor-arg name="name" value="trg"/>
<constructor-arg name="age" value="25"/>
bean>
注意这句源码注释@return a BeanWrapper for the new instance,说明这个方法最终会返回一个BeanWrapper,BeanWrapper可以操作Bean的实例,这个方法要传入四个参数,分别是bean的名字,RootBeanDefination,推断出来的构造方法数组,方法参数
public BeanWrapper autowireConstructor(String beanName, RootBeanDefinition mbd,
@Nullable Constructor<?>[] chosenCtors, @Nullable Object[] explicitArgs) {
//提前先实例化一个BeanWrapperImpl,后面会进行返回
BeanWrapperImpl bw = new BeanWrapperImpl();
this.beanFactory.initBeanWrapper(bw);
//存储构造方法的相关信息
Constructor<?> constructorToUse = null;
//构造函数要用到的参数和值
ArgumentsHolder argsHolderToUse = null;
//这个里面其实是存储了构造器的参数值
Object[] argsToUse = null;
//确定参数值列表的
//explicitArgs通过构造器getBean的方法传入
①
if (explicitArgs != null) {
//如果我们在调用getBean的时候传入了参数(构造器的参数),则会在这里进行存储
//想要走这里,注意在getBean的时候传入有参构造器的参数
argsToUse = explicitArgs;
}
else {
//很明显,这里就是从xml配置文件的constructor-arg中去获取构造器的参数列表的值
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;
}
}
}
if (argsToResolve != null) {
argsToUse = resolvePreparedArguments(beanName, mbd, bw, constructorToUse, argsToResolve, true);
}
}
②
if (constructorToUse == null || argsToUse == null) {
//先确认Constructor中已经得到了当前bean的构造器信息
// Take specified constructors, if any.
Constructor<?>[] candidates = chosenCtors;
if (candidates == null) {
Class<?> beanClass = mbd.getBeanClass();//class com.trg.entity.Student
try {
//如果当前bean的构造器是public的,则通过反射的方式返回所有的构造函数,如果是私有的则返回的是此类公共构造方法的 Constructor 对象数组
candidates = (mbd.isNonPublicAccessAllowed() ?
beanClass.getDeclaredConstructors() : beanClass.getConstructors());
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Resolution of declared constructors on bean Class [" + beanClass.getName() +
"] from ClassLoader [" + beanClass.getClassLoader() + "] failed", ex);
}
}
//只有一个构造器,且在getBaen的时候没有传构造器参数,且RootBeanDefinition没有构造器参数
//这里没看懂!mbd.hasConstructorArgumentValues()条件
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;
}
}
//开始解析构造函数
// Need to resolve the constructor.
//如果没有已经解析的构造方法
//则需要去解析构造方法
// Need to resolve the constructor.
//判断构造方法是否为空,判断是否根据构造方法自动注入
boolean autowiring = (chosenCtors为Null, != null ||
mbd.getResolvedAutowireMode() == AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR);
ConstructorArgumentValues resolvedValues = null;
//传进来的参数有几个
//这里我们配置了两个构造器,那么它就是2
int minNrOfArgs;
if (explicitArgs != null) {
//这里也是去校验我们在调用getBean()的时候,有没有传入参数,如果传入了则直接取他们的长度就行了
minNrOfArgs = explicitArgs.length;
}
else {
//这里是自己去获取我们传入了几个参数
//提取了以下配置文件中配置的构造器的参数
ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
//用于承载解析后的构造参数的值
resolvedValues = new ConstructorArgumentValues();
minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
}
//对所有的构造器进行了一个排序
//排序规则:排序给定的构造函数,public 构造函数优先参数数量降序、非public构造函数参数数量降序
AutowireUtils.sortConstructors(candidates);
int minTypeDiffWeight = Integer.MAX_VALUE;
Set<Constructor<?>> ambiguousConstructors = null;
LinkedList<UnsatisfiedDependencyException> causes = null;
//遍历获取到的所有构造参数,其实要找和minNrOfArgs对应的构造函数
for (Constructor<?> candidate : candidates) {
③ //看下这个构造函数有几个参数
int parameterCount = candidate.getParameterCount();
//如果已经找到选用的构造函数或者需要的参数个数小于当前的构造函数参数个数则终止,
//因为已经按照参数个数降序排列
if (constructorToUse != null && argsToUse != null && argsToUse.length > parameterCount) {
// Already found greedy constructor that can be satisfied ->
// do not look any further, there are only less greedy constructors left.
break;
}
//做了一个判断,如果当前构造函数的参数要比当前bean的传进来的参数少,那当前构造器就不看了
if (parameterCount < minNrOfArgs) {
continue;
}
ArgumentsHolder argsHolder;
//获取构造函数的的参数类别
Class<?>[] paramTypes = candidate.getParameterTypes();
//当前构造器的参数不为Null
if (resolvedValues != null) {
try {
//注释上获取参数名称
String[] paramNames = ConstructorPropertiesChecker.evaluate(candidate, parameterCount);
if (paramNames == null) {
//获取参数名称解析器
ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();
if (pnd != null) {
//获取指定构造函数的参数名称
//这里将会解析出构造器参数["name","age"]
paramNames = pnd.getParameterNames(candidate);
}
}
//根据名称和数据类型创建参数持有者
argsHolder = createArgumentArray(beanName, mbd, resolvedValues, bw, paramTypes, paramNames,
getUserDeclaredConstructor(candidate), autowiring, candidates.length == 1);
}
}
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));
// Choose this constructor if it represents the closest match.
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 " +
"(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 in bean '" + beanName + "' " +
"(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");
//将构建的实例存到函数开头创建的BeanWrapperImpl中
⑤ bw.setBeanInstance(instantiate(beanName, mbd, constructorToUse, argsToUse));
return bw;
}
拓展知识点:
getDeclaredConstructor()与getConstructor的区别?
第一个是获取所有的构造器,第二个是只获取public的构造器
这里有个疑问
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;
}
}
这里if在判断的时候,mbd为RootBeanDefinition,可以存储父类的BeanDefinition信息,也可以存储当前类的BeanDefinition信息,很明显,这里存储的是当前类的BeanDefinition信息。
!mbd.hasConstructorArgumentValues()这里是校验如果当前BeanDefinition没有构造器参数的话就成立。思考一下,没有构造器参数的情况,那就是默认的无参构造器了,如果我们在使用无参构造器的话,那autowireConstructor()方法就进不来了啊,这个判断甚是没看懂。
上面计算权重的代码可以参考下当前文章:https://www.jianshu.com/p/dc1b53dc97b9
函数归纳:
先确认了构造函数的参数
根据explicitArgs获取,这个是在调用getBean方法的时候传入的。
从缓存resolvedConstructorArguments中获取
配置文件获取
配置文件中的信息经过转换都会通过BeanDefinition实例承载,也就是参数mbd中包含,那么
可以通过调用mbd.getConstructorArgumentValues()来 获取配置的构造函数信息。有了配置中的
信息便可以获取对应的参数值信息了,获取参数值的信息包括直接指定值,如:直接指定构造
函数中某个值为原始类型String 类型,或者是-一个对其他bean 的引用,而这一处理委托给
resolveConstructorArguments方法,并返回能解析到的参数的个数。
构造函数的确认
经过了第一步后已经确定了构造函数的参数,接下来的任务就是根据构造函数参数在所有
构造函数中锁定对应的构造函数,而匹配的方法就是根据参数个数匹配,所以在匹配之前需要
先对构造函数按照public构造函数优先参数数量降序、非public构造函数参数数量降序。这样
可以在遍历的情况下迅速判断排在后面的构造函数参数个数是否符合条件。
由于在配置文件中并不是唯- -限制使用参数位置索引的方式去创建,同样还支持指定参数
名称进行设定参数值的情况,如,那么这种情况就需要首先确定构
造函数中的参数名称。
获取参数名称可以有两种方式,一种是通过注解的方式直接获取,另一种就是使用Spring
中提供的工具类ParameterNameDiscoverer 来获取。构造函数、参数名称、参数类型、参数值
都确定后就可以锁定构造函数以及转换对应的参数类型了。
这里可能说的比较含糊,总结一句话就是用构造器函数的参数与当前bean中的所有构造器进行一一比对,参数类型和个数一致,则表示锁定了构造器
根据确定的构造函数转换对应的参数类型
构造函数不确定性的验证
当然,有时候即使构造函数、参数名称、参数类型、参数值都确定后也不一-定会直接锁定
构造函数,不同构造函数的参数为父子关系,所以Spring 在最后又做了一次验证。
根据实例化策略以及得到的构造函数以及构造函数参数实例化bean
<bean id="student" class="com.trg.entity.Student" >
bean>
/**
* Instantiate the given bean using its default constructor.
* @param beanName the name of the bean
* @param mbd the bean definition for the bean
* @return a BeanWrapper for the new instance
*/
protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) {
try {
Object beanInstance;
final BeanFactory parent = this;
//获取权限验证
if (System.getSecurityManager() != null) {
beanInstance = AccessController.doPrivileged((PrivilegedAction<Object>) () ->
getInstantiationStrategy().instantiate(mbd, beanName, parent),
getAccessControlContext());
}
else {
//直接进行实例化
beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);
}
//然后赋值给了BeanWrapper
BeanWrapper bw = new BeanWrapperImpl(beanInstance);
initBeanWrapper(bw);
return bw;
}
catch (Throwable ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);
}
}
无参构造器的实例化bean其实没啥, 有参构造器的实例化bean主要麻烦在寻找构造器参数和对应构造器的匹配上了
有参构造器的实例化
@Override
public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner,
final Constructor<?> ctor, Object... args) {
if (!bd.hasMethodOverrides()) {
if (System.getSecurityManager() != null) {
// use own privileged to change accessibility (when security is on)
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
ReflectionUtils.makeAccessible(ctor);
return null;
});
}
return BeanUtils.instantiateClass(ctor, args);
}
else {
return instantiateWithMethodInjection(bd, beanName, owner, ctor, args);
}
}
无参构造器 的实例化
@Override
public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) {
// Don't override the class with CGLIB if no overrides.
// 如果没有覆盖,不要用CGLIB覆盖类。
if (!bd.hasMethodOverrides()) {
Constructor<?> constructorToUse;
synchronized (bd.constructorArgumentLock) {
//获取当前bean的构造方法
constructorToUse = (Constructor<?>) bd.resolvedConstructorOrFactoryMethod;
if (constructorToUse == null) {
//获取当前bean的全类名
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 (Throwable ex) {
throw new BeanInstantiationException(clazz, "No default constructor found", ex);
}
}
}
//通过构造函数来实例化这个bean
return BeanUtils.instantiateClass(constructorToUse);
}
else {
// Must generate CGLIB subclass.
return instantiateWithMethodInjection(bd, beanName, owner);
}
}
第一个有参构造器的实例化, 是直接将构造器给传入了进来,第二个还去找了下构造,都是最后通过构造器来实例化bean的
在doCreate中有这段代码:
// Eagerly cache singletons to be able to resolve circular references
// even when triggered by lifecycle interfaces like BeanFactoryAware.
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
if (logger.isTraceEnabled()) {
logger.trace("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
mbd.isSingleton():检查这个bean是不是单例的。
thisallowCircularReferences:是否允许循环依赖,很抱歉,并没有找到在配置文件中
如何配置,但是在AbstractRefreshableApplicationContext 中提供了设置函数,可以通
过硬编码的方式进行设置或者可以通过自定义命名空间进行配置,其中硬编码的方式
代码如下。
ClassPathXmlApplicationContext bf = new ClassPathXmlApplicationContext ("aspectTest . xml");
bf . setAllowBeanDe finit ionOverriding (false) ;
isSingletonCurrentlyInCreation(beanName)):当前bean是否正在创建中。在Spring中,会有
个专门的属性默认为DefaultSingletonBeanRegistry的singletonsCurrentlyInCreation来记
录bean的加载状态,在bean开始创建前会将beanName记录在属性中,在bean创建
结束后会将beanName 从属性中移除。那么我们跟随代码一路走来可是对这个属性的
记录并没有多少印象,这个状态是在哪里记录的呢?不同scope的记录位置并不一样,
我们以singleton为例,在singleton下记录属性的函数是在DefaultSingletonBeanRegistry
类的public Object getSingleton(String beanName, ObjectFactory singletonFactory)函数
的beforeSingletonCreation(beanName)和 afterSingletonCreation(beanName)中, 在这两段函
数中分别thissingletonsCurrentlyInCreation.add(beanName)与thissingletonsCurentlyIn-
Creation.remove(beanName)来进行状态的记录与移除。
当以上三个条件都满足的时候,才会执行addSingletonFactory方法的。先研究以下addSingletonFactory是啥?
拿之前说的简单的AB依赖循环为例来说
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NZSjZKtA-1630660854663)(D:\tool\Typora\data\Spring源码\image\AB类的依赖循环创建.png)]
这里当我们在创建beanA 的时候,会先记录A所对应的beanNameA,并将beanA 的创建工厂加入缓存中,当我们填充属性B的时候,会去创建beanB,同理,它也会记录B所对应的beanNameB,并将beanB的创建工厂加入到缓存中,
注意,当beanB在填充属性A的时候,我们会去创建beanA嘛?
其实,当依赖加载这种属性的时候,都会先去缓存中检测以下是不是已经有了我们创建好的bean,或者是否已经有创建好的ObjectFactory,而这里此时A的ObjectFactpry已经创建好了,所以就直接调用ObjectFactpry去创建A了
/** 获取用于早期访问指定bean的引用,通常用于解析循环引用。
* Obtain a reference for early access to the specified bean,
* typically for the purpose of resolving a circular reference.
* @param beanName the name of the bean (for error handling purposes)
* @param mbd the merged bean definition for the bean
* @param bean the raw bean instance
* @return the object to expose as bean reference
*/
protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
Object exposedObject = bean;
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
}
}
}
return exposedObject;
}
在getEarlyBeanReference函数中并没有太多的逻辑处理,或者说除了后处理器的调用外没有别的处理工作,根据以上分析,基本可以理清Spring 处理循环依赖的解决办法,在B中创建依赖A时通过ObjectFactory提供的实例化方法来中断A中的属性填充,使B中持有的A仅仅是刚刚初始化并没有填充任何属性的A,而这正初始化A的步骤还是在最开始创建A的时候进行的,但是因为A与B中的A所表示的属性地址是- -样的,所以在A中创建好的属性填充自然可以通过B中的A获取,这样就解决了循环依赖的问题。
测试代码,记得在javabean中加入一个依赖类
<bean id="user" class="com.trg.User">
<property name="name" value="tangruiguo">property>
<property name="email" value="[email protected]">property>
bean>
<bean id="student" class="com.trg.entity.Student" autowire="byType">
<property name="name" value="trg"/>
<property name="age" value="25"/>
bean>
populateBean(beanName, mbd, instanceWrapper);
/**使用来自bean定义的属性值填充给定BeanWrapper中的bean实例。
大概意思就是将beanDefinition中的值填充给了BeanWrapper
* Populate the bean instance in the given BeanWrapper with the property values
* from the bean definition.
* @param beanName the name of the bean
* @param mbd the bean definition for the bean
* @param bw the BeanWrapper with bean instance
*/
@SuppressWarnings("deprecation") // for postProcessPropertyValues
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
//先对BeanWrapper进行校验,如果为Null,则不能对他进行赋值了
if (bw == null) {
if (mbd.hasPropertyValues()) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
}
else {
// Skip property population phase for null instance.
return;
}
}
// Give any InstantiationAwareBeanPostProcessors the opportunity to modify the
// state of the bean before properties are set. This can be used, for example,
// to support styles of field injection.
//****给InstantiationAwareBeanPostProcessors最后一次机会在属性设置前来改变bean
//如:可以用来支持属性注人的类型
//检查用户是否有注册 InstantiationAwareBeanPostProcessor,如果有,使用责任链模式激活这些后置器中的postProcessAfterInstantiation方法,如果某个后置处理器返回了false,那么Spring就不会执行框架的自动装配逻辑了.官方的建议是不建议去扩展此后置处理器,而是推荐扩展自BeanPostProcessor或从InstantiationAwareBeanPostProcessorAdapter派生.
① //否是"synthetic"。一般是指只有AOP相关的prointCut配置或者Advice配置才会将 synthetic设置为true
//如果mdb是不是'syntheic' 且 工厂拥有InstiationAwareBeanPostProcessor
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
return;
}
}
}
}
//获取beanDefinition中为bean设置的属性值。这里找的是基本类型的属性
② PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
// 根据Bean配置的依赖注入方式完成注入,默认是0,即不走以下逻辑
// 如果设置了相关的依赖装配方式,会遍历Bean的属性,根据type或者name完成相应注入
int resolvedAutowireMode = mbd.getResolvedAutowireMode();
if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
// Add property values based on autowire by name if applicable.
if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);
}
// Add property values based on autowire by type if applicable.
if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
autowireByType(beanName, mbd, bw, newPvs);
}
pvs = newPvs;
}
// 容器是否注册了InstantiationAwareBeanPostProcessors
boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
// 是否进行依赖检查,默认为false
boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);
PropertyDescriptor[] filteredPds = null;
if (hasInstAwareBpps) {
if (pvs == null) {
pvs = mbd.getPropertyValues();
}
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
// 对@AutoWired标记的属性进行依赖注入
PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
if (filteredPds == null) {
filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
}
// 对解析完未设置的属性再进行处理
pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
return;
}
}
pvs = pvsToUse;
}
}
}
if (needsDepCheck) {
if (filteredPds == null) {
filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
}
checkDependencies(beanName, mbd, filteredPds, pvs);
}
if (pvs != null) {
//将属性应用到bean中
applyPropertyValues(beanName, mbd, bw, pvs);
}
}
InstantiationAwareBeanPostProcessor 处理器的postProcessAfterInstantiation 函数的应用,
此函数可以控制程序是否继续进行属性填充。
可以参考:https://blog.csdn.net/qq_38526573/article/details/88091702
根据注人类型( byName/byType ),提取依赖的bean,并统一存人PropertyValues中。
应用InstantiationAwareBeanPostProcessor处理器的postrocesSPropertyValues方法,对属性
获取完毕填充前对属性的再次处理,典型应用是RequiredAnnotationBeanPostProcessor 类中对
属性的验证。
将所有PropertyValues中的属性填充至BeanWrapper中。
针对以上,我们将研究以下依赖注入和属性填充
先了解一下几种注入方式:
AbstractBeanDefinition类中提供了几个常量:
0 AUTOWIRE_NO 没有显式配置上装配的方式
1 AUTOWIRE_BY_NAME 根据name自动装配
2 AUTOWIRE_BY_TYPE 根据type自动装配
3 AUTOWIRE_CONSTRUCTOR 根据构造器自动装配
MutablePropertyValues:PropertyValues接口的默认实现。允许简单操作属性,并提供构造函数来支持从Map进行深拷贝和构造
先清楚,这里是怎么进去的
如果是XML文件,则在bean的属性中配置autowired属性
如果是java类,则默认配置为@Bean(autowired=Autowired.BY_NAME)
第一个先看下autowireByName方法
/**如果自动装配设置为“byName”,则使用对该工厂中其他bean的引用来填充任何丢失的属性值。
* Fill in any missing property values with references to
* other beans in this factory if autowire is set to "byName".
* @param beanName the name of the bean we're wiring up.
* Useful for debugging messages; not used functionally.
* @param mbd bean definition to update through autowiring
* @param bw the BeanWrapper from which we can obtain information about the bean
* @param pvs the PropertyValues to register wired objects with
*/
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
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 {
if (logger.isTraceEnabled()) {
logger.trace("Not autowiring property '" + propertyName + "' of bean '" + beanName +
"' by name: no matching bean found");
}
}
}
}
/**
* Abstract method defining "autowire by type" (bean properties by type) behavior.
* This is like PicoContainer default, in which there must be exactly one bean
* of the property type in the bean factory. This makes bean factories simple to
* configure for small namespaces, but doesn't work as well as standard Spring
* behavior for bigger applications.
* @param beanName the name of the bean to autowire by type
* @param mbd the merged bean definition to update through autowiring
* @param bw the BeanWrapper from which we can obtain information about the bean
* @param pvs the PropertyValues to register wired objects with
*/
protected void autowireByType(
String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
//TypeConverter:定义类型转换方法的接口。通常(但不一定)是与PropertyEditorRegistry接口一起实现的。 //获取工厂的自定义类型转换器
TypeConverter converter = getCustomTypeConverter();
if (converter == null) {
//如果没有配置自定义类型转换器,使用bw作为类型转换器
converter = bw;
}
Set<String> autowiredBeanNames = new LinkedHashSet<>(4);
//注意,这里其实找的是那些个对象类型,并不是去找基本类型
String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
for (String propertyName : propertyNames) {
try {
//属性描述信息
PropertyDescriptor pd = bw.getPropertyDescriptor(propertyName);
// Don't try autowiring by type for type Object: never makes sense,
// even if it technically is a unsatisfied, non-simple property.
//这里判断获取到的属性不能是Object类型
if (Object.class != pd.getPropertyType()) {
//获取到set方法的参数属性包装对象,就是找到了set方法
MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);
// Do not allow eager init for type matching in case of a prioritized post-processor.
//eger为true时会导致初始化lazy-init单例和由FactoryBeans(或带有"factory-bean"引用的工厂方法)创建 的对象以进行类型检查
boolean eager = !(bw.getWrappedInstance() instanceof PriorityOrdered);
//AutowireByTypeDependencyDescriptor:根据类型依赖自动注入的描述符,重写了 getDependencyName() 方法,使其永远返回null
//将 methodParam 封装包装成AutowireByTypeDependencyDescriptor对象
DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(methodParam, eager);
//寻找类型匹配
//解析指定beanName的属性所匹配的值,并把解析到的属性名称存储在
//autowiredBeanNames中,当属性存在多个封装bean时如:
//@Autowired private List alist; 将会找到所有匹配A类型的bean并将
Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter);
if (autowiredArgument != null) {
pvs.add(propertyName, autowiredArgument);
}
for (String autowiredBeanName : autowiredBeanNames) {
registerDependentBean(autowiredBeanName, beanName);
if (logger.isTraceEnabled()) {
logger.trace("Autowiring by type from bean name '" + beanName + "' via property '" +
propertyName + "' to bean named '" + autowiredBeanName + "'");
}
}
autowiredBeanNames.clear();
}
}
catch (BeansException ex) {
throw new UnsatisfiedDependencyException(mbd.getResourceDescription(), beanName, propertyName, ex);
}
}
}
了解一下,它是怎么去找对象类型的数据 的
protected String[] unsatisfiedNonSimpleProperties(AbstractBeanDefinition mbd, BeanWrapper bw) {
Set<String> result = new TreeSet<>();
//这里还是只获取了基本类型的属性
PropertyValues pvs = mbd.getPropertyValues();
//获取所有的包装对象
//经过测试,发现这里其实是找javabean中定义的setter/getter方法的,这两个setter/getter是
//算一个的,我试着删除get方法,也能通过set找到的。
//这里是从beanWapper中找到,也可以理解是从javabean中找到,并不是从容器中找的
PropertyDescriptor[] pds = bw.getPropertyDescriptors();
for (PropertyDescriptor pd : pds) {
//pd.getWriteMethod():获取的set方法不为null
//isExcludedFromDependencyCheck:该pd不是被排除在依赖项检查之外
//pvs.contains(pd.getName())
//BeanUtils.isSimpleProperty(pd.getPropertyType()):pd的属性类型不是SimpleProperty类型
if (pd.getWriteMethod() != null && !isExcludedFromDependencyCheck(pd) && !pvs.contains(pd.getName()) &&
!BeanUtils.isSimpleProperty(pd.getPropertyType())) {
//都满足以上条件,就添加到result中,其实还是在找除基本类型外的属性
result.add(pd.getName());
}
}
return StringUtils.toStringArray(result);
}
注意将属性值全部获取后属性是以PropertyValues存在的,还没有被应用到已经实例化的bean中,这一工作是在applyPropetyValues中完成,有兴趣的可以自己看下源码
综上:
byType :
从BeanWrapper中寻找需要依赖注入的属性,然后遍历这些属性并寻找类型匹配的bean。这里查找类型匹配bean的时候是在容器的上下文中查找的。
byName :
从BeanWrapper中寻找需要依赖注入的属性,然后找到和自己对象后面的值对应的bean的id属性
init-method:在bean实例化前来调用init-method所指定的方法。
注意:这里测试的时候要在配置文件中添加属性
init-method= "init"
主要体现代码:
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareMethods(beanName, bean);
return null;
}, getAccessControlContext());
}
else {
//对特殊的bean处理: Aware、BeanClassLoaderAware. BeanFactoryAware
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
//应用后处理器
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
//激活用户自定义的init方法
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
if (mbd == null || !mbd.isSynthetic()) {
//后处理器应用
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
它是怎么去激活用户自定义的init方法的?
1、通过方法的名称init和全类名构造了一个initMethod(Method)类
2、从自身或者父类获取自身接口方法,返回methodToInvoke
3、然后进行invoke
Spring 中提供一些Aware相关接口,比如BeanFactoryAware、ApplicationContextAware 、ResourceL oaderAware、ServletContextAware 等,实现这些Aware接口的bean在被初始之后,可以取得一些相对应的资源, 例如实现BeanFactoryAware的bean在初始后,Spring 容器将会注人BeanFactory的实例,而实现ApplicationContextAware的bean,在bean被初始后,将会被注人ApplicationContext 的实例等。我们首先通过示例方法来了解一下Aware
的使用。
package com.trg.entity;
import com.trg.User;
import com.trg.custom.Person;
import org.springframework.beans.factory.annotation.Autowired;
public class Student {
/* public Student(String name,int age){
this.name = name;
this.age = age;
}
*/
private String name;
private int age;
.....//
public void testAware(){
System.out.println("test Aware method");
}
}
创建一个实现了BeanFactoryAware的方法:
package com.trg;
import com.trg.entity.Student;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
public class TestAware implements BeanFactoryAware {
private BeanFactory beanFactory;
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
this.beanFactory = beanFactory;
}
public void testA() {
Student student = (Student) beanFactory.getBean("student");
student.testAware();
}
}
测试:
XmlBeanFactory xmlBeanFactory = new XmlBeanFactory(new ClassPathResource("META-INF/beanFactoryTest.xml"));
Student student = (Student)xmlBeanFactory.getBean("student");
student.testAware();
System.out.print(student);
得到结果
test Aware method
Student{name='trg', age=25}
相信根据这个实例,我们可以去查看其它的XXXAware方法了
BeanPostProcessor相信大家都不陌生,这是Spring中开放式架构中一个必不可少的亮点,给用户充足的权限去更改或者扩展Spring, 而除了BeanPostrocessor 外还有很多其他的PostProcessor,当然大部分都是以此为基础,继承自BeanPostProcessor。 BeanPostProcessor 的使用位置就是这里,在调用客户自定义初始化方法前以及调用自定义初始化方法后分别会调用BeanPostProcessor的postProcessBeforelnitialization 和postProcessAfterlnitialization方法,使用户可以根据自己的业务需求进行响应的处理。
用户自己定制的init方法除了上面这种使用init-method的方法之外,还可以实现InitializingBean接口的afterPropertiesSet方法来自定义初始化方法。注意实现接口的这种方式在上面配置init-method之前进行调用。
案例:
package com.trg.entity;
import com.trg.User;
import com.trg.custom.Person;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
public class Student implements InitializingBean {
/* public Student(String name,int age){
this.name = name;
this.age = age;
}
*/
private String name;
private int age;
@Autowired
private Person person;
private User user;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Person getPerson() {
return person;
}
public void setPerson(Person person) {
this.person = person;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public void init(){
System.out.println("init的init-method方法调用中。。。。");
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", person=" + person +
", user=" + user +
'}';
}
public void testAware(){
System.out.println("test Aware method");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("init的实现接口的方法方法调用中。。。。");
}
}
xml中配置bean
调用结果如下:
init的实现接口的方法方法调用中。。。。
init的init-method方法调用中。。。。
test Aware method
看源码就可以知道为什么是先去查看是否是实现了接口的方式
//#AbstractAutowireCapableBeanFactory
protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd)
throws Throwable {
//先确认当前类是不是实现了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 (PrivilegedActionException pae) {
throw pae.getException();
}
}
else {
((InitializingBean) bean).afterPropertiesSet();
}
}
if (mbd != null && bean.getClass() != NullBean.class) {
String initMethodName = mbd.getInitMethodName();
if (StringUtils.hasLength(initMethodName) &&
!(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
!mbd.isExternallyManagedInitMethod(initMethodName)) {
invokeCustomInitMethod(beanName, bean, mbd);
}
}
}
这个方法就实现了这两个步骤的初始化操作
/**将给定bean添加到该工厂中的一次性bean列表中,注册其disablebean接口和/或给定的destroy方法,以便在工厂 关闭时调用(如果适用)。只适用于单例。
* Add the given bean to the list of disposable beans in this factory,
* registering its DisposableBean interface and/or the given destroy method
* to be called on factory shutdown (if applicable). Only applies to singletons.
* @param beanName the name of the bean
* @param bean the bean instance
* @param mbd the bean definition for the bean
* @see RootBeanDefinition#isSingleton
* @see RootBeanDefinition#getDependsOn
* @see #registerDisposableBean
* @see #registerDependentBean
*/
protected void registerDisposableBeanIfNecessary(String beanName, Object bean, RootBeanDefinition mbd) {
AccessControlContext acc = (System.getSecurityManager() != null ? getAccessControlContext() : null);
//如果当前bean不是Prototype且要求在bean关闭的时候进行销毁
if (!mbd.isPrototype() && requiresDestruction(bean, mbd)) {
//如果bean是单例的作用域
if (mbd.isSingleton()) {
// Register a DisposableBean implementation that performs all destruction
// work for the given bean: DestructionAwareBeanPostProcessors,
// DisposableBean interface, custom destroy method.
//单例模式下注册需要销毁的bean,此方法中会处理实现DisposableBean的bean,
//并且对所有的bean使用Destructi onAwa reBeanPostProcessors处理
DisposableBean Dest ruct ionAwa reBeanPost Processors,
registerDisposableBean(beanName,
new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));
}
else {
// A bean with a custom scope...
//自定义scope
Scope scope = this.scopes.get(mbd.getScope());
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope name '" + mbd.getScope() + "'");
}
scope.registerDestructionCallback(beanName,
new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));
}
}
}