简述
当我在工具类中使用static修饰我要自动注入的类的时候,发现使用的时候会报空指针,为了解决这个问题,让工具类更完美,为了简单性,易用性,最好和 @Autowired 和 @Value 使用方式一致,我自定义的注解是 @StaticAutowired,@StaticValue 分别对标上面两个注解,实现了 @Autowired 和 @Value 的所有功能,外加支持自动注入静态属性
报错原因
@Autowired 实现原理
AutoWired实现依赖于他自己的后置处理器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的实现原理
org.springframework.beans.factory.annotation.QualifierAnnotationAutowireCandidateResolver#findValue
在这个方法中去对@Value处理
找到我们探寻的地方之后开始构建我们自己的注解
@StaticAutowired,@StaticValue(构建思路抄Spring的然后改)
构建注解@StaticValue
```
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD})
@Documented
public @interface StaticValue {
/**
* 注入静态属性值
*/
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;
// 把数组改成了的那个元素
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中去掉了对静态属性的直接退出