Spring 自定義注解實現(xiàn)靜態(tài)注入(@StaticAutowired,@StaticValue)

簡述

當我在工具類中使用static修飾我要自動注入的類的時候,發(fā)現(xiàn)使用的時候會報空指針,為了解決這個問題,讓工具類更完美,為了簡單性,易用性,最好和 @Autowired 和 @Value 使用方式一致,我自定義的注解是 @StaticAutowired,@StaticValue 分別對標上面兩個注解,實現(xiàn)了 @Autowired 和 @Value 的所有功能,外加支持自動注入靜態(tài)屬性

報錯原因

@Autowired 實現(xiàn)原理

AutoWired實現(xiàn)依賴于他自己的后置處理器AutowiredAnnotationBeanPostProcessor,它的集成圖如下

@Autowired 的Bean 后置處理器自動注入Bean的處理在這里

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#populateBean

這populateBean中方法開始進入處理屬性值

點進去看具體方法

org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor#postProcessProperties

org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor#findAutowiringMetadata

org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor#buildAutowiringMetadata

找到罪魁禍首

@Value的實現(xiàn)原理

org.springframework.beans.factory.annotation.QualifierAnnotationAutowireCandidateResolver#findValue

在這個方法中去對@Value處理

找到我們探尋的地方之后開始構建我們自己的注解

@StaticAutowired,@StaticValue(構建思路抄Spring的然后改)

構建注解@StaticValue

```

@Retention(RetentionPolicy.RUNTIME)

@Target({ElementType.FIELD})

@Documented

public @interface StaticValue {

? ? /**

? ? * 注入靜態(tài)屬性值

? ? */

? ? String value();

}

構建@StaticValue解析類

主要學習了這個方法是如何處理的

```

public class ExContextAnnotationAutowireCandidateResolver extends ContextAnnotationAutowireCandidateResolver {

? ? private Class<? extends Annotation> valueAnnotationType = StaticValue.class;

? ? @Override

? ? protected Object findValue(Annotation[] annotationsToSearch) {

? ? ? ? // 父類 對 @Value 的 value 值解析出來

? ? ? ? Object value = super.findValue(annotationsToSearch);

? ? ? ? if(value!=null){

? ? ? ? ? ? return value;

? ? ? ? }

? ? ? ? //父類解析之后去看這個字段上時候有我們自己的注解,然后拿到這個注解再學習父類那樣去解析

? ? ? ? if (annotationsToSearch.length > 0) {

? ? ? ? ? ? AnnotationAttributes attr = AnnotatedElementUtils.getMergedAnnotationAttributes(AnnotatedElementUtils.forAnnotations(annotationsToSearch), this.valueAnnotationType);

? ? ? ? ? ? if (attr != null) {

? ? ? ? ? ? ? ? return this.extractValue(attr);

? ? ? ? ? ? }

? ? ? ? }

? ? ? ? return null;

? ? }

}

構建注解@StaticAutowired

```

@Retention(RetentionPolicy.RUNTIME)

@Target({ElementType.FIELD})

@Documented

public @interface StaticAutowired{

? ? /**

? ? * 是否必須有

? ? */

? ? boolean required() default true;

}

構建@StaticAutowired解析類

這塊的話主要是對AutowiredAnnotationBeanPostProcessor的一個學習然后好些方法都是從里面拿,主要思路就是從入口方法開始先拿,然后看入口方法里需要啥我們再拿一個,最后再是去修改

```

@Component

