1. @Autowired和@Value注解--Spring5.2.X
首先来看一下这两个注解的源码
@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Autowired {
boolean required() default true;
}
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Value {
String value();
}
从上面的源码可以看出来两个注解都可以用于 方法、参数、变量、注解类型 。@Autowired 还能用于构造函数。通过这个类使用的地方可以看出来,主要用于类的内部。所以主要是通过 BeanPostProcessor 来处理这两个注解。
2. 注解处理类AutowiredAnnotationBeanPostProcessor源码解析
首先看 AutowiredAnnotationBeanPostProcessor 是如何注入到上下文中的。通过代码发现主要是有 AnnotationConfigUtils#registerAnnotationConfigProcessors 注入到上下文中的。看一下源码
public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
BeanDefinitionRegistry registry, @Nullable Object source) {
DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
if (beanFactory != null) {
//省略代码
//注入AutowiredAnnotationBeanPostProcessor类的定义
if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
}
}
//省略代码
return beanDefs;
}
下面来看一下 AutowiredAnnotationBeanPostProcessor 源码:
public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter
implements MergedBeanDefinitionPostProcessor, PriorityOrdered, BeanFactoryAware {
//省略代码
}
AutowiredAnnotationBeanPostProcessor 继承了 InstantiationAwareBeanPostProcessorAdapter 类(这个类是BeanPostProcessor的实现)。然后还实现了其他的三个接口。
首先来看一下这个类的构造函数:
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.
}
}
从这个构造函数可以看出来主要处理 @Autowired、@Value、javax.inject.Inject 。 第三个是javax。这就是对 JSR-330 标准的支持。通过调用 postProcessProperties 方法来处理以上的三个注解
@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;
}
主要是通过 findAutowiringMetadata 方法来获取自动注入元数据。以及通过 InjectionMetadata#inject 方法来注入元数据。
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.needsRefresh
判断从缓存中获取的注入元数据是否需要刷新:
public static boolean needsRefresh(@Nullable InjectionMetadata metadata, Class<?> clazz) { return (metadata == null || metadata.targetClass != clazz); } -
buildAutowiringMetadata
创建自动注入的元数据
下面来看一下 buildAutowiringMetadata 的源码是如何创建自动注入元数据的。
private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {
//判断是否包含 @Autowired @Value 或者@Inject注解
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<>();
//通过反射获取targetClass
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;
}
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);
return InjectionMetadata.forElements(elements, clazz);
}
通过上面的代码可以看出来处理主要分成了两类:
- 处理类的字段上面的注解
- 处理方法上面注解
根据处理的不同的数据创建两个不同的自动注入元素。字段的创建 AutowiredFieldElement 、 方法上面的注解创建 AutowiredMethodElement 。
private class AutowiredFieldElement extends InjectionMetadata.InjectedElement {
//省略代码
}
private class AutowiredMethodElement extends InjectionMetadata.InjectedElement {
//省略代码
}
以上两个都是内部类。都继承了 InjectionMetadata.InjectedElement 的接口。根据不同类型创建好以后通过调用:
return InjectionMetadata.forElements(elements, clazz);
创建返回数据。也就是调用 findAutowiringMetadata 方法中的 buildAutowiringMetadata 方法。在前面分析过
public void processInjection(Object bean) throws BeanCreationException {
Class<?> clazz = bean.getClass();
InjectionMetadata metadata = findAutowiringMetadata(clazz.getName(), clazz, null);
try {
//这里就是注入数据。
metadata.inject(bean, null, null);
}
catch (BeanCreationException ex) {
throw ex;
}
catch (Throwable ex) {
throw new BeanCreationException(
"Injection of autowired dependencies failed for class [" + clazz + "]", ex);
}
}
这里可以分一下 InjectionMetadata#inject 方法
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) {
if (logger.isTraceEnabled()) {
logger.trace("Processing injected element of bean '" + beanName + "': " + element);
}
//主要是InjectedElement#inject来处理
element.inject(target, beanName, pvs);
}
}
}
最终是通过调用 InjectedElement#inject 方法来注入。下面来分析一下 AutowiredFieldElement 和 AutowiredMethodElement 的实现。
private class AutowiredFieldElement extends InjectionMetadata.InjectedElement {
private final boolean required;
private volatile boolean cached = false;
@Nullable
private volatile Object cachedFieldValue;
public AutowiredFieldElement(Field field, boolean required) {
super(field, null);
this.required = required;
}
@Override
protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
Field field = (Field) this.member;
Object value;
//第一次不会进入因为cached默认为false
if (this.cached) {
value = resolvedCachedArgument(beanName, this.cachedFieldValue);
}
else {
//创建一个依赖的描述
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();
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) {
if (value != null || this.required) {
this.cachedFieldValue = desc;
registerDependentBeans(beanName, autowiredBeanNames);
if (autowiredBeanNames.size() == 1) {
String autowiredBeanName = autowiredBeanNames.iterator().next();
if (beanFactory.containsBean(autowiredBeanName) &&
beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {
this.cachedFieldValue = new ShortcutDependencyDescriptor(
desc, autowiredBeanName, field.getType());
}
}
}
else {
this.cachedFieldValue = null;
}
this.cached = true;
}
}
}
//在Value不为空的情况下通过反射设置值
if (value != null) {
ReflectionUtils.makeAccessible(field);
field.set(bean, value);
}
}
}
AutowiredMethodElement 的实现和 AutowiredFieldElement 实现差不多。
3. 自定义拓展
自定义的拓展可以参考一下几个项目:
第一个项目是自己写的,类似于@Value注解。