The source of this article is How to initialize Spring Bean Please indicate the source
I have been doing Java for many years, and I have always had a doubt: how does Spring initialize beans, how to invoke reflection to instantiate objects, and do it yourself to solve this doubt.
In the past, I thought that the instantiation of spring bean objects was always done by the BeanPostProcessor
interface implementation class. I just didn't know the specific implementation class. Let's verify this conjecture.
L3 cache
Why the interviewer especially likes to ask about the creation of the third-level cache of beans, mainly because the bean creation is completed with the conversion between the third-level caches, and the different states of the objects are stored in different caches. I will analyze the code below, by the way. Supports how objects flow through the cache.
First understand the spring three-level cache.
/** 一级缓存 用于存放完全可以使用单例bean,也就是初始化完成并且注入所有依赖 */
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
/** 二级缓存 过早暴露单例对象,此时bean刚刚完成初始化,未完成属性注入和执行 init 方法 */
private final Map<String, Object> earlySingletonObjects = new ConcurrentHashMap<>(16);
/** 三级缓存 装载创建bean的工厂对象 */
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16)
The main function of the third-level cache: To create an object ObjectFactory, first put it into the third-level cache. When calling getObject to create an instance, the created object will be added to the second-level cache, and the third-level cache will be deleted. When the object has completed the initialization method and Attribute injection, then add the cache to the first-level cache, and delete the second-level cache.
doGetBean
Starting from the source, all spring bean initialization is implemented by the AbstractBeanFactory.doGetBean
method. Below I will reduce the bloated part of the source code and post it.
protected <T> T doGetBean(
String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
throws BeansException {
//name 前缀处理 beanFactory beanName 带有&开头
String beanName = transformedBeanName(name);
Object beanInstance;
//从三级缓存去取bean,三级中都没有则返回null,说明对象还没有创建
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) { //如果缓存中bean 是FactoryBean实例,要通过接口获取到实际bean
beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
else {
//判断bean对象标记是否正在创建中,如果正在创建中则不应该继续下去,出现依赖循环就会出现这个错误
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
BeanFactory parentBeanFactory = getParentBeanFactory();
// 检查父容器是否存在,尝试从父容器中获取
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
String nameToLookup = originalBeanName(name);
if (parentBeanFactory instanceof AbstractBeanFactory) {
return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
nameToLookup, requiredType, args, typeCheckOnly);
}
else if (args != null) {
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else if (requiredType != null) {
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
else {
return (T) parentBeanFactory.getBean(nameToLookup);
}
}
if (!typeCheckOnly) { //缓存中标记beanName 正在被创建
markBeanAsCreated(beanName);
}
StartupStep beanCreation = this.applicationStartup.start("spring.beans.instantiate")
.tag("beanName", name);
try {
if (requiredType != null) {
beanCreation.tag("beanType", requiredType::toString);
}
RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
// Guarantee initialization of beans that the current bean depends on.
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) { //bean 中@DependsOn 信息,用于标记bean之间初始化顺序,优先创建@DependsOn 中bean
for (String dep : dependsOn) {
if (isDependent(beanName, dep)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
registerDependentBean(dep, beanName);
try {
getBean(dep);
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
}
}
}
//创建单例对象
if (mbd.isSingleton()) { //重点就在这里实例化对象 ,getSingleton 就是在这里将创建完成对象加入到一级缓存中
sharedInstance = getSingleton(beanName, () -> {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex)
destroySingleton(beanName);
throw ex;
}
});
//如果生成bean 是FactoryBean ,再获取真正的对象
beanInstance = 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);
}
beanInstance = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}
else { // session request 这些作用域,由作用域容器去管理这些对象
String scopeName = mbd.getScope();
if (!StringUtils.hasLength(scopeName)) {
throw new IllegalStateException("No scope name defined for bean ´" + beanName + "'");
}
Scope scope = this.scopes.get(scopeName);
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
}
try {
Object scopedInstance = scope.get(beanName, () -> {
beforePrototypeCreation(beanName);
try {
return createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
});
beanInstance = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
}
catch (IllegalStateException ex) {
throw new ScopeNotActiveException(beanName, scopeName, ex);
}
}
}
catch (BeansException ex) {
beanCreation.tag("exception", ex.getClass().toString());
beanCreation.tag("message", String.valueOf(ex.getMessage()));
cleanupAfterBeanCreationFailure(beanName);
throw ex;
}
finally {
beanCreation.end();
}
}
//返回初始化成功的对象,一个对象初始化就这样完成的了
return adaptBeanInstance(name, beanInstance, requiredType);
}
A brief summary of the above code flow:
- Get it from the third-level cache first, if there is none in the cache. Then go to determine whether there is a parent container, and get it from the parent container. Without officially entering the bean initialization process, first obtain the RootBeanDefinition and bean class meta information according to the beanName, and process the beans in dependsOn first to ensure the creation order of bean dependencies. The annotation
org.springframework.context.annotation.@DependsOn
will be explained below. The next step is to initialize the bean object according to different scopes. The initialization process is like this, we will focus on how to instantiate the singleton bean, and focus onAbstractAutowireCapableBeanFactory.createBean
to obtain and register a singleton object
@DependsOn
annotation means that instantiating an object depends on an instantiation, but does not need to hold the instance object. For example, bean A needs to rely on bean b to be instantiated, but bean b does not need to be used as its attribute, and is often used to mark the instantiation order of different instances.
Look at the getSingleton method
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
synchronized (this.singletonObjects) {
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
if (this.singletonsCurrentlyInDestruction) { //标记bean 是否在销毁
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!)");
}
beforeSingletonCreation(beanName);
boolean newSingleton = false;
boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
if (recordSuppressedExceptions) {
this.suppressedExceptions = new LinkedHashSet<>();
}
try {
singletonObject = singletonFactory.getObject();
newSingleton = true;
}
catch (IllegalStateException ex) {
}
catch (BeanCreationException ex) {
throw ex;
}
finally {
if (recordSuppressedExceptions) {
this.suppressedExceptions = null;
}
afterSingletonCreation(beanName);
}
if (newSingleton) {
addSingleton(beanName, singletonObject); //就是在这里删除二三级缓存,提交到一级缓存
}
}
return singletonObject;
}
}
protected void addSingleton(String beanName, Object singletonObject) {
synchronized (this.singletonObjects) {
this.singletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.add(beanName);
}
}
Adding it to the first-level cache means that the bean has been instantiated and can be used normally. Let's see how instantiation and property injection are performed.
createBean
Enter AbstractAutowireCapableBeanFactory.createBean
below
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
RootBeanDefinition mbdToUse = mbd;
//克隆一份mbd => mbdToUse
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();
}
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.
//通过BeanPostProcessors 增强返回一个代理对象,这个生成AOP的代理对象,使用多个BeanPostProcessors来处理
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 {
// bean 对象实例化就这里实现
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
return beanInstance;
}
catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
throw ex;
}
catch (Throwable ex) {
throw new BeanCreationException(
mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
}
}
The logic here is relatively simple, clone a RootBeanDefinition to initialize the object, resolveBeforeInstantiation is mainly used to initialize the proxy object, mainly use the BeanPostProcessor subclass InstantiationAwareBeanPostProcessor implementation method to realize the object initialization, and call the post method after the instantiation is successful. Object dependency injection, here you can see that the returned object of this method directly jumps out of the method stack, here you can see that there is still a difference between a singleton and a proxy object. Singleton object initialization is implemented in doCreateBean
doCreateBean
Here's AbstractAutowireCapableBeanFactory.doCreateBean
very close to how the object is instantiated
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) {
instanceWrapper = createBeanInstance(beanName, mbd, args); //这个就是实例化方法
}
Object bean = instanceWrapper.getWrappedInstance();
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
mbd.resolvedTargetType = beanType;
}
// 使用BeanDefinitionPostProcessors 对合并bean进行实例化
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
try {
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Post-processing of merged bean definition failed", ex);
}
mbd.postProcessed = true;
}
}
// 这里就需要用到上面说的三级缓存知识了
// 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)); //将已经实例化的对象加入到第三级缓存 singletonFactories
}
// Initialize the bean instance.
Object exposedObject = bean;
try {
populateBean(beanName, mbd, instanceWrapper); //对属性进入注入,下面会具体分析的
exposedObject = initializeBean(beanName, exposedObject, mbd); //执行初始化方法,或者注入Aware 接口bean
}
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);
}
}
//下面代码省略
//主要就是对设置了DisposableBean 接口销毁钩子方法处理
}
This code is mainly divided into three parts
- The instance is initialized, the object is created, and it is added to the L3 cache. The third-level cache is often used to store proxy objects, because some classes require dynamic proxy methods and need to generate proxy objects, which will be delegated to the third-level cache method ObjectFactroy to implement, and ordinary objects will be returned directly if they are not needed.
- Property injection for instantiated beans
- Execute the initialization method, the DisposableBean interface is added to the disposableBeans container
instantiateBean
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
// Make sure bean class is actually resolved at this point.
Class<?> beanClass = resolveBeanClass(mbd, beanName);
if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
}
Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
if (instanceSupplier != null) {// 有实现Supplier 接口,由instanceSupplier.get() 方法创建实例
return obtainFromSupplier(instanceSupplier, beanName);
}
//factoryName 使用工厂模式创建bean,调用工厂方法去创建,这个支持静态方法和factoryBean.invoke
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);
}
}
// 获取构造函数参数
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);
}
The instantiation method instantiateBean will eventually call SimpleInstantiationStrategy.instantiate for instantiation
instantiate
public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) {
// Don't override the class with CGLIB if no overrides.
if (!bd.hasMethodOverrides()) {
Constructor<?> constructorToUse;
synchronized (bd.constructorArgumentLock) {
constructorToUse = (Constructor<?>) bd.resolvedConstructorOrFactoryMethod;
if (constructorToUse == null) {
final Class<?> clazz = bd.getBeanClass();
if (clazz.isInterface()) {
throw new BeanInstantiationException(clazz, "Specified class is an interface");
}
try {
if (System.getSecurityManager() != null) {
constructorToUse = AccessController.doPrivileged(
(PrivilegedExceptionAction<Constructor<?>>) clazz::getDeclaredConstructor);
}
else {
constructorToUse = clazz.getDeclaredConstructor(); //获取构造函数
}
bd.resolvedConstructorOrFactoryMethod = constructorToUse;
}
catch (Throwable ex) {
throw new BeanInstantiationException(clazz, "No default constructor found", ex);
}
}
}
return BeanUtils.instantiateClass(constructorToUse); //调用构造函数进行实例化
}
else {
// Must generate CGLIB subclass.
return instantiateWithMethodInjection(bd, beanName, owner);
}
}
instantiateClass
@Override
public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) {
// Don't override the class with CGLIB if no overrides.
if (!bd.hasMethodOverrides()) {
Constructor<?> constructorToUse;
synchronized (bd.constructorArgumentLock) {
constructorToUse = (Constructor<?>) bd.resolvedConstructorOrFactoryMethod;
if (constructorToUse == null) {
final Class<?> clazz = bd.getBeanClass();
if (clazz.isInterface()) {
throw new BeanInstantiationException(clazz, "Specified class is an interface");
}
try {
if (System.getSecurityManager() != null) {
constructorToUse = AccessController.doPrivileged(
(PrivilegedExceptionAction<Constructor<?>>) clazz::getDeclaredConstructor);
}
else {
constructorToUse = clazz.getDeclaredConstructor();
}
bd.resolvedConstructorOrFactoryMethod = constructorToUse;
}
catch (Throwable ex) {
throw new BeanInstantiationException(clazz, "No default constructor found", ex);
}
}
}
return BeanUtils.instantiateClass(constructorToUse); //调用构造器进行初始化
}
else {
// Must generate CGLIB subclass.
return instantiateWithMethodInjection(bd, beanName, owner);
}
}
Here, we should pay attention to determine whether the bean has a method to rewrite. If not, use the constructor generated by reflection. If there is, use the gclib method to create a proxy object. The specific implementation method is org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate
. Interested students can go to learn.
At this point a simple bean instantiation is complete.
injection
Let's enter another feature of IOC, bean injection, starting with AbstractAutowireCapableBeanFactory.populateBean
method
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
// 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.postProcessAfterInstantiation 如果返回true,目标实例内部的返回值会被populate,否则populate这个过程会被忽视
//翻译说如果返回true可以执行字段注入 真的6666啊
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
if (!bp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
return;
}
}
}
PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
//获取注入方式分布有4种
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;
}
boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
//依赖方式,模式都是没有类型检查,这种依赖方式一般都是xml 配置用得比较多,没有配置这里都是返回false
boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE); /
PropertyDescriptor[] filteredPds = null;
if (hasInstAwareBpps) {
if (pvs == null) {
pvs = mbd.getPropertyValues();
}
for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
PropertyValues pvsToUse = bp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName); //获取注解标注需要注入方法或者是字段,并且进行注入
if (pvsToUse == null) {
if (filteredPds == null) {
filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
}
pvsToUse = bp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
return;
}
}
pvs = pvsToUse;
}
}
if (needsDepCheck) {
if (filteredPds == null) {
filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
}
checkDependencies(beanName, mbd, filteredPds, pvs);
}
if (pvs != null) {
applyPropertyValues(beanName, mbd, bw, pvs);
}
}
Little knowledge points:
AutowireCapableBeanFactory.AUTOWIRE_NO indicates that no external class injection will be performed on the current bean. Conventional use of @Autowire and @Resource are of this type
The remaining three are set autowireMode through xml or AutowireCapableBeanFactory.autowire(Class<?> beanClass, int autowireMode, boolean dependencyCheck).
According to the above code, it can be known that the main process bean injection is processed by InstantiationAwareBeanPostProcessor, briefly explaining the interface method
method | describe |
---|---|
postProcessBeforeInitialization | The method is the first executed method, it is called before the target object is instantiated, the return value type of this method is Object, we can return any type of value. Since the target object has not been instantiated at this time, this return value can be used to replace the original instance of the target object (such as a proxy object). If the return value of the method replaces the original target object, only the postProcessAfterInitialization method will be called, and other methods will not be called; otherwise, follow the normal process. |
postProcessAfterInitialization | The method is called after the target object is instantiated. At this time, the object has been instantiated, but the properties of the instance have not been set, and are all null. Because its return value is one of the factors that determines whether to call the postProcessPropertyValues method (because there is another factor is mbd.getDependencyCheck()); if the method returns false and no check is needed, then postProcessPropertyValues will be ignored and not executed; If it returns true, postProcessPropertyValues will be executed |
postProcessPropertyValues | Called after assigning a value to a bean property, modifying the property value. If the postProcessAfterInstantiation method returns false, this method may not be called. The property value can be modified within this method |
postProcessProperties | Bean property assignment is to call this method |
The InstantiationAwareBeanPostProcessor interface implementation class is mainly divided into 3
- ConfigurationClassPostProcessor : You can see the @Configuration instantiation by looking at the class name, and there is no attribute injection logic, so I will skip it.
- CommonAnnotationBeanPostProcessor : This class implements bean injection, but implements JSR-250 annotations, @Resource, @EJB, @WebServiceRef, @WebServiceContext, @PostConstruct, @PreDestory annotations.
- AutowiredAnnotationBeanPostProcessor : Implement @Autowired, @Value injection, and support JSR-330's @Inject, mainly analyze this class to know the bean injection.
Analysis of AutowiredAnnotationBeanPostProcessor
private final Set<Class<? extends Annotation>> autowiredAnnotationTypes = new LinkedHashSet<>(4);
@SuppressWarnings("unchecked")
public AutowiredAnnotationBeanPostProcessor() {
this.autowiredAnnotationTypes.add(Autowired.class);
this.autowiredAnnotationTypes.add(Value.class);
try {
this.autowiredAnnotationTypes.add((Class<? extends Annotation>)
ClassUtils.forName("javax.inject.Inject", AutowiredAnnotationBeanPostProcessor.class.getClassLoader()));
logger.trace("JSR-330 'javax.inject.Inject' annotation found and supported for autowiring");
}
catch (ClassNotFoundException ex) {
// JSR-330 API not available - simply skip.
}
}
Add support annotations to the collection during initialization, and then use the scanner to scan methods, constructors, fields, and inject if there are these annotations.
Let's see how to judge whether it needs to be injected
@Nullable
private MergedAnnotation<?> findAutowiredAnnotation(AccessibleObject ao) {
MergedAnnotations annotations = MergedAnnotations.from(ao);
for (Class<? extends Annotation> type : this.autowiredAnnotationTypes) {
MergedAnnotation<?> annotation = annotations.get(type);
if (annotation.isPresent()) {
return annotation;
}
}
return null;
}
AccessibleObject is the parent class of Method, Field, and Constructor.
How postProcessProperties implements bean injection
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
//获取需要注入字段,方法
InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
try {
metadata.inject(bean, beanName, pvs); //注入
}
catch (BeanCreationException ex) {
throw ex;
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex);
}
return pvs;
}
//下面就行获取InjectionMetadata
private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs) {
// Fall back to class name as cache key, for backwards compatibility with custom callers.
String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
// 快速从缓存中获取,如果没有加锁去解析,然后在结果放入缓存中
InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);
if (InjectionMetadata.needsRefresh(metadata, clazz)) {
synchronized (this.injectionMetadataCache) { //双重检查
metadata = this.injectionMetadataCache.get(cacheKey);
if (InjectionMetadata.needsRefresh(metadata, clazz)) {
if (metadata != null) {
metadata.clear(pvs);
}
metadata = buildAutowiringMetadata(clazz);
this.injectionMetadataCache.put(cacheKey, metadata);
}
}
}
return metadata;
}
- InjectionMetadata is mainly the type of the collection bean that needs to be injected, because the bean Class information has been parsed, which is equivalent to loading the parsed result
See how to scan methods and fields
private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {
//从给定注解中判断class 是否携带这个注解
if (!AnnotationUtils.isCandidateClass(clazz, this.autowiredAnnotationTypes)) {
return InjectionMetadata.EMPTY;
}
List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();
Class<?> targetClass = clazz;
do {
final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>();
//遍历所有Field,找出扫描的注解,特意标注不支持static 修饰field
ReflectionUtils.doWithLocalFields(targetClass, field -> {
MergedAnnotation<?> ann = findAutowiredAnnotation(field);
if (ann != null) {
if (Modifier.isStatic(field.getModifiers())) {
if (logger.isInfoEnabled()) {
logger.info("Autowired annotation is not supported on static fields: " + field);
}
return;
}
// 获取注解内 required 值
boolean required = determineRequiredStatus(ann);
currElements.add(new AutowiredFieldElement(field, required));
}
});
ReflectionUtils.doWithLocalMethods(targetClass, method -> {
//获取方法上桥接方法,因为泛型类型擦除,要对桥接方法进行安全检查,防止在调用是出现异常
Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
return;
}
//获取注解
MergedAnnotation<?> ann = findAutowiredAnnotation(bridgedMethod);
//方法安全检查
if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
if (Modifier.isStatic(method.getModifiers())) { //不支持静态方法注入
if (logger.isInfoEnabled()) {
logger.info("Autowired annotation is not supported on static methods: " + method);
}
return;
}
if (method.getParameterCount() == 0) {
if (logger.isInfoEnabled()) {
logger.info("Autowired annotation should only be used on methods with parameters: " +
method);
}
}
boolean required = determineRequiredStatus(ann);
PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
currElements.add(new AutowiredMethodElement(method, required, pd));
}
});
// 这样写是为了后面加入排在队列前面,父类属性优先于子类
elements.addAll(0, currElements);
targetClass = targetClass.getSuperclass();
}
while (targetClass != null && targetClass != Object.class); //这里写得很好,向上解析父类,直到是Object 为止
return InjectionMetadata.forElements(elements, clazz);
}
The logic is very simple, that is, go to the class to obtain the specified annotation according to the given annotation, so as to obtain the type that needs to be injected, but a few lines of simple code can show the powerful coding ability, and I learned 👍.
Now the object that needs to be injected has been obtained, let's see how to inject it
public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
Collection<InjectedElement> checkedElements = this.checkedElements;
Collection<InjectedElement> elementsToIterate =
(checkedElements != null ? checkedElements : this.injectedElements);
if (!elementsToIterate.isEmpty()) {
for (InjectedElement element : elementsToIterate) {
element.inject(target, beanName, pvs);
}
}
}
@Override
protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
Field field = (Field) this.member;
Object value;
if (this.cached) {
try {
value = resolvedCachedArgument(beanName, this.cachedFieldValue);
}
catch (NoSuchBeanDefinitionException ex) {
// Unexpected removal of target bean for cached argument -> re-resolve
value = resolveFieldValue(field, bean, beanName);
}
}
else {
value = resolveFieldValue(field, bean, beanName);
}
if (value != null) {
ReflectionUtils.makeAccessible(field);
field.set(bean, value);
}
}
private Object resolveFieldValue(Field field, Object bean, @Nullable String beanName) {
DependencyDescriptor desc = new DependencyDescriptor(field, this.required);
desc.setContainingClass(bean.getClass());
Set<String> autowiredBeanNames = new LinkedHashSet<>(1);
Assert.state(beanFactory != null, "No BeanFactory available");
TypeConverter typeConverter = beanFactory.getTypeConverter(); //类型转换器
Object value;
try {
value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
}
catch (BeansException ex) {
throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex);
}
synchronized (this) {
if (!this.cached) {
Object cachedFieldValue = null;
if (value != null || this.required) {
cachedFieldValue = desc;
// 将注入关系添加到容器中,方便bean销毁时同步销毁
registerDependentBeans(beanName, autowiredBeanNames);
if (autowiredBeanNames.size() == 1) {
String autowiredBeanName = autowiredBeanNames.iterator().next();
if (beanFactory.containsBean(autowiredBeanName) &&
beanFactory.isTypeMatch(autowiredBeanName, field.getType())) { //这些都是为了缓存起来
cachedFieldValue = new ShortcutDependencyDescriptor(
desc, autowiredBeanName, field.getType());
}
}
}
this.cachedFieldValue = cachedFieldValue;
this.cached = true;
}
}
return value;
}
}
The main core is that the type instance that needs to be injected is obtained from the cache in beanFactory.resolveDependency
Enter DefaultListableBeanFactory to see
public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
if (Optional.class == descriptor.getDependencyType()) {
return createOptionalDependency(descriptor, requestingBeanName);
}
else if (ObjectFactory.class == descriptor.getDependencyType() ||
ObjectProvider.class == descriptor.getDependencyType()) {
return new DependencyObjectProvider(descriptor, requestingBeanName);
}
else if (javaxInjectProviderClass == descriptor.getDependencyType()) {
return new Jsr330Factory().createDependencyProvider(descriptor, requestingBeanName);
}
else {
//懒加载 扫描@Lazy注解,返回一个代理对象
Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
descriptor, requestingBeanName);
if (result == null) {
result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
}
return result;
}
}
@Lazy uses annotations to decorate beans or classes, which will not be created immediately when the container is initialized, but will only be created when the bean needs to be used.
Depending on the types of Optional, ObjectFactory, Provider, and lazy loading scenarios, the essence of these processes is to call the doResolveDependency method to initialize the object. No matter what kind of object, the original object must be obtained and then handed over to these interfaces for packaging enhancement.
public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
//如果这个注入是通过构造器注入,可以从构造器解析缓存中去获取注入信息点
InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
try {
Object shortcut = descriptor.resolveShortcut(this);
if (shortcut != null) {
return shortcut;
}
Class<?> type = descriptor.getDependencyType();
//尝试从注解中获取默认值 @Value 的value
Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);
if (value != null) {
if (value instanceof String) {
String strVal = resolveEmbeddedValue((String) value);
BeanDefinition bd = (beanName != null && containsBean(beanName) ?
getMergedBeanDefinition(beanName) : null);
value = evaluateBeanDefinitionString(strVal, bd);
}
TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
try {
return converter.convertIfNecessary(value, type, descriptor.getTypeDescriptor());
}
catch (UnsupportedOperationException ex) {
// A custom TypeConverter which does not support TypeDescriptor resolution...
return (descriptor.getField() != null ?
converter.convertIfNecessary(value, type, descriptor.getField()) :
converter.convertIfNecessary(value, type, descriptor.getMethodParameter()));
}
}
//多种混合类型处理,stream、collection、Map Array 这些
Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
if (multipleBeans != null) {
return multipleBeans;
}
//根据类型获取容器中bean名,返回map key就是bean名,value 初始从容器中获取对象,如果没有找到就会抛出异常了
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
if (matchingBeans.isEmpty()) {
if (isRequired(descriptor)) {
raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
}
return null;
}
String autowiredBeanName;
Object instanceCandidate;
if (matchingBeans.size() > 1) { //出现一个类型,不同实例,可以根据@Primary, @Priority、属性名方式去配置
autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
if (autowiredBeanName == null) {
if (isRequired(descriptor) || !indicatesMultipleBeans(type)) { //没有确定,抛出异常
return descriptor.resolveNotUnique(descriptor.getResolvableType(), matchingBeans);
}
else {
return null;
}
}
instanceCandidate = matchingBeans.get(autowiredBeanName);
}
else {
// We have exactly one match.
Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
autowiredBeanName = entry.getKey();
instanceCandidate = entry.getValue();
}
if (autowiredBeanNames != null) {
autowiredBeanNames.add(autowiredBeanName);
}
if (instanceCandidate instanceof Class) { //这里其实就是从容器中获取实例,如果这时候没有初始化,就走上面初始化流程
instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
}
Object result = instanceCandidate;
if (result instanceof NullBean) {
if (isRequired(descriptor)) {
raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
}
result = null;
}
if (!ClassUtils.isAssignableValue(type, result)) {
throw new BeanNotOfRequiredTypeException(autowiredBeanName, type, instanceCandidate.getClass());
}
return result;
}
finally {
ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
}
}
This method is a simple summary. First, it deals with the @Value situation, and then uses findAutowireCandidates to get the instance from the container through the type. If the instance has not been initialized, it will call the above initialization process and return the initialization object. Corresponding processing is performed according to the injection type, such as stream and Collection, these mixed types are added directly. If there are multiple beans of one type, then the annotations @Primary and @Priority are used to judge or match the beanName according to the attribute name, and finally return the bean object.
Here is a brief look at a bean initialization process.
Summarize
Now I know that Bean instantiation is created by a strategy pattern using reflection attack classes, which has nothing to do with BeanPostProcessor. When I first started learning spring, the teacher said that @Autowired and @Resources are compared and injected based on type and beanName, which is not entirely correct. He obtains the bean by type. If a type has multiple beanNames, it is injected through the bean and attribute name. After using Spring for so many years, I have never used @DependsOn, @Primary, @Priority, @Lookup. If you don't look at the source code, you don't know that there is this feature. After reading the entire source code, I have a clearer view of the bean life cycle. Bean instantiation -> attribute injection -> execute initialization method -> join spring container
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。