首页 > Python资料 博客日记
Spring-bean的生命周期-中篇
2024-10-16 00:00:11Python资料围观44次
阶段4:BeanDefinition合并阶段
合并阶段是做什么的?
可能我们定义bean的时候有父子bean关系,此时子BeanDefinition中的信息是不完整的,比如设置属性的时候配置在父BeanDefinition中,此时BeanDefinition中是没有这些信息的,需要将子bean的BeanDefinition和父bean BeanDefinition进行合并,得到最终的一个 RootBeanDefinition ,合并之后得到的RootBeanDefinition 包含bean定义的所有信息,包含了从父bean中继继承过来的所有信息,后续bean的所有创建工作就是依靠合并之后BeanDefinition来进行的。
合并BeanDefinition会使用下面这个方法:
org.springframework.beans.factory.support.AbstractBeanFactory#getMergedBeanDefinition
bean定义可能存在多级父子关系,合并的时候进进行递归合并,最终得到一个包含完整信息的RootBeanDefinition
案例:
spring bean
package com.shiguiwu.springmybatis.spring.lifecycle.definition;
import com.shiguiwu.springmybatis.spring.lifecycle.instance.MyAutowire;
import lombok.Data;
/**
* @description: 小猪
* @author: stone
* @date: Created by 2021/3/17 14:08
* @version: 1.0.0
* @pakeage: com.shiguiwu.springmybatis.spring.lifecycle.definition
*/
@Data
public class Pig {
private String name;
private Integer age;
private String description;
public Pig() {
}
@MyAutowire
public Pig(String name, Integer age) {
System.out.println("增强候选注解@MyAutowire !!!!");
this.name = name;
this.age = age;
}
public Pig(String name, Integer age, String description) {
this.name = name;
this.age = age;
this.description = description;
}
}
xml如下:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- 合并阶段 -->
<bean id="p1" class="com.shiguiwu.springmybatis.spring.lifecycle.definition.Pig" >
<property name="name" value="小猪佩奇"/>
</bean>
<bean id="p2" parent="p1">
<property name="age" value="18" />
</bean>
<bean id="p3" parent="p2">
<property name="description" value="佩奇是个可爱的小孩子"/>
</bean>
</beans>
java 测试代码
package com.shiguiwu.springmybatis.spring.lifecycle.merge;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
/**
* @description: 4,合并阶段
* @author: stone
* @date: Created by 2021/3/23 23:06
* @version: 1.0.0
* @pakeage: com.shiguiwu.springmybatis.spring.lifecycle.merge
*/
public class MergeTests {
public static void main(String[] args) {
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);
reader.loadBeanDefinitions("spring/merge.xml");
String[] definitionNames = factory.getBeanDefinitionNames();
for (String definitionName : definitionNames) {
System.out.println(definitionName);
System.out.println("========================================");
BeanDefinition beanDefinition = factory.getBeanDefinition(definitionName);
BeanDefinition mergedBeanDefinition = factory.getMergedBeanDefinition(definitionName);
System.out.println("解析xml过程中的bean definitionName:" + beanDefinition);
System.out.println("解析xml过程中的bean definitionName 的属性信息:" + beanDefinition.getPropertyValues());
System.out.println("==========================================");
System.out.println("解析xml过程中的合并bean definitionName:" + mergedBeanDefinition);
System.out.println("解析xml过程中的合并bean definitionName 的属性信息:" + mergedBeanDefinition.getPropertyValues());
System.out.println("-------------------------------------------");
}
}
}
输出效果如下:
23:57:59.842 [main] DEBUG org.springframework.beans.factory.xml.XmlBeanDefinitionReader - Loaded 3 bean definitions from class path resource [spring/merge.xml]
p1
========================================
解析xml过程中的bean definitionName:Generic bean: class [com.shiguiwu.springmybatis.spring.lifecycle.definition.Pig]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in class path resource [spring/merge.xml]
解析xml过程中的bean definitionName 的属性信息:PropertyValues: length=1; bean property 'name'
==========================================
解析xml过程中的合并bean definitionName:Root bean: class [com.shiguiwu.springmybatis.spring.lifecycle.definition.Pig]; scope=singleton; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in class path resource [spring/merge.xml]
解析xml过程中的合并bean definitionName 的属性信息:PropertyValues: length=1; bean property 'name'
-------------------------------------------
p2
========================================
解析xml过程中的bean definitionName:Generic bean with parent 'p1': class [null]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in class path resource [spring/merge.xml]
解析xml过程中的bean definitionName 的属性信息:PropertyValues: length=1; bean property 'age'
==========================================
解析xml过程中的合并bean definitionName:Root bean: class [com.shiguiwu.springmybatis.spring.lifecycle.definition.Pig]; scope=singleton; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in class path resource [spring/merge.xml]
解析xml过程中的合并bean definitionName 的属性信息:PropertyValues: length=2; bean property 'name'; bean property 'age'
-------------------------------------------
p3
========================================
解析xml过程中的bean definitionName:Generic bean with parent 'p2': class [null]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in class path resource [spring/merge.xml]
解析xml过程中的bean definitionName 的属性信息:PropertyValues: length=1; bean property 'description'
==========================================
解析xml过程中的合并bean definitionName:Root bean: class [com.shiguiwu.springmybatis.spring.lifecycle.definition.Pig]; scope=singleton; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in class path resource [spring/merge.xml]
解析xml过程中的合并bean definitionName 的属性信息:PropertyValues: length=3; bean property 'name'; bean property 'age'; bean property 'description'
-------------------------------------------
从输出的结果中可以看到,合并之前,BeanDefinition是不完整的,比p2和p3中的class是null,属性信息也不完整,但是合并之后这些信息都完整了。
合并之前是 GenericBeanDefinition 类型的,合并之后得到的是 RootBeanDefinition 类型的。
获取p3合并的BeanDefinition时,内部会递归进行合并,先将p1和p2合并,然后将p2再和p3合并,最后得到合并之后的BeanDefinition。
阶段5:Bean Class加载阶段
这个阶段就是将bean的class名称转换为Class类型的对象。
BeanDefinition中有个Object类型的字段:beanClass
private volatile Object beanClass;
用来表示bean的class对象,通常这个字段的值有2种类型,一种是bean对应的Class类型的对象,另一种是bean对应的Class的完整类名,第一种情况不需要解析,第二种情况:即这个字段是bean的类名的
时候,就需要通过类加载器将其转换为一个Class对象。此时会对阶段4中合并产生的 RootBeanDefinition 中的 beanClass 进行解析,将bean的类名转换为
Class对象 ,然后赋值给 beanClass 字段。
源码位置:
org.springframework.beans.factory.support.AbstractBeanFactory#resolveBeanClass
阶段6:Bean实例化阶段
2个小阶段
- Bean实例化前操作
- Bean实例化操作
Bean实例化前操作
先来看一下 DefaultListableBeanFactory ,这个类中有个非常非常重要的字段:
private final List<BeanPostProcessor> beanPostProcessors = new CopyOnWriteArrayList<>();
是一个 BeanPostProcessor 类型的集合,从阶段6开始,spring就开始为我们提供扩展点。
BeanPostProcessor是一个接口,还有很多子接口,这些接口中提供了很多方法,spring在bean生命周期的不同阶段,会调用上面这个列表中的BeanPostProcessor中的一些方法,来对生命周期进行扩展,bean生命周期中的所有扩展点都是依靠这个集合中的BeanPostProcessor来实现的,所以如果大家想对bean的生命周期进行干预,这块一定要掌握好。
下面是实例化前的扩展:
@Nullable
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实例化之前给开发者留了个口子,开发者自己可以在这个地方直接去创建一个对象作为bean实例,而跳过spring内部实例化bean的过程。上面代码中轮询 beanPostProcessors 列表,如果类型是InstantiationAwareBeanPostProcessor , 尝试调InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation 获取bean的实例对象,如果能够获取到,那么将返回值作为当前bean的实例,那么spring自带的实例化bean的过程就被跳过了。
postProcessBeforeInstantiation 方法如下:
default Object postProcessBeforeInstantiation(Class<?> beanClass, String
beanName) throws BeansException {
return null;
}
这个地方给开发者提供了一个扩展点,允许开发者在这个方法中直接返回bean的一个实例。
案例
先定义一个postProcessor class
package com.shiguiwu.springmybatis.spring.lifecycle.instance;
import com.shiguiwu.springmybatis.spring.lifecycle.definition.User;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor;
/**
* @description: process
* @author: stone
* @date: Created by 2021/3/24 20:59
* @version: 1.0.0
* @pakeage: com.shiguiwu.springmybatis.spring.lifecycle.instance
*/
public class UserBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
System.out.println("调用InstantiationAwareBeanPostProcessor》》》》》》》》》》》》》");
if (User.class.isAssignableFrom(beanClass)) {
User user = new User();
user.setName("石贵武!!");
return user;
}
return null;
}
}
测试案例
package com.shiguiwu.springmybatis.spring.lifecycle.instance;
import com.shiguiwu.springmybatis.spring.lifecycle.definition.User;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
/**
* @description: 6.0, 实例前阶段
* @author: stone
* @date: Created by 2021/3/24 20:43
* @version: 1.0.0
* @pakeage: com.shiguiwu.springmybatis.spring.lifecycle.instance
*/
public class InstancedTests {
public static void main(String[] args) {
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
//实例化前的干预
//创建了一个InstantiationAwareBeanPostProcessor,丢到了容器中的BeanPostProcessor列表中
factory.addBeanPostProcessor(new UserBeanPostProcessor());
//定义个
BeanDefinition definition = BeanDefinitionBuilder.genericBeanDefinition(User.class)
//改修名称
.addPropertyValue("name", "周冬")
.getBeanDefinition();
//注册定义对象
factory.registerBeanDefinition("user", definition);
System.out.println(factory.getBean("user"));
}
}
输出结果如下:
D:\jdk8\bin\java.exe -agentlib:jdwp=transport=dt_socket,address=127.0.0.1:65150,suspend=y,server=n -javaagent:D:\idea\20190304\system\captureAgent\debugger-agent.jar -Dfile.encoding=UTF-8 -classpath "D:\jdk8\jre\lib\charsets.jar;D:\jdk8\jre\lib\deploy.jar;D:\jdk8\jre\lib\ext\access-bridge-64.jar;D:\jdk8\jre\lib\ext\cldrdata.jar;D:\jdk8\jre\lib\ext\dnsns.jar;D:\jdk8\jre\lib\ext\jaccess.jar;D:\jdk8\jre\lib\ext\jfxrt.jar;D:\jdk8\jre\lib\ext\localedata.jar;D:\jdk8\jre\lib\ext\nashorn.jar;D:\jdk8\jre\lib\ext\sunec.jar;D:\jdk8\jre\lib\ext\sunjce_provider.jar;D:\jdk8\jre\lib\ext\sunmscapi.jar;D:\jdk8\jre\lib\ext\sunpkcs11.jar;D:\jdk8\jre\lib\ext\zipfs.jar;D:\jdk8\jre\lib\javaws.jar;D:\jdk8\jre\lib\jce.jar;D:\jdk8\jre\lib\jfr.jar;D:\jdk8\jre\lib\jfxswt.jar;D:\jdk8\jre\lib\jsse.jar;D:\jdk8\jre\lib\management-agent.jar;D:\jdk8\jre\lib\plugin.jar;D:\jdk8\jre\lib\resources.jar;D:\jdk8\jre\lib\rt.jar;G:\workspace\ideaWorkspace\spring-mybatis\target\classes;G:\maven_repository\com\baomidou\mybatis-plus-boot-starter\3.2.0\mybatis-plus-boot-starter-3.2.0.jar;G:\maven_repository\com\baomidou\mybatis-plus\3.2.0\mybatis-plus-3.2.0.jar;G:\maven_repository\com\baomidou\mybatis-plus-extension\3.2.0\mybatis-plus-extension-3.2.0.jar;G:\maven_repository\com\baomidou\mybatis-plus-core\3.2.0\mybatis-plus-core-3.2.0.jar;G:\maven_repository\com\baomidou\mybatis-plus-annotation\3.2.0\mybatis-plus-annotation-3.2.0.jar;G:\maven_repository\com\github\jsqlparser\jsqlparser\2.1\jsqlparser-2.1.jar;G:\maven_repository\org\mybatis\mybatis\3.5.2\mybatis-3.5.2.jar;G:\maven_repository\org\mybatis\mybatis-spring\2.0.2\mybatis-spring-2.0.2.jar;G:\maven_repository\org\springframework\boot\spring-boot-autoconfigure\2.3.11.RELEASE\spring-boot-autoconfigure-2.3.11.RELEASE.jar;G:\maven_repository\org\springframework\boot\spring-boot\2.3.11.RELEASE\spring-boot-2.3.11.RELEASE.jar;G:\maven_repository\org\springframework\boot\spring-boot-starter-jdbc\2.3.11.RELEASE\spring-boot-starter-jdbc-2.3.11.RELEASE.jar;G:\maven_repository\com\zaxxer\HikariCP\3.4.5\HikariCP-3.4.5.jar;G:\maven_repository\org\springframework\spring-jdbc\5.2.15.RELEASE\spring-jdbc-5.2.15.RELEASE.jar;G:\maven_repository\org\springframework\boot\spring-boot-starter-web\2.3.11.RELEASE\spring-boot-starter-web-2.3.11.RELEASE.jar;G:\maven_repository\org\springframework\boot\spring-boot-starter\2.3.11.RELEASE\spring-boot-starter-2.3.11.RELEASE.jar;G:\maven_repository\org\springframework\boot\spring-boot-starter-logging\2.3.11.RELEASE\spring-boot-starter-logging-2.3.11.RELEASE.jar;G:\maven_repository\ch\qos\logback\logback-classic\1.2.3\logback-classic-1.2.3.jar;G:\maven_repository\ch\qos\logback\logback-core\1.2.3\logback-core-1.2.3.jar;G:\maven_repository\org\apache\logging\log4j\log4j-to-slf4j\2.13.3\log4j-to-slf4j-2.13.3.jar;G:\maven_repository\org\apache\logging\log4j\log4j-api\2.13.3\log4j-api-2.13.3.jar;G:\maven_repository\org\slf4j\jul-to-slf4j\1.7.30\jul-to-slf4j-1.7.30.jar;G:\maven_repository\jakarta\annotation\jakarta.annotation-api\1.3.5\jakarta.annotation-api-1.3.5.jar;G:\maven_repository\org\yaml\snakeyaml\1.26\snakeyaml-1.26.jar;G:\maven_repository\org\springframework\boot\spring-boot-starter-json\2.3.11.RELEASE\spring-boot-starter-json-2.3.11.RELEASE.jar;G:\maven_repository\com\fasterxml\jackson\core\jackson-databind\2.11.4\jackson-databind-2.11.4.jar;G:\maven_repository\com\fasterxml\jackson\core\jackson-annotations\2.11.4\jackson-annotations-2.11.4.jar;G:\maven_repository\com\fasterxml\jackson\core\jackson-core\2.11.4\jackson-core-2.11.4.jar;G:\maven_repository\com\fasterxml\jackson\datatype\jackson-datatype-jdk8\2.11.4\jackson-datatype-jdk8-2.11.4.jar;G:\maven_repository\com\fasterxml\jackson\datatype\jackson-datatype-jsr310\2.11.4\jackson-datatype-jsr310-2.11.4.jar;G:\maven_repository\com\fasterxml\jackson\module\jackson-module-parameter-names\2.11.4\jackson-module-parameter-names-2.11.4.jar;G:\maven_repository\org\springframework\boot\spring-boot-starter-tomcat\2.3.11.RELEASE\spring-boot-starter-tomcat-2.3.11.RELEASE.jar;G:\maven_repository\org\apache\tomcat\embed\tomcat-embed-core\9.0.46\tomcat-embed-core-9.0.46.jar;G:\maven_repository\org\glassfish\jakarta.el\3.0.3\jakarta.el-3.0.3.jar;G:\maven_repository\org\apache\tomcat\embed\tomcat-embed-websocket\9.0.46\tomcat-embed-websocket-9.0.46.jar;G:\maven_repository\org\springframework\spring-web\5.2.15.RELEASE\spring-web-5.2.15.RELEASE.jar;G:\maven_repository\org\springframework\spring-beans\5.2.15.RELEASE\spring-beans-5.2.15.RELEASE.jar;G:\maven_repository\org\springframework\spring-webmvc\5.2.15.RELEASE\spring-webmvc-5.2.15.RELEASE.jar;G:\maven_repository\org\springframework\spring-context\5.2.15.RELEASE\spring-context-5.2.15.RELEASE.jar;G:\maven_repository\org\springframework\spring-expression\5.2.15.RELEASE\spring-expression-5.2.15.RELEASE.jar;G:\maven_repository\org\springframework\boot\spring-boot-starter-aop\2.3.11.RELEASE\spring-boot-starter-aop-2.3.11.RELEASE.jar;G:\maven_repository\org\springframework\spring-aop\5.2.15.RELEASE\spring-aop-5.2.15.RELEASE.jar;G:\maven_repository\org\aspectj\aspectjweaver\1.9.6\aspectjweaver-1.9.6.jar;G:\maven_repository\org\springframework\boot\spring-boot-starter-cache\2.3.11.RELEASE\spring-boot-starter-cache-2.3.11.RELEASE.jar;G:\maven_repository\org\springframework\spring-context-support\5.2.15.RELEASE\spring-context-support-5.2.15.RELEASE.jar;G:\maven_repository\mysql\mysql-connector-java\8.0.25\mysql-connector-java-8.0.25.jar;G:\maven_repository\org\springframework\boot\spring-boot-configuration-processor\2.3.11.RELEASE\spring-boot-configuration-processor-2.3.11.RELEASE.jar;G:\maven_repository\org\projectlombok\lombok\1.18.20\lombok-1.18.20.jar;G:\maven_repository\cn\hutool\hutool-all\5.3.7\hutool-all-5.3.7.jar;G:\maven_repository\com\shiguiwu\facade\facade-spring-boot-starter-autoconfigurer\1.0.1-SNAPSHOT\facade-spring-boot-starter-autoconfigurer-1.0.1-SNAPSHOT.jar;G:\maven_repository\org\slf4j\slf4j-api\1.7.30\slf4j-api-1.7.30.jar;G:\maven_repository\org\springframework\spring-core\5.2.15.RELEASE\spring-core-5.2.15.RELEASE.jar;G:\maven_repository\org\springframework\spring-jcl\5.2.15.RELEASE\spring-jcl-5.2.15.RELEASE.jar;G:\maven_repository\org\springframework\boot\spring-boot-starter-data-redis\2.3.11.RELEASE\spring-boot-starter-data-redis-2.3.11.RELEASE.jar;G:\maven_repository\org\springframework\data\spring-data-redis\2.3.9.RELEASE\spring-data-redis-2.3.9.RELEASE.jar;G:\maven_repository\org\springframework\data\spring-data-keyvalue\2.3.9.RELEASE\spring-data-keyvalue-2.3.9.RELEASE.jar;G:\maven_repository\org\springframework\data\spring-data-commons\2.3.9.RELEASE\spring-data-commons-2.3.9.RELEASE.jar;G:\maven_repository\org\springframework\spring-tx\5.2.15.RELEASE\spring-tx-5.2.15.RELEASE.jar;G:\maven_repository\org\springframework\spring-oxm\5.2.15.RELEASE\spring-oxm-5.2.15.RELEASE.jar;G:\maven_repository\io\lettuce\lettuce-core\5.3.7.RELEASE\lettuce-core-5.3.7.RELEASE.jar;G:\maven_repository\io\netty\netty-common\4.1.65.Final\netty-common-4.1.65.Final.jar;G:\maven_repository\io\netty\netty-handler\4.1.65.Final\netty-handler-4.1.65.Final.jar;G:\maven_repository\io\netty\netty-resolver\4.1.65.Final\netty-resolver-4.1.65.Final.jar;G:\maven_repository\io\netty\netty-buffer\4.1.65.Final\netty-buffer-4.1.65.Final.jar;G:\maven_repository\io\netty\netty-codec\4.1.65.Final\netty-codec-4.1.65.Final.jar;G:\maven_repository\io\netty\netty-transport\4.1.65.Final\netty-transport-4.1.65.Final.jar;G:\maven_repository\io\projectreactor\reactor-core\3.3.17.RELEASE\reactor-core-3.3.17.RELEASE.jar;G:\maven_repository\org\reactivestreams\reactive-streams\1.0.3\reactive-streams-1.0.3.jar;D:\JetBrains\IntelliJ IDEA 2019.3.4\lib\idea_rt.jar" com.shiguiwu.springmybatis.spring.lifecycle.instance.InstancedTests
Connected to the target VM, address: '127.0.0.1:65150', transport: 'socket'
20:19:14.485 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'user'
调用InstantiationAwareBeanPostProcessor》》》》》》》》》》》》》
User(pig=null, name=石贵武!!, pigList=null, pigSet=null, stringMap=null, stringPigMap=null, strings=null, stringSet=null)
Disconnected from the target VM, address: '127.0.0.1:65150', transport: 'socket'
Process finished with exit code 0
定义和输出不一致的原因是因为我们在InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation 方法中手动创建了一个实例直接返回了,而不是依靠spring内部去创建这个实例。
Bean实例化操作
这个过程会通过反射来调用bean的构造器来创建bean的实例。具体需要使用哪个构造器,spring为开发者提供了一个接口,允许开发者自己来判断用哪个构造器。
看一下这块的代码逻辑:
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
Constructor<?>[] ctors = ibp.determineCandidateConstructors(beanClass, beanName);
if (ctors != null) {
return ctors;
}
}
}
会调用 SmartInstantiationAwareBeanPostProcessor接口determineCandidateConstructors 方法,这个方法会返回候选的构造器列表,也可以返回空,看一下这个方法的源码:
default Constructor<?>[] determineCandidateConstructors (Class < ? > beanClass, String beanName) throws BeansException {
return null;
}
这个方法有个比较重要的实现类
org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor
可以将 @Autowired 标注的方法作为候选构造器返回,有兴趣的可以去看一下代码。
来个案例
下面我们来个案例,自定义一个注解,当构造器被这个注解标注的时候,让spring自动选择使用这个构造器创建对象。
先定义一个注解
package com.shiguiwu.springmybatis.spring.lifecycle.instance;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @description: 自定义候选注解
* @author: stone
* @date: Created by 2021/3/24 23:43
* @version: 1.0.0
* @pakeage: com.shiguiwu.springmybatis.spring.lifecycle.instance
*/
@Target({ElementType.METHOD, ElementType.CONSTRUCTOR, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MyAutowire {
}
再定义一个post类
package com.shiguiwu.springmybatis.spring.lifecycle.instance;
import cn.hutool.core.collection.CollUtil;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.SmartInstantiationAwareBeanPostProcessor;
import java.lang.reflect.Constructor;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
/**
* @description: 自定义候选构造器
* @author: stone
* @date: Created by 2021/3/24 23:42
* @version: 1.0.0
* @pakeage: com.shiguiwu.springmybatis.spring.lifecycle.instance
*/
public class MySmartInstantiationAwareBeanPostProcessor implements SmartInstantiationAwareBeanPostProcessor {
@Override
public Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, String beanName) throws BeansException {
System.out.println("bean的名称:" + beanName);
System.out.println(beanClass.getName());
System.out.println("调用 SmartInstantiationAwareBeanPostProcessor#determineCandidateConstructors ");
Constructor<?>[] constructors = beanClass.getDeclaredConstructors();
Constructor[] array = Arrays.stream(constructors)
.filter(c -> c.isAnnotationPresent(MyAutowire.class)).toArray(Constructor[]::new);
return (array.length!=0) ? array : null;
}
}
测试代码:
package com.shiguiwu.springmybatis.spring.lifecycle.instance;
import com.shiguiwu.springmybatis.spring.lifecycle.definition.Pig;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
/**
* @description: 6.1实例化中
* 利用bean定义信息,借助反射,调用构造器,生成实例。构造器可有开发者决定
*
*
* @author: stone
* @date: Created by 2021/3/24 23:15
* @version: 1.0.0
* @pakeage: com.shiguiwu.springmybatis.spring.lifecycle.instance
*/
public class InstancingTests {
public static void main(String[] args) {
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
factory.addBeanPostProcessor(new MySmartInstantiationAwareBeanPostProcessor());
BeanDefinition stringBean = BeanDefinitionBuilder.genericBeanDefinition(String.class)
.addConstructorArgValue("小猪佩奇")
.getBeanDefinition();
BeanDefinition integerBean = BeanDefinitionBuilder.genericBeanDefinition(Integer.class)
.addConstructorArgValue(1)
.getBeanDefinition();
BeanDefinition pig = BeanDefinitionBuilder.genericBeanDefinition(Pig.class)
.getBeanDefinition();
factory.registerBeanDefinition("age", integerBean);
factory.registerBeanDefinition("name", stringBean);
factory.registerBeanDefinition("pig", pig);
System.out.println(factory.getBean(Pig.class));
}
}
输出如下:
21:00:40.255 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'pig'
bean的名称:pig
com.shiguiwu.springmybatis.spring.lifecycle.definition.Pig
调用 SmartInstantiationAwareBeanPostProcessor#determineCandidateConstructors
21:00:40.436 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'name'
bean的名称:name
java.lang.String
调用 SmartInstantiationAwareBeanPostProcessor#determineCandidateConstructors
21:00:40.928 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'age'
bean的名称:age
java.lang.Integer
调用 SmartInstantiationAwareBeanPostProcessor#determineCandidateConstructors
21:00:40.945 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Autowiring by type from bean name 'pig' via constructor to bean named 'name'
21:00:40.945 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Autowiring by type from bean name 'pig' via constructor to bean named 'age'
增强候选注解@MyAutowire !!!!
Pig(name=小猪佩奇, age=1, description=null)
从输出中可以看出调用了Person中标注@MyAutowired标注的构造器。
到目前为止bean实例化阶段结束了,继续进入后面的阶段。
阶段7:合并后的BeanDefinition处理
合并后的处理,这里spring也为我们提供了扩展点,在合并之后,做些我们自己的动作和业务等。源码如下:
protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class<?> beanType, String beanName) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof MergedBeanDefinitionPostProcessor) {
MergedBeanDefinitionPostProcessor bdp =
(MergedBeanDefinitionPostProcessor) bp;
bdp.postProcessMergedBeanDefinition(mbd, beanType, beanName);
}
}
}
会调用 MergedBeanDefinitionPostProcessor接口的postProcessMergedBeanDefinition 方法,看一下这个方法的源码:
void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?>
beanType, String beanName);
spring会轮询 BeanPostProcessor ,依次调用MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition
第一个参数为beanDefinition,表示合并之后的RootBeanDefinition,我们可以在这个方法内部对合并之后的 BeanDefinition 进行再次处理
postProcessMergedBeanDefinition有2个实现类,前面我们介绍过,用的也比较多,面试的时候也会经常问的:
org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor
在 postProcessMergedBeanDefinition 方法中对 @Autowired、@Value 标注的方法、字段进行缓存 org.springframework.context.annotation.CommonAnnotationBeanPostProcessor 在 postProcessMergedBeanDefinition 方法中对 @Resource 标注的字段、@Resource 标注的方 法、 @PostConstruct 标注的字段、 @PreDestroy标注的方法进行缓存
此致,spring bean的生命周期中篇完结,后面会更新终篇
标签:
上一篇:Spring1~~~
下一篇:Java:继承和多态(1)
相关文章
最新发布
- 【Python】selenium安装+Microsoft Edge驱动器下载配置流程
- Python 中自动打开网页并点击[自动化脚本],Selenium
- Anaconda基础使用
- 【Python】成功解决 TypeError: ‘<‘ not supported between instances of ‘str’ and ‘int’
- manim边学边做--三维的点和线
- CPython是最常用的Python解释器之一,也是Python官方实现。它是用C语言编写的,旨在提供一个高效且易于使用的Python解释器。
- Anaconda安装配置Jupyter(2024最新版)
- Python中读取Excel最快的几种方法!
- Python某城市美食商家爬虫数据可视化分析和推荐查询系统毕业设计论文开题报告
- 如何使用 Python 批量检测和转换 JSONL 文件编码为 UTF-8
点击排行
- 版本匹配指南:Numpy版本和Python版本的对应关系
- 版本匹配指南:PyTorch版本、torchvision 版本和Python版本的对应关系
- Python 可视化 web 神器:streamlit、Gradio、dash、nicegui;低代码 Python Web 框架:PyWebIO
- 相关性分析——Pearson相关系数+热力图(附data和Python完整代码)
- Python与PyTorch的版本对应
- Anaconda版本和Python版本对应关系(持续更新...)
- Python pyinstaller打包exe最完整教程
- Could not build wheels for llama-cpp-python, which is required to install pyproject.toml-based proj