This article is mainly based on the explanations of SpringBoot-2.3.3.RELEASE and Spring-5.2.8.RELEASE. In
Spring @Autowire
, the @Value
realization principle of annotations, the liberation of these two annotations into one explanation is mainly because their implementation is basically the same.
This article relates @Autowire
Notes: @Value
, @Qualifier
, @Lazy
, @Primary
, ,@javax.annotation.Priority
Related class introduction
The following are several important related classes:
org.springframework.beans.factory.config.BeanPostProcessor
org.springframework.beans.factory.support.MergedBeanDefinitionPostProcessor
org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor
org.s.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor
org.s.beans.factory.annotation.InjectionMetadata.InjectedElement
org.s.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.AutowiredFieldElement
org.s.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.AutowiredMethodElement
BeanPostProcessor
BeanPostProcessor is an interface class, all beans will pass through this post processor in the initial period, mainly providing the following two interface methods,
public interface BeanPostProcessor {
@Nullable
default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
@Nullable
default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
}
-
postProcessBeforeInitialization
The method is executed before the bean initialization method. For example, if the bean implements the InitializingBean interface, it will beInitializingBean#afterPropertiesSet
executed before the method. (Not really, because look created bean, anBeanPostProcessor
implementation class is already registered)
toBeanPostProcessor#postProcessBeforeInitialization
whether@PostConstruct
to perform initialization before the annotated method, which is uncertain , because the execution @PostConstruct initialization method is through theInitDestroyAnnotationBeanPostProcessor
implementation and InitDestroyAnnotationBeanPostProcessor By rewriting theBeanPostProcessor#postProcessBeforeInitialization
@PostConstruct function,CommonAnnotationBeanPostProcessor
itInitDestroyAnnotationBeanPostProcessor
has the same capabilities through inheritance . Therefore, it depends on the order in which the BeanPostProcessor implementation class is registered to determine whether it@PostConstruct
is executed in preference to annotations. -
postProcessAfterInitialization
The method is executed after the bean's initialization method. -
The subclass interface of BeanPostProcessor is as follows UML diagram
-
AbstractAutowireCapableBeanFactory#initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd)
The source code is as follows:
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareMethods(beanName, bean);
return null;
}, getAccessControlContext());
}else {
//判断是否实现了Aware接口,执行子类接口方法,
//此时只有:BeanNameAware,BeanClassLoaderAware,BeanFactoryAware
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
//调用BeanPostProcessor#postProcessBeforeInitialization
//ApplicationContextAwareProcessor#postProcessBeforeInitialization
//实现EnvironmentAware,..ApplicationContextAware等Aware的回调.
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
//如果bean实现了InitializingBean接口则执行接口的afterPropertiesSet方法
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
MergedBeanDefinitionPostProcessor
@Autowire
, @Value
The search is AutowiredAnnotationBeanPostProcessor
achieved by rewriting the method
public interface MergedBeanDefinitionPostProcessor extends BeanPostProcessor {
void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName);
default void resetBeanDefinition(String beanName) {
}
}
BeanDefinition
Mainly encapsulates the bean class information, such as whether it is a singleton, the name of the initialization method, the name of the dependent bean, and so on.
Before bean object is created, if a bean BeanDefinition is a subclass will first merge parent BeanDefinition, eventually return to a post-merger RootBeanDefinition
, MergedBeanDefinitionPostProcessor
it is Spring provided to interface development, and facilitate RootBeanDefinition combined to make custom modifications . Call AbstractAutowireCapableBeanFactory#doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
back the MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition
method when it is called .
InstantiationAwareBeanPostProcessor
(See note)
@Autowire
, @Value
the assignment is AutowiredAnnotationBeanPostProcessor
achieved by rewriting the postProcessProperties
method
public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {
//创建bean对象实例之前执行
default Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
return null;
}
//创建bean对象实例之后执行
default boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
return true;
}
//用于给bean对象中的成员属性赋值
//@Autowire,@Value的赋值就是AutowiredAnnotationBeanPostProcessor通过重写该方法实现
default PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName)
throws BeansException {
return null;
}
@Deprecated //标记为过时
default PropertyValues postProcessPropertyValues(
PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
return pvs;
}
}
AutowiredAnnotationBeanPostProcessor
@Autowire
, @Value
, @Lookup
And other annotations are made AutowiredAnnotationBeanPostProcessor
to realize, in this paper to explain @Autowire
, @Value
comment function realization principle.
AutowiredAnnotationBeanPostProcessor
Inheritance are as follows:
AutowiredAnnotationBeanPostProcessor
a structure as follows: the main definition @Autowire
, @Value
two annotations are filtered target bean conditions,
if the bean Field
, Method
is marked two annotation is required attribute values corresponding to infuse or bean.
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.
}
}
In the process of realizing @Autowire and @Value functions, AutowiredAnnotationBeanPostProcessor mainly plays two roles.
- Rewriting
MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition
method, all reflecting traversal beanClassField
andMethod
find marked with bean@Autowire
,@Value
aField
, ,Method
encapsulatedorg.springframework.beans.factory.annotation.InjectionMetadata
in. Stored in member variablesprivate final Map<String, InjectionMetadata> injectionMetadataCache = new ConcurrentHashMap<>(256);
.
AutowiredAnnotationBeanPostProcessor#postProcessMergedBeanDefinition
Source code:
@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
metadata.checkConfigMembers(beanDefinition);
}
findAutowiringMetadata
The method will be called internally to AnnotationUtils#isCandidateClass(Class<?>, Class<? extends Annotation>)
determine whether a certain class may be marked with a certain annotation. The source code is as follows:
public static boolean isCandidateClass(Class<?> clazz, Class<? extends Annotation> annotationType) {
return isCandidateClass(clazz, annotationType.getName());
}
public static boolean isCandidateClass(Class<?> clazz, String annotationName) {
//如果注解所在包是java开头,任何类上都可能标记这个注解
if (annotationName.startsWith("java.")) {
return true;
}
//注解所在包不是java开头的情况
//可以认为是自定义注解,例如Spring的@Service @Autowired @Value 对Spring来说就是其自定义注解
//如果类的包是以java开头,则不可能标记自定义的注解
if (AnnotationsScanner.hasPlainJavaAnnotationsOnly(clazz)) {
return false;
}
return true;
}
AnnotationsScanner.hasPlainJavaAnnotationsOnly(clazz)
static boolean hasPlainJavaAnnotationsOnly(Class<?> type) {
return (type.getName().startsWith("java.") || type == Ordered.class);
}
- Rewrite the
InstantiationAwareBeanPostProcessor#postProcessProperties
method, traverse the injectionMetadataCacheInjectionMetadata
, call theorg.springframework.beans.factory.annotation.InjectionMetadata#inject
method,@Autowire
and@value
assign values to the bean and attribute fields.
AutowiredAnnotationBeanPostProcessor#postProcessProperties
Source code:
@Override
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
There is an abstract
internal class InjectionMetadata.InjectedElement
, which is mainly used to give Field
or Method
assign values.
AutowiredAnnotationBeanPostProcessor
There are two private inner classes inherited separately InjectedElement
.
AutowiredAnnotationBeanPostProcessor.AutowiredFieldElement
: Assign values to Field
AutowiredAnnotationBeanPostProcessor.AutowiredMethodElement
through reflection.: Assign values to Setter Method through reflection.
AutowiredAnnotationBeanPostProcessor.AutowiredFieldElement#inject
Source code:
@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);
}
}
AutowiredAnnotationBeanPostProcessor.AutowiredFieldElement#resolveFieldValue
Source code:
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;
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 beanFactory.resolveDependency
(default DefaultListableBeanFactory
) overall logic called inside the method is roughly as follows:
- Judge
Filed
orMethod
on whether there are@Lazy
notes, if there is created brokers for lazy loading. - If it is not lazy loading, it is judged whether there is an
@Value
annotation. If it exists, the value value is obtained. Finally, byPropertySourcesPropertyResolver#getProperty(java.lang.String, java.lang.Class<T>, boolean)
parsing the property value ( in fact, it isConfigurableEnvironment
the MutablePropertySources collection encapsulated in ), after obtaining the property value, it will be analyzed by SpringEL. After parsing, theSimpleTypeConverter
object performs a data type conversion and returns to the type required by Filed. - If there is no
@Value
comment, it is based on@Autowire
injecting the bean, theDefaultListableBeanFactory
variable beanName all, determines whether the object type and the required identical, is saved to List beanName set (a plurality of the same interface implementation class may occur, so use set),- Traverse beanNames to determine whether each bean meets the requirements, if it exists, it
@Qualifier
will determine whether the name matches, and if it matches, the corresponding bean object will be obtained. If there is no@Qualifier
annotation, all bean objects are obtained and encapsulated in Map. - If there are multiple instance objects in the Map, then judge
@Primary
the implementation class with annotations and return the object.@Primary
There can only be one implementation of the same type - If there are multiple instance objects in the Map, but there are no
@Primary
annotations, compare whether there are@javax.annotation.Priority
annotations and choose the higher priority to return. The smaller the value, the higher the priority. - Match by name
- If the above rules are not met, an exception message will be thrown and multiple bean implementations will appear.
- Traverse beanNames to determine whether each bean meets the requirements, if it exists, it
The matching logic of dependency injection Bean in Spring is as follows
DefaultListableBeanFactory#determineAutowireCandidate
protected String determineAutowireCandidate(Map<String, Object> candidates, DependencyDescriptor descriptor) {
Class<?> requiredType = descriptor.getDependencyType();
String primaryCandidate = determinePrimaryCandidate(candidates, requiredType);
if (primaryCandidate != null) {
return primaryCandidate;
}
String priorityCandidate = determineHighestPriorityCandidate(candidates, requiredType);
if (priorityCandidate != null) {
return priorityCandidate;
}
// Fallback
for (Map.Entry<String, Object> entry : candidates.entrySet()) {
String candidateName = entry.getKey();
Object beanInstance = entry.getValue();
if ((beanInstance != null && this.resolvableDependencies.containsValue(beanInstance)) ||
matchesBeanName(candidateName, descriptor.getDependencyName())) {
return candidateName;
}
}
return null;
}