public class StaticAutowiredAnnotationBeanPostProcessor? implements SmartInstantiationAwareBeanPostProcessor, MergedBeanDefinitionPostProcessor, PriorityOrdered, BeanFactoryAware {

? ? protected final Log logger = LogFactory.getLog(this.getClass());

? ? /**

? ? * 支持的注解

? ? */

? ? private final Set<Class<? extends Annotation>> autowiredAnnotationTypes = new LinkedHashSet(4);

? ? private String requiredParameterName = "required";

? ? private boolean requiredParameterValue = true;

? ? private final ExContextAnnotationAutowireCandidateResolver

? ? ? ? ? ? exContextAnnotationAutowireCandidateResolver = new ExContextAnnotationAutowireCandidateResolver();

? ? @Nullable

? ? private DefaultListableBeanFactory beanFactory;

? ? private final Map<String, InjectionMetadata> injectionMetadataCache = new ConcurrentHashMap(256);

? ? public StaticAutowiredAnnotationBeanPostProcessor() {

? ? ? ? this.autowiredAnnotationTypes.add(StaticAutowired.class);

? ? ? ? this.autowiredAnnotationTypes.add(StaticValue.class);

? ? }

? ? @Override

? ? public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {

? ? ? ? InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);

? ? ? ? AutowireCandidateResolver autowireCandidateResolver = beanFactory.getAutowireCandidateResolver();

? ? ? ? // 為了 解析 @StaticValue 必須使用 自定義的 ExContextAnnotationAutowireCandidateResolver

? ? ? ? boolean isExContextAnnotationAutowireCandidateResolver = autowireCandidateResolver instanceof ExContextAnnotationAutowireCandidateResolver;

? ? ? ? try {

? ? ? ? ? ? if (!isExContextAnnotationAutowireCandidateResolver) {

? ? ? ? ? ? ? ? beanFactory.setAutowireCandidateResolver(exContextAnnotationAutowireCandidateResolver);

? ? ? ? ? ? }

? ? ? ? ? ? metadata.inject(bean, beanName, pvs);

? ? ? ? }

? ? ? ? catch (BeanCreationException ex) {

? ? ? ? ? ? throw ex;

? ? ? ? }

? ? ? ? catch (Throwable ex) {

? ? ? ? ? ? throw new BeanCreationException(beanName, "Injection of static autowired dependencies failed", ex);

? ? ? ? }finally {

? ? ? ? ? ? // 設置回原來的

? ? ? ? ? ? if (!isExContextAnnotationAutowireCandidateResolver) {

? ? ? ? ? ? ? ? beanFactory.setAutowireCandidateResolver(autowireCandidateResolver);

? ? ? ? ? ? }

? ? ? ? }

? ? ? ? return pvs;

? ? }

