作者:京东科技 韩国凯
通过本文,读者能够 0 源码根底的初步学习 spring 源码,并可能触类旁通从此进入源码世界的大米!
因为是第一次浏览源码,文章之中不免存在一些问题,还望包涵斧正!
文章 demo 源码:http://xingyun.jd.com/codingR…
一、@Autowired 与 @Resource 的区别
用一句话总结两者的区别就是:@Autowired 会先通过类型注入,即 byType,当存在有 多个类型 时会通过名称注入。@Resource 则相同,会先通过名称注入,即 byName,当名称不存在或有多个名称时 会通过类型注入。
那么通过名称注入与通过类型注入有什么区别呢?
// 创立接口
interface StuService{String getName();
}
@Service
//Stu2 实现接口并注册 bean
class Stu2 implements StuService{
@Override
public String getName() {return "stu2";}
}
@Service
//Stu3 实现接口并注册 bean
class Stu3 implements StuService{
@Override
public String getName() {return "stu3";}
}
1.1 @Autowired
那么此时如果咱们对 StuService
注入,@Autowired 能够抉择注入的类型就有两个,别离是 Stu2
与 Stu3
。
须要留神的是,类型有很多种抉择:
- 当注册 bean 与获取 bean 为同一个类时,类型只有这个类自身。
例如,咱们有获取 session 的工具类,须要将其注入到 spring 之中,
@Component
class SessionUtil{public String getSession(){return "session";}
}
只有一个类,间接注册 bean,应用时能够任意抉择
@Autowired
SessionUtil sessionUtil;
此时 @Autowired 只有一个注册类型,间接注入。
- 当注册 bean 有多个时,类型为所有注册的 bean,实现形式有:实现接口、继承、通过其余形式,例如 xml 配置注册 bean。
例如上述 StuService
有多个实现类,每个实现类都注册了 bean,因而 @Autowired 能够抉择的类型就有两个。
@Autowired
StuService stu;
根据上述的 @Autowired 逻辑,此时有多个类型,那么会依据 bean name 查找,(即类名首字母小写的),发现 stu
没有对应的实现类,
此时会报错:
Field stu in com.example.demo.spring.Stu1 required a single bean, but 2 were found:
只须要将 stu
替换成 stu2
或 stu3
即可实现注入。
继承和其余形式同时有多个 bean 注入时同理。
因而,@Autowired 中类型的定义能够归结为:当注册 bean 有多个时,类型为所有注册的 bean,实现形式有:实现接口、继承、通过其余形式,例如 xml 配置注册 bean 或者 @Bean 注册。
1.2 @Resource
- 当只有一个 bean 时,能够间接注册
@Autowired
SessionUtil sessionUtil;
- 当有多个 bean 注册时,如果未指定名称,则 bean name 为类名首字母小写,指定了 bean 名称则注册名称为该名称。
例如上文中 Stu1 Stu2
都未指定 bean 名称,因而两者的 bean 名称别离为 stu1 stu2
。
当应用 @Bean 在办法上注册 bean,此时名称为办法名称。
@Bean()
public Student getStudent(){Student student = new Student();
student.setName("bob");
student.setId(26);
return student;
}
此时该 bean 名称为 getStudent
。
同样,咱们也能够注册 bean 时自定义 bean 名称
@Bean("stu1")
public Student getStudent(){Student student = new Student();
student.setName("bob");
student.setId(26);
return student;
}
@Service("stu2")
class Stu2 implements StuService{
@Override
public String getName() {return "stu2";}
}
@Component("stu3")
class Stu3 implements StuService{
@Override
public String getName() {return "stu3";}
}
在援用时指定 bean:
@Resource(name = "stu2")
private StuService stu1;
1.3 @Autowired
当咱们应用 @Resource 时,会依据名称也就是 stu2
去查问,此时 bean 名称只有一个,查到返回
@Resource
private Stu3 stu2;
然而在执行时却发现报错:
Bean named 'stu2' is expected to be of type 'com.example.demo.spring.Stu3' but was actually of type 'com.example.demo.spring.Stu2'
这是因为只依据了 bean 名称去查问,却没有依据 bean 类型,查到的是 Stu2
类型的 bean,然而冀望的却是Stu3
,因而会产生类型不匹配。
二、SpringIOC 的 Bean 注入流程
spring 的注册流程次要蕴含两个局部:
- 容器的启动阶段及预热工作
- Bean 的注入流程
先理解一下几个概念:
2.1 概念介绍
2.1.1 配置元数据
存在于磁盘上的我的项目中用于形容一个 bean 的数据,能够是 xml、properties、yaml 等动态文件,也能够是各种注解形容的对应信息,例如 @Service、@Component 形容的一个 bean 的信息。
<bean id="role" class="com.wbg.springxmlbean.entity.Role">
<property name="id" value="1"/>
<property name="roleName" value="高级工程师"/>
<property name="note" value="重要人员"/>
</bean>
以上就是一个由 xml 定义的配置元数据。
2.1.2 BeanDefinition 与 BeanDefinitionReader
在 spring 中,无论是那种配置元数据,最终都会转换为BeanDefinition
,由 BeanDefinition 形容要生成并被援用的对象,能够了解为 BeanDefinition 就是 bean 的生成模板,或者是 bean 的说明书,依照 BeanDefinition 生成 bean。
而将配置元数据转换为 BeanDefinition
的工作就是由 BeanDefinitionReader
实现的,对于不同的的配置元数据有不同的 Reader 实现对应的工作,例如有 XmlBeanDefinitionReader
读取 xml 配置信息,PropertiesBeanDefinitionReader
读取 properties 配置信息,AnnotatedBeanDefinitionReader
读取注解的配置信息。
BeanDefinitionReader 的作用就是将磁盘上的文件信息或注解信息转化为内存中用于形容 bean 的 BeanDefinition。
2.1.3 BeanFactoryPostProcessor
BeanFactoryPostProcessor 是容器启动阶段 Spring 提供的一个扩大点,次要负责对注册到 BeanDefinitionRegistry 中的一个个的 BeanDefinition 进行肯定水平上的批改与替换。例如咱们的配置元信息中有些可能会批改的配置信息散落到各处,不够灵便,批改相应配置的时候比拟麻烦,这时咱们能够应用占位符的形式来配置。例如配置 Jdbc 的 DataSource 连贯的时候能够这样配置:
<bean id="dataSource"
class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="maxIdle" value="${jdbc.maxIdle}"></property>
<property name="maxActive" value="${jdbc.maxActive}"></property>
<property name="maxWait" value="${jdbc.maxWait}"></property>
<property name="minIdle" value="${jdbc.minIdle}"></property>
<property name="driverClassName"
value="${jdbc.driverClassName}">
</property>
<property name="url" value="${jdbc.url}"></property>
<property name="username" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
</bean>
BeanFactoryPostProcessor 就会对注册到 BeanDefinitionRegistry 中的 BeanDefinition 做最初的批改,替换 $ 占位符为配置文件中的实在的数据。
2.1.4 BeanDefinitionRegistry
一个存储 BeanDefinition 的中央,存储形式为 KV 值,key 为 beanName,value 为 BeanDefinition。
2.1.5 容器启动阶段
容器的启动阶段绝对比较简单,首先会将存在于各处的磁盘上的配置元信息由各自的 Reader 读取到内存之中,转换成 BeanDefinition
,而后注册到BeanDefinationRegistry
之中,最初由 BeanFactoryPostProcessor
进行批改与替换。
2.1.6 BeanFactory 与 FactoryBean
BeanFactory 与 FactoryBean 的名字很像,然而的确两个不同的货色。
依据命名规定来看,BeanFactory 是一个 Factory,也就是一个寄存 bean 的工厂,在创立 bean 实现后放到其中,应用是从其中获取。
而 FactoryBean 则是一个 bean,只不过与不同的的 bean 不同的是他不仅能够创立自身类型的 bean,也能够相似于 Factory 一样创立一层有包装的新的 bean。这个 Bean 能够返回一个新的类型的 bean,在返回之前也能够对其进行加工。
@Component
class FactoryBeanDemo implements FactoryBean<Student>{
@Override
public Student getObject() {return new Student();
}
@Override
public Class<?> getObjectType() {return Student.class;}
}
创立一个 FactoryBean 只须要实现其接口,并实现其中的两个办法。当咱们获取 FactoryBean 时,会返回其中 getObject()
办法返回的对象。而如果想要获取 FactoryBean 自身,只须要在 bean name 前加一个 ”&” 符号即可。
@Resource()
private Object factoryBeanDemo;
@GetMapping("/getStu")
private String getBean(){System.out.println(factoryBeanDemo.getClass());
return stu2.getName();}
// 输入后果
class com.example.demo.domain.Student
能够看到获取到的是 Student 类型。
class com.example.demo.spring.FactoryBeanDemo
将获取 bean 名称假“&”符号:
@Resource(name = "&factoryBeanDemo")
private Object factoryBeanDemo;
class com.example.demo.spring.FactoryBeanDemo
能够看到获取到的对象变成了 FactoryBeanDemo 自身。
2.2 Bean 注入流程
在容器启动阶段,曾经实现了 bean 的注册。如果该对象是配置成懒加载的形式,那么直到咱们向 Spring 要依赖对象实例之前,其都是以 BeanDefinitionRegistry 中的一个个的 BeanDefinition 的模式存在,也就是 Spring 只有在咱们第一次依赖对象的时候才开启相应对象的实例化阶段。而如果咱们不是抉择懒加载的形式,容器启动阶段实现之后,其中有一个步骤 finishBeanFactoryInitialization(),在这一步将立刻启动 Bean 实例化阶段,通过隐式的调用所有依赖对象的 getBean 办法来实例化所有配置的 Bean,实现类的加载。
doGetBean():获取并返回 bean
doGetBean()的次要流程有两个:
- 尝试从缓存中获取 bean,如果获取到间接返回。
- 如果没有获取到则尝试加载 bean。
protected <T> T doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
throws BeansException {String beanName = transformedBeanName(name);
Object beanInstance;
// Eagerly check singleton cache for manually registered singletons.
// 1、查问缓存中是否存在,存在的话间接返回
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 获取实例,次要是检测如果是 FactoryBean 类型,则获取其外部的 getObject()的 bean。(须要先理解 FactoryBean 的作用)beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
//2、不存在则创立 bean
else {
// Fail if we're already creating this bean instance:
// We're assumably within a circular reference.
if (isPrototypeCurrentlyInCreation(beanName)) {throw new BeanCurrentlyInCreationException(beanName);
}
// Check if bean definition exists in this factory.
// 2.1 尝试从父类的 Factory 加载 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);
}
StartupStep beanCreation = this.applicationStartup.start("spring.beans.instantiate")
.tag("beanName", name);
try {if (requiredType != null) {beanCreation.tag("beanType", requiredType::toString);
}
/*
* 2.2 获取 RootBeanDefinition:首先会依据 beanName 获取 BeanDefinition,而后将 BeanDefinition 转换为 RootBeanDefinition
* BeanDefinition 接口的实现类有很多,通过不同形式注册到 BeanDefinitionRegistry 中的 BeanDefinition 的类型可能都不太雷同。最终,在通过 BeanDefinition 来创立 bean 的实例时,通常都会调用 getMergedBeanDefinition 来获取到一个 RootBeanDefinition。所以,RootBeanDefinition 实质上是 Spring 运行时对立的 BeanDefinition 视图。* */
RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
// Guarantee initialization of beans that the current bean depends on.
// 2.3 初始化依赖的 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.
// 2.4 创立实例
if (mbd.isSingleton()) {sharedInstance = getSingleton(beanName, () -> {
try {
// 返回真正的 bean
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;
}
});
beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
}
return adaptBeanInstance(name, beanInstance, requiredType);
}
2.2.1 mbd = getMergedLocalBeanDefinition(beanName)获取 BeanDefinition
RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
BeanDefinition 接口的实现类有很多,通过不同形式注册到 BeanDefinitionRegistry 中的 BeanDefinition 的类型可能都不太雷同。
最终,在通过 BeanDefinition 来创立 bean 的实例时,通常都会调用 getMergedBeanDefinition 来获取到一个 RootBeanDefinition。所以,RootBeanDefinition 实质上是 Spring 运行时对立的 BeanDefinition 视图。
此处就是将各种 BeanDefinition 对立转换为 spring 能辨认的 RootBeanDefinition。
2.2.2 getSingleton(String beanName, ObjectFactory<?> singletonFactory) 获取创立好的对象
sharedInstance = getSingleton(beanName, () -> {
try {
// 返回真正的 bean
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;
}
});
从 getSingleton()
办法中获取创立好的对象
// 获取 singletonFactory 返回的后果
singletonObject = singletonFactory.getObject();
getSingleton()
办法中最次要的一次调用也就是从 singletonFactory
中获取对象,而获取对象的后果就是下面代码中传入的匿名工厂返回的后果,也就是 createBean(beanName, mbd, args)
2.2.3 createBean(beanName, mbd, args) 创立 bean
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {if (logger.isTraceEnabled()) {logger.trace("Creating instance of bean'" + beanName + "'");
}
RootBeanDefinition mbdToUse = mbd;
// Make sure bean class is actually resolved at this point, and
// clone the bean definition in case of a dynamically resolved Class
// which cannot be stored in the shared merged bean definition.
// 1. 解析 bean class
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {mbdToUse = new RootBeanDefinition(mbd);
mbdToUse.setBeanClass(resolvedClass);
}
// Prepare method overrides.
// 2. 筹备笼罩的办法
try {mbdToUse.prepareMethodOverrides();
}
catch (BeanDefinitionValidationException ex) {throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
beanName, "Validation of method overrides failed", ex);
}
try {
// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
// 3. 尝试返回代理创立的 Bean,这个作用就是查找 bean 中所有实现前置和后置处理器的接口,有没有手工创立而后返回的,代替了 spring 的创立 bean 的流程
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {return bean;}
}
catch (Throwable ex) {throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
"BeanPostProcessor before instantiation of bean failed", ex);
}
try {
//4. 真正创立 bean
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
if (logger.isTraceEnabled()) {logger.trace("Finished creating instance of bean'" + beanName + "'");
}
return beanInstance;
}
catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
// A previously detected exception with proper bean creation context already,
// or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.
throw ex;
}
catch (Throwable ex) {
throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
}
}
创立 bean 次要有以下几步:
- 解析 bean 的 class 文件,为前面的依据 class 文件通过反射创建对象做筹备。
- 预处理 bean 的 Override 属性,预处理的形式也比较简单,就是在办法 prepareMethodOverride 中判断一下,如果 lookup-method 标签或者 replaced-method 标签中配置了 bean 中须要笼罩的办法,就将 MethodOverride 中的 overload 属性值设置为 false。
- 尝试通过反射获取被代理的 bean。
- 真正创立 bean 的过程
2.2.4 Object beanInstance = doCreateBean(beanName, mbdToUse, args) 开始创立 bean
以上流程都是获取 bean 前的流程或获取 bean 的筹备,doCreateBean 是真正的创立并填充 bean 的流程(去掉了一些不重要的代码)。
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
// Instantiate the bean.
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
//1. 通过反射创立实例化对象,并将其放入 wraaper 中。wraaper 能够了解为 bean 的包装对象,外面是 bean 实例的,还有一些其余 bean 的属性方便使用
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
Object bean = instanceWrapper.getWrappedInstance();
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {mbd.resolvedTargetType = beanType;}
// Allow post-processors to modify the merged bean definition.
//2. 容许后处理处理器批改合并后的 bean 定义,这里只是解析这些 @Autowired @Value @Resource @PostConstruct 等这些注解,并没有产生理论属性注入的动作
synchronized (mbd.postProcessingLock) {if (!mbd.postProcessed) {
try {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.
//3. 是否须要提前曝光,用来解决循环依赖时应用
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;
//4. 将实例化实现成的 bean 填充属性
populateBean(beanName, mbd, instanceWrapper);
//5. 调用初始化办法,例如 init-method
exposedObject = initializeBean(beanName, exposedObject, mbd);
//6. 循环依赖查看
if (earlySingletonExposure) {Object earlySingletonReference = getSingleton(beanName, false);
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);
}
}
}
}
}
// Register bean as disposable.
//7. 注册 bean
try {registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
catch (BeanDefinitionValidationException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
}
return exposedObject;
}
从上述流程中能够看到,咱们创立一个 bean 次要有以下几个流程:
- 首先通过 class 依据反射创建对象,此时该对象的所有的属性都为空,能够了解为咱们 new 出的空属性对象。
- 解析 @Autowired @Value @Resource @PostConstruct 这些注解,但并没有产生属性注入的行为。
- 是否须要提前曝光,用来解决循环依赖时应用,次要作用是如果须要代理会返回代理对象,如果不须要代理,返回后面创立的对象
- 将第一步实例化实现的空属性对象填充属性,其中如果该 bean 依赖了其余 bean,也会在此步骤将依赖的 bean 拆卸,如果 bean 曾经被创立,则间接属性注入,如果不存在,则创立 bean,创立形式跟本 bean 雷同,能够了解为递归。
- 将实例化实现的 bean 对象初始化,次要查看 bean 是否实现了一些前置或后置或初始化的办法,如果是的话就执行。
- 循环依赖查看。
- 依据 scope 注册 bean。
能够看到,通过以上的几个步骤,咱们就获取到了一个实例 bean。
其中最重要的三个办法:
- 实例化 bean
- 拆卸属性
- 初始化 bean
2.2.5 总结
总结来说,创立 bean 的流程就是先依据反射获取对象,而后填充对象的属性,初始化,最初将 bean 注册。
2.3 创立 bean 流程深刻了解
上文咱们只粗略的解说了创立 bean 的过程,并没有深刻的查看源码是如何实现的,例如通过反射获取对象是怎么获取的,填充属性是如何填充的,下文将具体论述 2.2.5 过程中在源码层面是如何构建的。
2.3.1 instanceWrapper = createBeanInstance(beanName, mbd, args) 获取实例化对象
该办法通过反射获取实例化的空属性对象。
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
// Make sure bean class is actually resolved at this point.
//1.1 解析 class
Class<?> beanClass = resolveBeanClass(mbd, beanName);
//1.2 确认 public 权限
if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
}
//2. 如果存在 Supplier 回调,则调用 obtainFromSupplier() 进行初始化,因为反射获取对象的效率比拟低
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) {
/*
* 3. 如果 args 为空且办法曾经被 resolved,则会间接抉择对应的构造方法
* mbd.resolvedConstructorOrFactoryMethod 的赋值在下方【1】【2】的代码中赋值
* */
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?
//4. 主动拆卸的构造方法
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?
//5. 是否有首选构造方法
ctors = mbd.getPreferredConstructors();
if (ctors != null) {return autowireConstructor(beanName, mbd, ctors, null);
}
// No special handling: simply use no-arg constructor.
//6. 通过默认的无参构造函数
return instantiateBean(beanName, mbd);
}
- 首先解析 class 文件与确认 public 权限。
- 如果存在 Supplier 回调,则调用 obtainFromSupplier() 进行初始化,因为反射获取对象的效率比拟低。
- 如果 args 为空且应用那个构造函数曾经被确定了,则进行标记,后续间接抉择应用那种构造方法。
- 如果 args 不为空或没有被解析过,则抉择应用那种构造方法来结构实例化的对象:
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
Constructor<?>[] ctors = bp.determineCandidateConstructors(beanClass, beanName);
抉择 AutowiredAnnotationBeanPostProcessor 实现类:
其中重要的代码已贴出:
//1. 遍历所有的构造方法
for (Constructor<?> candidate : rawCandidates) {if (!candidate.isSynthetic()) {nonSyntheticConstructors++;}
else if (primaryConstructor != null) {continue;}
//2. 查看以后构造方法是否有 @Autowired 注解
MergedAnnotation<?> ann = findAutowiredAnnotation(candidate);
if (ann == null) {Class<?> userClass = ClassUtils.getUserClass(beanClass);
if (userClass != beanClass) {
try {
Constructor<?> superCtor =
userClass.getDeclaredConstructor(candidate.getParameterTypes());
ann = findAutowiredAnnotation(superCtor);
}
catch (NoSuchMethodException ex) {// Simply proceed, no equivalent superclass constructor found...}
}
}
//3. 如果有 @Autowired 注解
if (ann != null) {
//4. 如果曾经有一个 @Autowired 注解,则阐明存在多个 @Autowired 注解,则抛出异样
if (requiredConstructor != null) {
throw new BeanCreationException(beanName,
"Invalid autowire-marked constructor:" + candidate +
". Found constructor with'required'Autowired annotation already:" +
requiredConstructor);
}
boolean required = determineRequiredStatus(ann);
if (required) {if (!candidates.isEmpty()) {
throw new BeanCreationException(beanName,
"Invalid autowire-marked constructors:" + candidates +
". Found constructor with'required'Autowired annotation:" +
candidate);
}
requiredConstructor = candidate;
}
candidates.add(candidate);
}
// 5 无参构造函数
else if (candidate.getParameterCount() == 0) {
// 将其设置为默认构造函数
defaultConstructor = candidate;
}
}
// 对下面的处理过程进行判断
//6.1 先查看是否有 @Autowired 注解
if (!candidates.isEmpty()) {
// Add default constructor to list of optional constructors, as fallback.
if (requiredConstructor == null) {if (defaultConstructor != null) {candidates.add(defaultConstructor);
}
else if (candidates.size() == 1 && logger.isInfoEnabled()) {
logger.info("Inconsistent constructor declaration on bean with name'" + beanName +
"': single autowire-marked constructor flagged as optional -" +
"this constructor is effectively required since there is no" +
"default constructor to fall back to:" + candidates.get(0));
}
}
// 返回 @Autowired 注解的构造方法
candidateConstructors = candidates.toArray(new Constructor<?>[0]);
}
//6.2 如果只有一个有参构造函数,则返回该有参函数
else if (rawCandidates.length == 1 && rawCandidates[0].getParameterCount() > 0) {candidateConstructors = new Constructor<?>[] {rawCandidates[0]};
}
//6.3 对于非 Kotlin 类只会返回 null,所以这里不会进入
else if (nonSyntheticConstructors == 2 && primaryConstructor != null &&
defaultConstructor != null && !primaryConstructor.equals(defaultConstructor)) {candidateConstructors = new Constructor<?>[] {primaryConstructor, defaultConstructor};
}
else if (nonSyntheticConstructors == 1 && primaryConstructor != null) {candidateConstructors = new Constructor<?>[] {primaryConstructor};
}
else {
//6.4 对于不能辨认的场景会进入到这里,例如有多个构造函数然而并没有指定 @Autowired 注解或者没有构造函数(java 会帮咱们生成一个无参的构造函数),返回 null
candidateConstructors = new Constructor<?>[0];
}
2- 5 步会对所有的构造函数进行查看,并在查看完进行标记,并会在第 6 步对标记的后果进行返回,依照 ifelse 判断程序次要分为以下几种状况:
- 如果有 @Autowired 注解的办法则返回该构造方法
- 如果只有一个有参构造函数则会返回该有参构造函数
- 对于不能辨认的场景会进入到这里,例如有多个构造函数然而并没有指定 @Autowired 注解或者没有构造函数(java 会帮咱们生成一个无参的构造函数)会返回 null
在获取到须要的构造函数后,会进行标记,下次不必再次解析能够间接选用那个构造函数,即上文的第 4 步
- 是否有首选的构造函数
- 如果都没有的话,通过默认的无参构造函数创建对象。
咱们查看代码发现,无论第 4 步返回什么后果,最终会执行以下两个办法:
autowireConstructor()与 instantiateBean()
两者都会调用
instantiate()
办法
最终都会执行以下这个办法
BeanUtils.instantiateClass(constructorToUse)
也就是如下的代码
for (int i = 0 ; i < args.length; i++) {if (args[i] == null) {Class<?> parameterType = parameterTypes[i];
argsWithDefaultValues[i] = (parameterType.isPrimitive() ? DEFAULT_TYPE_VALUES.get(parameterType) : null);
}
else {argsWithDefaultValues[i] = args[i];
}
}
return ctor.newInstance(argsWithDefaultValues);
其中最重要的一句:
return ctor.newInstance(argsWithDefaultValues);
能够发现,也就是这里通过反射的形式创立了一个空属性对象,并一层层返回,直到前面的属性拆卸等过程,能够说这里就是 bean 加载过程的源头。
2.3.2 applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName) 解析各种注解
该办法次要解析该 bean 所相干的注解,例如属性有 @Resource,bean 中 @PostConstruct 注解都会被解析。
for (MergedBeanDefinitionPostProcessor processor : getBeanPostProcessorCache().mergedDefinition) {processor.postProcessMergedBeanDefinition(mbd, beanType, beanName);
}
processor 次要有两个实现类:
- AutowiredAnnotationBeanPostProcessor 解决 @Autowired 和 @Value 注解 bean 定义信息
- CommonAnnotationBeanPostProcessor 解决 @Resource、@PostConstruct、@PreDestroy 注解的 bean 定义信息
这里须要留神的是,该办法只是会解析并不会真正的进行注入,因为学习意义不大,并不在赘述。
2.3.3 populateBean(beanName, mbd, instanceWrapper) 对实例化实现的 bean 进行属性注入
// 遍历所有的属性
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;
}
其中 bp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName)
有几个实现办法,比拟重要的是:
- AutowiredAnnotationBeanPostProcessor,次要拆卸属性是 @Autowired 与 @Value 的属性
- CommonAnnotationBeanPostProcessor,次要拆卸属性是 @Resource 的属性
两者最终都会进入如下办法:
// 判断要注入的是属性还是办法
if (this.isField) {Field field = (Field) this.member;
ReflectionUtils.makeAccessible(field);
// 如果是属性的话则间接注入
field.set(target, getResourceToInject(target, requestingBeanName));
}
else {if (checkPropertySkipping(pvs)) {return;}
try {Method method = (Method) this.member;
ReflectionUtils.makeAccessible(method);
// 否则通过反射注入
method.invoke(target, getResourceToInject(target, requestingBeanName));
}
catch (InvocationTargetException ex) {throw ex.getTargetException();
}
}
了解起来比较简单,判断是办法注入还是属性注入,在注入时注入的对象为:
getResourceToInject(target, requestingBeanName)
找到 ResourceElement
的实现办法中 getResource()
办法:
返回了 autowireResource(this.resourceFactory, element, requestingBeanName)
if (factory instanceof AutowireCapableBeanFactory) {AutowireCapableBeanFactory beanFactory = (AutowireCapableBeanFactory) factory;
DependencyDescriptor descriptor = element.getDependencyDescriptor();
if (this.fallbackToDefaultTypeMatch && element.isDefaultName && !factory.containsBean(name)) {autowiredBeanNames = new LinkedHashSet<>();
resource = beanFactory.resolveDependency(descriptor, requestingBeanName, autowiredBeanNames, null);
if (resource == null) {throw new NoSuchBeanDefinitionException(element.getLookupType(), "No resolvable resource object");
}
}
else {resource = beanFactory.resolveBeanByName(name, descriptor);
autowiredBeanNames = Collections.singleton(name);
}
}
else {resource = factory.getBean(name, element.lookupType);
autowiredBeanNames = Collections.singleton(name);
}
在这个办法中,无论是 if 还是 else,最终都会调用
getBean(name, element.lookupType)
也就是咱们 bean 注入的入口,这个过程很像递归,在咱们创立 bean 时,如果发现咱们有依赖的其余 bean,那么就会去创立依赖的 bean,如果依赖的 bean 还有其依赖的属性则又会去创立被依赖的属性,只到最终全副创立实现,返回一开始想要创立的 bean。
2.3.4 exposedObject = initializeBean(beanName, exposedObject, mbd)初始化 bean
在该办法中,会对曾经填充过属性的 bean 进行初始化:
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
// 对 bean 的前置解决,其中 @PostConstruct 就在此步骤中
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
// 调用初始化办法如果 bean 实现了 InitializingBean 接口,则先执行 InitializingBean 接口的 afterPropertiesSet 办法,而后执行 xml 或注解设置的 init-method 办法。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()) {
// 对 bean 进行后置解决,对象的代理产生在此步骤中
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
在初始化 bean 的时候,次要分为三个局部,别离是applyBeanPostProcessorsBeforeInitialization、invokeInitMethods、applyBeanPostProcessorsAfterInitialization
,别离对应于初始化的前置解决、自定义 init 办法、后置解决。
applyBeanPostProcessorsBeforeInitialization、applyBeanPostProcessorsAfterInitialization
两个办法的大略逻辑就是获取获取所有实现其接口的类,而后执行其中被笼罩的办法。
罕用的注解执行程序如下:
- @PostConstruct 注解润饰的办法
- InitializingBean 接口的 afterPropertiesSet()办法
- init-method 指定的办法
- @PreDestroy 注解润饰的办法
- DisposableBean 接口的 destroy()办法
- destory-method 指定的办法
并且在代码中能够看到,前置解决与后置解决都能够扭转 bean。
在容器启动阶段咱们讲到 BeanFactoryPostProcessor,这里咱们讲到 BeanPostProcessor,那么 BeanFactoryPostProcessor 和 BeanPostProcessor 有什么区别呢?
BeanFactoryPostProcessor 存在于容器启动阶段,而 BeanPostProcessor 存在于对象实例化阶段,BeanFactoryPostProcessor 关注对象被创立之前那些配置的批改,而 BeanPostProcessor 阶段关注对象曾经被创立之后的性能加强,替换等操作,这样就很容易辨别了。
BeanPostProcessor 与 BeanFactoryPostProcessor 都是 Spring 在 Bean 生产过程中强有力的扩大点。Spring 中驰名的 AOP(面向切面编程),其实就是依赖 BeanPostProcessor 对 Bean 对象性能加强的。
BeanFactoryPostProcessor 次要用于解决实例化之前,对实例的属性进行拓展,而 BeanPostProcessor 是在实例化之后对对象做的拓展。
2.4 总结
用简略的话形容一下,创立一个 bean 的过程大略包含三局部:
- 通过反射实例化 bean
- 属性拆卸以及填充
- 初始化,包含 init-method、以及其前后三个步骤。其中 AOP 加强就是产生在初始化之后的
applyBeanPostProcessorsAfterInitialization
的步骤中。
通过以上的步骤,就能够取得咱们能够失常应用的一个 bean。