到目前为止,我们知道Spring
创建Bean
对象有5中方法,分别是:
- 使用
FactoryBean
的getObject
方法创建 - 使用
BeanPostProcessor
的子接口InstantiationAwareBeanPostProcessor
的postProcessBeforeInstantiation
方法创建 - 设置
BeanDefinition
的Supplier
属性进行创建 - 设置
BeanDefinition
的factory-method
进行创建 - 使用全过程:
getBean-->doGetBean-->createBean-->doCreateBean
反射进行创建
前面4中已经介绍,接下来介绍第5种,我们知道如果使用反射创建,那么必然要知道使用构造函数进行实例化,因为使用构造函数能够将带有参数的设置进去。
SmartInstantiationAwareBeanPostProcessor 接口
在前面讲过InstantiationAwareBeanPostProcessor
是用来提前实例化对象的,而SmartInstantiationAwareBeanPostProcessor
是InstantiationAwareBeanPostProcessor
的子接口,他是用来干啥呢?
在createBeanInstance
方法中的源码:
// 省略代码....
// 明确构造器从BeanPostProcessor中,对应的是 AutowiredAnnotationBeanPostProcessor
// 他是 SmartInstantiationAwareBeanPostProcessor 的子类,使用determineCandidateConstructors进行
// 解析构造函数
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
return autowireConstructor(beanName, mbd, ctors, args);
}
// 省略代码....
点进去:
protected Constructor<?>[] determineConstructorsFromBeanPostProcessors(@Nullable Class<?> beanClass, String beanName)
throws BeansException {
if (beanClass != null && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
// 决定候选的构造函数
Constructor<?>[] ctors = ibp.determineCandidateConstructors(beanClass, beanName);
if (ctors != null) {
return ctors;
}
}
}
}
return null;
}
可以看到这个接口是用来解析BeanClass
的构造函数的,SmartInstantiationAwareBeanPostProcessor
的实现类AutowiredAnnotationBeanPostProcessor
,这个类是用来解析确定合适的构造函数,重点解析了@Autowired
注解,并且还解析了@Value
注解和@Lookup
注解。
当解析出来构造函数之后,那么就调用autowireConstructor
方法进行实例化,解析时会new一个构造器解析器ConstructorResolver
,在解析factoryMehod
时也是使用的这个类使用的是instantiateUsingFactoryMethod
这个方法,并且解析factoryMethod
更加复杂,需要判断是否是静态的工厂创建还是实例工厂创建,而自动装配的构造解析相对来说简单一些,使用autowireConstructor
方法进行解析。
最终解析出构造方法和构造参数之后进行实例化:
// 使用合适的构造方法和构造参数进行实例化
bw.setBeanInstance(instantiate(beanName, mbd, constructorToUse, argsToUse));
实例化:
private Object instantiate(
String beanName, RootBeanDefinition mbd, Constructor<?> constructorToUse, Object[] argsToUse) {
try {
// 获取实例化策略,一般使用 CglibSubClassingInstantiationStrategy
InstantiationStrategy strategy = this.beanFactory.getInstantiationStrategy();
if (System.getSecurityManager() != null) {
return AccessController.doPrivileged((PrivilegedAction<Object>) () ->
strategy.instantiate(mbd, beanName, this.beanFactory, constructorToUse, argsToUse),
this.beanFactory.getAccessControlContext());
}
else {
// 开始实例化
return strategy.instantiate(mbd, beanName, this.beanFactory, constructorToUse, argsToUse);
}
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Bean instantiation via constructor failed", ex);
}
}
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 {
// 如果方法被覆盖,lookup-method 和 replace-method
return instantiateWithMethodInjection(bd, beanName, owner, ctor, args);
}
}
如果前面的解析都没有到Bean
,那么就会使用无参构造函数进行解析:
// 省略代码....
// Preferred constructors for default construction?
// 首选的构造器为默认的创建方式,使用了@Primary注解的为首选的创建对象方式
ctors = mbd.getPreferredConstructors();
if (ctors != null) {
return autowireConstructor(beanName, mbd, ctors, null);
}
// No special handling: simply use no-arg constructor.
// 调用无参构造函数实例化对象
return instantiateBean(beanName, mbd);
实例化Bean
:
protected BeanWrapper instantiateBean(String beanName, RootBeanDefinition mbd) {
try {
Object beanInstance;
if (System.getSecurityManager() != null) {
beanInstance = AccessController.doPrivileged(
(PrivilegedAction<Object>) () -> getInstantiationStrategy().instantiate(mbd, beanName, this),
getAccessControlContext());
}
else {
// 实例化对象,使用反射进行创建
beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, this);
}
// 创建一个Bean的包装器
BeanWrapper bw = new BeanWrapperImpl(beanInstance);
// 初始化Bean的包装器
initBeanWrapper(bw);
return bw;
}
catch (Throwable ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);
}
}
这里可以看到前面使用factoryMethod
和autowireConstructor
解析构造函数进行实例化还是使用无参构造函数进行实例化都是将Bean
进行了包装,那这个包装有啥作用呢?
BeanWrapper的作用
我们先来看下前面的方法是怎么创建BeanWrapper
的:
factory-method
解析,ConstructorResolver#instantiateUsingFactoryMethod
方法:
public BeanWrapper instantiateUsingFactoryMethod(
String beanName, RootBeanDefinition mbd, @Nullable Object[] explicitArgs) {
// 创建一个Bean的包装器
BeanWrapperImpl bw = new BeanWrapperImpl();
this.beanFactory.initBeanWrapper(bw);
// factoryBean
Object factoryBean;
// factory 工厂类
Class<?> factoryClass;
// 标识是否是静态的工厂
boolean isStatic;
// 省略代码....
}
SmartInstantiationAwareBeanPostProcessor
子类AutowiredAnnotationBeanPostProcessor
解析出构造函数,然后使用ConstructorResolver#autowireConstructor
执行:
public BeanWrapper autowireConstructor(String beanName, RootBeanDefinition mbd,
@Nullable Constructor<?>[] chosenCtors, @Nullable Object[] explicitArgs) {
// 创建一个包装器
BeanWrapperImpl bw = new BeanWrapperImpl();
// 初始化包装器
this.beanFactory.initBeanWrapper(bw);
// 构造函数
Constructor<?> constructorToUse = null;
// 构造参数
ArgumentsHolder argsHolderToUse = null;
// 需要使用的构造参数
Object[] argsToUse = null;
// 明确的构造参数不为空,则赋值给将要执行实例化的构造参数
if (explicitArgs != null) {
argsToUse = explicitArgs;
}
// 省略代码....
}
最终都是会进行转换服务ConversionService
和PropertyEditorRegistry
的注册,一个是用来进行属性类型转换的,一个是用来属性值解析的:
protected void initBeanWrapper(BeanWrapper bw) {
// 获取转换服务放到bean的包装器中
bw.setConversionService(getConversionService());
// 注册定制的属性编辑器
registerCustomEditors(bw);
}
在前面的文章中,介绍了这两个如何使用,而且还自定义了属性编辑器和类型转换,需要的小伙伴可以去看看:
https://www.cnblogs.com/redwinter/p/16167214.html 和 https://www.cnblogs.com/redwinter/p/16241328.html
到这里Bean的实例化就完成了,接着往下看源码:
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
// Instantiate the bean.
BeanWrapper instanceWrapper = null;
// 从缓存中获取FactoryBean的Bean对象
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
// 实例化对象
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
// 从包装器中获取Bean对象
Object bean = instanceWrapper.getWrappedInstance();
// 从包装器中获取Bean类型
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 {
// 合并Bean
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Post-processing of merged bean definition failed", ex);
}
mbd.postProcessed = true;
}
}
}
点进去:
protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class<?> beanType, String beanName) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof MergedBeanDefinitionPostProcessor) {
MergedBeanDefinitionPostProcessor bdp = (MergedBeanDefinitionPostProcessor) bp;
// 执行合并BeanDefinition
bdp.postProcessMergedBeanDefinition(mbd, beanType, beanName);
}
}
}
可以看到这里出现了一个接口MergedBeanDefinitionPostProcessor
,这个接口也是BeanPostProcessor
的子接口,那他到底是干啥用的呢?
MergedBeanDefinitionPostProcessor 接口
点击发现这个接口的实现类全是跟注解相关的,包括AutowiredAnnotationBeanPostProcessor
、CommonAnnotationBeanPostProcessor
及InitDestroyAnnotationBeanPostProcessor
实现类,CommonAnnotationBeanPostProcessor
在构造函数中设置了两个注解:@PostConstruct和
@PreDestroy ,一个是在初始化完之后调用,一个是容器销毁时调用。
CommonAnnotationBeanPostProcessor这个类的父类为
InitDestroyAnnotationBeanPostProcessor`,用于处理初始化和销毁方法的。
CommonAnnotationBeanPostProcessor
的构造器:
public CommonAnnotationBeanPostProcessor() {
setOrder(Ordered.LOWEST_PRECEDENCE - 3);
// 初始化PostConstruct PreDestroy注解
// 调用父类的方法进行设置
setInitAnnotationType(PostConstruct.class);
setDestroyAnnotationType(PreDestroy.class);
ignoreResourceType("javax.xml.ws.WebServiceContext");
}
CommonAnnotationBeanPostProcessor
合并方法:
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
// 调用父类
super.postProcessMergedBeanDefinition(beanDefinition, beanType, beanName);
InjectionMetadata metadata = findResourceMetadata(beanName, beanType, null);
metadata.checkConfigMembers(beanDefinition);
}
点击postProcessMergedBeanDefinition
方法发现调用了父类的这个方法,然后执行了一个叫查找生命周期元数据的方法findLifecycleMetadata
。
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
LifecycleMetadata metadata = findLifecycleMetadata(beanType);
metadata.checkConfigMembers(beanDefinition);
}
查找生命周期元数据:
private LifecycleMetadata findLifecycleMetadata(Class<?> clazz) {
if (this.lifecycleMetadataCache == null) {
// Happens after deserialization, during destruction...
return buildLifecycleMetadata(clazz);
}
// Quick check on the concurrent map first, with minimal locking.
// 查询缓存
LifecycleMetadata metadata = this.lifecycleMetadataCache.get(clazz);
if (metadata == null) {
synchronized (this.lifecycleMetadataCache) {
// 再次查询
metadata = this.lifecycleMetadataCache.get(clazz);
if (metadata == null) {
// 没有查询到就去构建生命周期的元数据
metadata = buildLifecycleMetadata(clazz);
this.lifecycleMetadataCache.put(clazz, metadata);
}
return metadata;
}
}
return metadata;
}
构建生命周期元数据:
private LifecycleMetadata buildLifecycleMetadata(final Class<?> clazz) {
// 这里的initAnnotationType 就是子类set进去的@PostConstruct
// destroyAnnotationType 就是子类set进去的@PreDestroy
if (!AnnotationUtils.isCandidateClass(clazz, Arrays.asList(this.initAnnotationType, this.destroyAnnotationType))) {
return this.emptyLifecycleMetadata;
}
// 存放初始化方法
List<LifecycleElement> initMethods = new ArrayList<>();
// 存放销毁方法
List<LifecycleElement> destroyMethods = new ArrayList<>();
Class<?> targetClass = clazz;
do {
final List<LifecycleElement> currInitMethods = new ArrayList<>();
final List<LifecycleElement> currDestroyMethods = new ArrayList<>();
ReflectionUtils.doWithLocalMethods(targetClass, method -> {
// 如果找到方法上有@PostConstruct注解,这加入到当前初始化方法集合中
if (this.initAnnotationType != null && method.isAnnotationPresent(this.initAnnotationType)) {
// 创建一个生命周期元素
//LifecycleElement element = new LifecycleElement(method);
currInitMethods.add(new LifecycleElement(method));
}
// 如果找到方法上标有@PreDestroy 注解,就加入到当前销毁方法集合中
if (this.destroyAnnotationType != null && method.isAnnotationPresent(this.destroyAnnotationType)) {
currDestroyMethods.add(new LifecycleElement(method));
}
});
// 赋值到初始化方法集合和销毁方法集合中
initMethods.addAll(0, currInitMethods);
destroyMethods.addAll(currDestroyMethods);
targetClass = targetClass.getSuperclass();
}
// 遍历查找
while (targetClass != null && targetClass != Object.class);
// 如果没有解析到,那么返回一个空的生命周期元数据,否则创建一个生命周期元素并放入初始化方法和销毁方法的集合
return (initMethods.isEmpty() && destroyMethods.isEmpty() ? this.emptyLifecycleMetadata :
new LifecycleMetadata(clazz, initMethods, destroyMethods));
}
最终发现实际上就是在解析我们的Bean
的方法上是否标记了@PostConstruc
t注解和@PreDestroy
方法,如果有就加入到生命周期元数据中,并且将解析到的方法放入到BeanDefinition
的externallyManagedInitMethods
和externallyManagedDestroyMethods
集合中。
Bean
初始化和销毁方法解析和执行流程如下:
其实InitDestoryAnnotationBeanPostProcessor
主要是对Bean
的做了自定义初始化和销毁方法的解析,以及在后期调用BPP
时执行。
自动装配注解的解析
在Spring
中自动装配的注解一般来说比较常用的有两个,一个@Autowired
是Spring
提供的,还有个是@Resource
是Java
的注解,这两个注解都能够完成自动装配,不过在实现时@Autowired
注解是由AutowiredAnnotationBeanPostProcessor
解析的和执行,而@Resource
注解是由CommonAnnotationBeanPostProcessor
解析和执行的。
除此之外,AutowiredAnnotationBeanPostProcessor
还解析了@Value
注解,CommonAnnotationBeanPostProcessor
还解析了@EJB
及@WebServiceRef
不过这个不常用。这些注解的解析跟解析@PostConstruct
和@PreDestroy
一样,这里就不做分析了,不同的是这几个注解可以标在字段和方法上,解析是需要对字段和方法都要解析,其他实现基本原理一致。
Spring Bean
的实例化基本就解析完了,接下来开始解析循环依赖和Bean
的属性填充部分。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/6188.html