? ? private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs) {

? ? ? ? String cacheKey = StringUtils.hasLength(beanName) ? beanName : clazz.getName();

? ? ? ? InjectionMetadata metadata = (InjectionMetadata)this.injectionMetadataCache.get(cacheKey);

? ? ? ? if (InjectionMetadata.needsRefresh(metadata, clazz)) {

? ? ? ? ? ? synchronized(this.injectionMetadataCache) {

? ? ? ? ? ? ? ? metadata = (InjectionMetadata)this.injectionMetadataCache.get(cacheKey);

? ? ? ? ? ? ? ? if (InjectionMetadata.needsRefresh(metadata, clazz)) {

? ? ? ? ? ? ? ? ? ? if (metadata != null) {

? ? ? ? ? ? ? ? ? ? ? ? metadata.clear(pvs);

? ? ? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? ? ? metadata = this.buildAutowiringMetadata(clazz);

? ? ? ? ? ? ? ? ? ? this.injectionMetadataCache.put(cacheKey, metadata);

? ? ? ? ? ? ? ? }

? ? ? ? ? ? }

? ? ? ? }

? ? ? ? return metadata;

? ? }

? ? private InjectionMetadata buildAutowiringMetadata(Class<?> clazz) {

? ? ? ? List<InjectionMetadata.InjectedElement> elements = new ArrayList();

? ? ? ? Class targetClass = clazz;

? ? ? ? do {

? ? ? ? ? ? List<InjectionMetadata.InjectedElement> currElements = new ArrayList();

? ? ? ? ? ? ReflectionUtils.doWithLocalFields(targetClass, (field) -> {

? ? ? ? ? ? ? ? AnnotationAttributes ann = this.findAutowiredAnnotation(field);

? ? ? ? ? ? ? ? // 這里改動

? ? ? ? ? ? ? ? if (ann != null) {

? ? ? ? ? ? ? ? ? ? if (Modifier.isStatic(field.getModifiers())) {

? ? ? ? ? ? ? ? ? ? ? ? if (logger.isInfoEnabled()) {

? ? ? ? ? ? ? ? ? ? ? ? ? ? logger.info("StaticAutowired annotation is supported on static fields: " + field);

? ? ? ? ? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? ? ? // 這里也有改動讓其用我們自己的去處理

? ? ? ? ? ? ? ? ? ? boolean required = this.determineRequiredStatus(ann);

? ? ? ? ? ? ? ? ? ? currElements.add(new StaticAutowiredAnnotationBeanPostProcessor.AutowiredFieldElement(field, required));

? ? ? ? ? ? ? ? }

? ? ? ? ? ? });

? ? ? ? ? ? elements.addAll(0, currElements);

? ? ? ? ? ? targetClass = targetClass.getSuperclass();

? ? ? ? } while(targetClass != null && targetClass != Object.class);

? ? ? ? return new InjectionMetadata(clazz, elements);

? ? }

? ? protected boolean determineRequiredStatus(AnnotationAttributes ann) {

? ? ? ? return !ann.containsKey(this.requiredParameterName) || this.requiredParameterValue == ann.getBoolean(this.requiredParameterName);

? ? }

? ? @Nullable

? ? private AnnotationAttributes findAutowiredAnnotation(AccessibleObject ao) {

? ? ? ? if (ao.getAnnotations().length > 0) {

? ? ? ? ? ? Iterator var2 = this.autowiredAnnotationTypes.iterator();

? ? ? ? ? ? while(var2.hasNext()) {

? ? ? ? ? ? ? ? Class<? extends Annotation> type = (Class)var2.next();

? ? ? ? ? ? ? ? AnnotationAttributes attributes = AnnotatedElementUtils.getMergedAnnotationAttributes(ao, type);

? ? ? ? ? ? ? ? if (attributes != null) {

? ? ? ? ? ? ? ? ? ? return attributes;

? ? ? ? ? ? ? ? }

? ? ? ? ? ? }

? ? ? ? }

? ? ? ? return null;

? ? }

? ? @Nullable

? ? private Object resolvedCachedArgument(@Nullable String beanName, @Nullable Object cachedArgument) {

? ? ? ? if (cachedArgument instanceof DependencyDescriptor) {

? ? ? ? ? ? DependencyDescriptor descriptor = (DependencyDescriptor)cachedArgument;

? ? ? ? ? ? Assert.state(this.beanFactory != null, "No BeanFactory available");

? ? ? ? ? ? return this.beanFactory.resolveDependency(descriptor, beanName, (Set)null, (TypeConverter)null);

? ? ? ? } else {

? ? ? ? ? ? return cachedArgument;

? ? ? ? }

? ? }

? ? private void registerDependentBeans(@Nullable String beanName, Set<String> autowiredBeanNames) {

? ? ? ? if (beanName != null) {

? ? ? ? ? ? Iterator var3 = autowiredBeanNames.iterator();

? ? ? ? ? ? while(var3.hasNext()) {

? ? ? ? ? ? ? ? String autowiredBeanName = (String)var3.next();

? ? ? ? ? ? ? ? if (this.beanFactory != null && this.beanFactory.containsBean(autowiredBeanName)) {

? ? ? ? ? ? ? ? ? ? this.beanFactory.registerDependentBean(autowiredBeanName, beanName);

? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? if (this.logger.isDebugEnabled()) {

? ? ? ? ? ? ? ? ? ? this.logger.debug("Autowiring by type from bean name '" + beanName + "' to bean named '" + autowiredBeanName + "'");

? ? ? ? ? ? ? ? }

? ? ? ? ? ? }

? ? ? ? }

? ? }

? ? @Override

? ? public void setBeanFactory(BeanFactory beanFactory) throws BeansException {

? ? ? ? if (!(beanFactory instanceof DefaultListableBeanFactory)) {

? ? ? ? ? ? throw new IllegalArgumentException("StaticAutowiredAnnotationBeanPostProcessor requires a DefaultListableBeanFactory: " + beanFactory);

? ? ? ? } else {

? ? ? ? ? ? this.beanFactory = (DefaultListableBeanFactory) beanFactory;

? ? ? ? }

? ? }

? ? @Override

? ? public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {

? ? ? ? InjectionMetadata metadata = this.findAutowiringMetadata(beanName, beanType, (PropertyValues)null);

? ? ? ? metadata.checkConfigMembers(beanDefinition);

? ? }

? ? @Override

? ? public int getOrder() {

? ? ? ? return Ordered.LOWEST_PRECEDENCE - 2;

? ? }

? ? private static class ShortcutDependencyDescriptor extends DependencyDescriptor {

? ? ? ? private final String shortcut;

? ? ? ? private final Class<?> requiredType;

? ? ? ? public ShortcutDependencyDescriptor(DependencyDescriptor original, String shortcut, Class<?> requiredType) {

? ? ? ? ? ? super(original);

? ? ? ? ? ? this.shortcut = shortcut;

? ? ? ? ? ? this.requiredType = requiredType;

? ? ? ? }

? ? ? ? @Override

? ? ? ? public Object resolveShortcut(BeanFactory beanFactory) {

? ? ? ? ? ? return beanFactory.getBean(this.shortcut, this.requiredType);

? ? ? ? }

? ? }

? ? 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, (PropertyDescriptor)null);

? ? ? ? ? ? this.required = required;

? ? ? ? }

? ? ? ? @Override

? ? ? ? protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {

? ? ? ? ? ? Field field = (Field)this.member;

? ? ? ? ? ? // 把數(shù)組改成了的那個元素

? ? ? ? ? ? Object value;

? ? ? ? ? ? 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 var12) {

? ? ? ? ? ? ? ? ? ? throw new UnsatisfiedDependencyException((String)null, beanName, new InjectionPoint(field), var12);

? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? synchronized(this) {

? ? ? ? ? ? ? ? ? ? if (!this.cached) {

? ? ? ? ? ? ? ? ? ? ? ? if (value == null && !this.required) {

? ? ? ? ? ? ? ? ? ? ? ? ? ? this.cachedFieldValue = null;

? ? ? ? ? ? ? ? ? ? ? ? } else {

? ? ? ? ? ? ? ? ? ? ? ? ? ? this.cachedFieldValue = desc;

? ? ? ? ? ? ? ? ? ? ? ? ? ? registerDependentBeans(beanName, autowiredBeanNames);

? ? ? ? ? ? ? ? ? ? ? ? ? ? if (autowiredBeanNames.size() == 1) {

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? String autowiredBeanName = (String)autowiredBeanNames.iterator().next();

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? if (beanFactory.containsBean(autowiredBeanName) && beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? this.cachedFieldValue = new StaticAutowiredAnnotationBeanPostProcessor.ShortcutDependencyDescriptor(desc, autowiredBeanName, field.getType());

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? ? ? ? ? this.cached = true;

? ? ? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? }

? ? ? ? ? ? }

? ? ? ? ? ? if (value != null) {

? ? ? ? ? ? ? ? ReflectionUtils.makeAccessible(field);

? ? ? ? ? ? ? ? field.set(bean, value);

? ? ? ? ? ? }

? ? ? ? }

? ? }

}

總結

從解析的入口方法開始,從AutowiredAnnotationBeanPostProcessor缺啥拿啥

buildAutowiringMetadata中去掉了對靜態(tài)屬性的直接退出

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

  • 什么是循環(huán)依賴? 循環(huán)依賴:在依賴注入的過程中,多個Bean對象互相持有對方的引用,比如A對象中包含B對象,B對象...
    Java弟中弟閱讀 749評論 0 1
  • Spring Bean生命周期 1.BeanDefinition Spring中對象皆為bean,進而將bean的...
    Johar77閱讀 634評論 0 0
  • 【Spring源碼】- 05 擴展點之BeanPostProcessor 原創(chuàng)張張Reactor2020昨天 原文...
    ska2620閱讀 558評論 0 0
  • 結合源碼分析 Spring 容器與 SpringMVC 容器之間的關系 問題 問題描述:項目中發(fā)現(xiàn),自定義切面注解...
    java菜閱讀 205評論 0 0
  • 16宿命:用概率思維提高你的勝算 以前的我是風險厭惡者,不喜歡去冒險,但是人生放棄了冒險,也就放棄了無數(shù)的可能。 ...
    yichen大刀閱讀 8,165評論 0 4

友情鏈接更多精彩內容