本文引自我的个人博客: sunmingshuai.coding.me
spring
框架提供的注解
方式的注入 大大方便了程序员的编程 但从另外一个方面来看 spring
把功能细节隐藏的更深了 对技术有点追求的人 一定会很好奇spring注解的工作的方式 这篇博客以讲解@Value``@Autowired``@Qualifier
注解为例来讲解注解是怎么工作的 (其他注解如@Resource
@Required
注解的工作原理类似)
component-scan做了些什么:源码解读这篇博客的最后有介绍到 注册了一些注解处理器BPP
我们再看下这个方法
public static Set registerAnnotationConfigProcessors(
BeanDefinitionRegistry registry, Object source) {
Set beanDefs = new LinkedHashSet(4);
// @Configuration
if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
}
//@Autowired @Value
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));
}
//@Required
if (!registry.containsBeanDefinition(REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(RequiredAnnotationBeanPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
}
//@PostConsruct @Resouce 等java注解
// Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor.
if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
}
//
// Check for JPA support, and if present add the PersistenceAnnotationBeanPostProcessor.
if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition();
try {
def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME,
AnnotationConfigUtils.class.getClassLoader()));
}
catch (ClassNotFoundException ex) {
throw new IllegalStateException(
"Cannot load optional framework class: " + PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, ex);
}
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME));
}
return beanDefs;
}
注解以及对应的后置处理器如下表所示
注解 | BPP |
---|---|
@Configuration | ConfigurationClassPostProcessor |
@Autowired(@Qualifier),@Value,@Inject | AutowiredAnnotationBeanPostProcessor |
@Required | RequiredAnnotationBeanPostProcessor |
@Postconstruct,PreDestroy,@Resource | CommonAnnotationBeanPostProcessor |
@Persistence | PersistenceAnnotationBeanPostProcessor |
我们看下AutowiredAnnotationBeanPostProcessor
这个处理器 @Autowired``@Qualifier``@Value
注解的解析就是在postProcessMergedBeanDefinition
以及postProcessPropertyValues
这两个方法中完成的
postProcessMergedBeanDefinition
这个方法执行时间的节点是在创建bean
的实例后 在populateBean()
方法调用前调用的
这个方法主要完成的功能就是找出带有特定注解的field
method
并记录在数据结构中
// 执行的时间节点是bean刚刚初始化完 但在属性填充之前
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class> beanType, String beanName) {
if (beanType != null) {
//找出所有的字段或者方法上的@Autowired @Value @Inject注解 并保存
InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
//加入到BeanDefinition
metadata.checkConfigMembers(beanDefinition);
}
}
最后会调用buildAutowiringMetadata(clazz)
完成检查
/**
* 分别对field method做检查 是否存在相应注解
*
* @param clazz
* @return
*/
private InjectionMetadata buildAutowiringMetadata(Class> clazz) {
LinkedList elements = new LinkedList();
Class> targetClass = clazz;
do {
LinkedList currElements = new LinkedList();
// 循环所有的field
for (Field field : targetClass.getDeclaredFields()) {
// 寻找@Autowired @Value @Inject注解 只处理一个
Annotation ann = findAutowiredAnnotation(field);
if (ann != null) {
//忽略静态属性的注入
if (Modifier.isStatic(field.getModifiers())) {
if (logger.isWarnEnabled()) {
logger.warn("Autowired annotation is not supported on static fields: " + field);
}
continue;
}
boolean required = determineRequiredStatus(ann);
currElements.add(new AutowiredFieldElement(field, required));
}
}
// 循环所有的方法 比如setxxx方法注入
for (Method method : targetClass.getDeclaredMethods()) {
Annotation ann = null;
Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
if (BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
ann = findAutowiredAnnotation(bridgedMethod);
}
if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
if (Modifier.isStatic(method.getModifiers())) {
if (logger.isWarnEnabled()) {
logger.warn("Autowired annotation is not supported on static methods: " + method);
}
continue;
}
if (method.getParameterTypes().length == 0) {
if (logger.isWarnEnabled()) {
logger.warn("Autowired annotation should be used on methods with actual 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 new InjectionMetadata(clazz, elements);
}
特定注解指的就是@Autowired
@Value
@Inject(较少用)
@Qualifier
注解是跟@Autowired
注解搭配使用的 单独使用是不起作用的
特定的数据结构指的就是InjectionMetadata 博主前面说过 阅读源代码千万不要对这样的代码感到畏惧 就把他当成一个包装类或者工具类就可以了 为了完成或者包装某些功能写出的一些类而已
再具体的代码就不带着一起看了 相信读者阅读这样的代码应该没有任何问题
我们接着看下另外一个方法postProcessPropertyValues(xxx)
这个方法的执行的时间节点是在populateBean(xxx)
之后
@Override
public PropertyValues postProcessPropertyValues(
PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
//从缓存中读取出
InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
try {
//注入
metadata.inject(bean, beanName, pvs);
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex);
}
return pvs;
}
在postProcessMergedBeanDefinition(xxx)
方法中把循环检查出的特定注解修饰的field``method
以特定的数据结构以beanName
为key保存在了一个map中 在postProcessPropertyValues(xxx)
方法中取出来处理
这里我们以field
注入讲解 进入方法AutowiredFieldElement#inject(xxx)
@Override
protected void inject(Object bean, String beanName, PropertyValues pvs) throws Throwable {
Field field = (Field) this.member;
try {
Object value;
if (this.cached) {
value = resolvedCachedArgument(beanName, this.cachedFieldValue);
}
else {
DependencyDescriptor desc = new DependencyDescriptor(field, this.required);
Set autowiredBeanNames = new LinkedHashSet(1);
TypeConverter typeConverter = beanFactory.getTypeConverter();
value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
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)) {
if (beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {
this.cachedFieldValue = new RuntimeBeanReference(autowiredBeanName);
}
}
}
}
else {
this.cachedFieldValue = null;
}
this.cached = true;
}
}
}
// 通过反射设置值
if (value != null) {
ReflectionUtils.makeAccessible(field);
field.set(bean, value);
}
}
catch (Throwable ex) {
throw new BeanCreationException("Could not autowire field: " + field, ex);
}
}
这里 DependencyDescriptor
同样是为了方便操作 对field
进行的包装
beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter)
方法完成解析 最后会调用doResolveDependency(xxx)
方法
protected Object doResolveDependency(DependencyDescriptor descriptor, Class> type, String beanName,
Set<String> autowiredBeanNames, TypeConverter typeConverter) throws BeansException {
//处理@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());
return (descriptor.getField() != null ?
converter.convertIfNecessary(value, type, descriptor.getField()) :
converter.convertIfNecessary(value, type, descriptor.getMethodParameter()));
}
//处理@Autowired注解
if (type.isArray()) {
Class> componentType = type.getComponentType();
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, componentType, descriptor);
if (matchingBeans.isEmpty()) {
if (descriptor.isRequired()) {
raiseNoSuchBeanDefinitionException(componentType, "array of " + componentType.getName(), descriptor);
}
return null;
}
if (autowiredBeanNames != null) {
autowiredBeanNames.addAll(matchingBeans.keySet());
}
TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
return converter.convertIfNecessary(matchingBeans.values(), type);
}
else if (Collection.class.isAssignableFrom(type) && type.isInterface()) {
Class> elementType = descriptor.getCollectionType();
if (elementType == null) {
if (descriptor.isRequired()) {
throw new FatalBeanException("No element type declared for collection [" + type.getName() + "]");
}
return null;
}
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, elementType, descriptor);
if (matchingBeans.isEmpty()) {
if (descriptor.isRequired()) {
raiseNoSuchBeanDefinitionException(elementType, "collection of " + elementType.getName(), descriptor);
}
return null;
}
if (autowiredBeanNames != null) {
autowiredBeanNames.addAll(matchingBeans.keySet());
}
TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
return converter.convertIfNecessary(matchingBeans.values(), type);
}
else if (Map.class.isAssignableFrom(type) && type.isInterface()) {
Class> keyType = descriptor.getMapKeyType();
if (keyType == null || !String.class.isAssignableFrom(keyType)) {
if (descriptor.isRequired()) {
throw new FatalBeanException("Key type [" + keyType + "] of map [" + type.getName() +
"] must be assignable to [java.lang.String]");
}
return null;
}
Class> valueType = descriptor.getMapValueType();
if (valueType == null) {
if (descriptor.isRequired()) {
throw new FatalBeanException("No value type declared for map [" + type.getName() + "]");
}
return null;
}
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, valueType, descriptor);
if (matchingBeans.isEmpty()) {
if (descriptor.isRequired()) {
raiseNoSuchBeanDefinitionException(valueType, "map with value type " + valueType.getName(), descriptor);
}
return null;
}
if (autowiredBeanNames != null) {
autowiredBeanNames.addAll(matchingBeans.keySet());
}
return matchingBeans;
}
else {
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
if (matchingBeans.isEmpty()) {
if (descriptor.isRequired()) {
raiseNoSuchBeanDefinitionException(type, "", descriptor);
}
return null;
}
if (matchingBeans.size() > 1) {
String primaryBeanName = determinePrimaryCandidate(matchingBeans, descriptor);
if (primaryBeanName == null) {
throw new NoUniqueBeanDefinitionException(type, matchingBeans.keySet());
}
if (autowiredBeanNames != null) {
autowiredBeanNames.add(primaryBeanName);
}
return matchingBeans.get(primaryBeanName);
}
// We have exactly one match.
Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
if (autowiredBeanNames != null) {
autowiredBeanNames.add(entry.getKey());
}
return entry.getValue();
}
}
我们先看对@Value
注解的解析
@Value
注解有两种使用方法 除了可以直接指出我们想要的值外 还可以
@Value("${xxx}")
这个功能在
spring3.x
以后才能使用 3.x以前的版本取出来的就是${xxx}
而不会再被解析 其背后的原因就是3.x以后的代码 通过PropertyPlaceholderConfigurer向beanFactory
加入了一个处理器 PropertyPlaceholderConfigurer源码解析 这篇文章的最后又指出
getAutowireCandidateResolver()
这个方法返回的是在初始化beanFactory
的过程中加入的QualifierAnnotationAutowireCandidateResolver
类
protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) {
if (this.allowBeanDefinitionOverriding != null) {
beanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
}
if (this.allowCircularReferences != null) {
beanFactory.setAllowCircularReferences(this.allowCircularReferences);
}
//设置Qualifier注解解析类
beanFactory.setAutowireCandidateResolver(new QualifierAnnotationAutowireCandidateResolver());
}
QualifierAnnotationAutowireCandidateResolver#getSuggestedValue(xxx)
public Object getSuggestedValue(DependencyDescriptor descriptor) {
Object value = findValue(descriptor.getAnnotations());
if (value == null) {
MethodParameter methodParam = descriptor.getMethodParameter();
if (methodParam != null) {
value = findValue(methodParam.getMethodAnnotations());
}
}
return value;
}
如果有@Value
注解的话 返回设置的value
值 如果没有就返回null
如果返回的value
不为null的话 就需要进一步处理这个原始值 因为这个值可能不是我们最终想要的 例如我们前面讲到的@Value("${xxx}")
这个时候返回的就是${xxx}
显然不是我们想要的 当然spring还提供了处理表达式的支持 这里不再讲解
最后再通过converter处理一遍返回
如果返回的是null 说明没有@Value
注解 spring
增加了对array
collection
map
注入的支持 有兴趣的可以看看 我们就选一个最简单最基础的注入为例来讲解 @Autowired
的工作原理 也就是最后一个else
分支
{
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
if (matchingBeans.isEmpty()) {
if (descriptor.isRequired()) {
raiseNoSuchBeanDefinitionException(type, "", descriptor);
}
return null;
}
if (matchingBeans.size() > 1) {
String primaryBeanName = determinePrimaryCandidate(matchingBeans, descriptor);
if (primaryBeanName == null) {
throw new NoUniqueBeanDefinitionException(type, matchingBeans.keySet());
}
if (autowiredBeanNames != null) {
autowiredBeanNames.add(primaryBeanName);
}
return matchingBeans.get(primaryBeanName);
}
// We have exactly one match.
Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
if (autowiredBeanNames != null) {
autowiredBeanNames.add(entry.getKey());
}
return entry.getValue();
}
进入findAutowireCandidates(xxx)
方法
protected Map<String, Object> findAutowireCandidates(
String beanName, Class> requiredType, DependencyDescriptor descriptor) {
String[] candidateNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this, requiredType, true, descriptor.isEager());
Map<String, Object> result = new LinkedHashMap<String, Object>(candidateNames.length);
for (Class> autowiringType : this.resolvableDependencies.keySet()) {
if (autowiringType.isAssignableFrom(requiredType)) {
Object autowiringValue = this.resolvableDependencies.get(autowiringType);
autowiringValue = AutowireUtils.resolveAutowiringValue(autowiringValue, requiredType);
if (requiredType.isInstance(autowiringValue)) {
result.put(ObjectUtils.identityToString(autowiringValue), autowiringValue);
break;
}
}
}
for (String candidateName : candidateNames) {
if (!candidateName.equals(beanName) && isAutowireCandidate(candidateName, descriptor)) {
result.put(candidateName, getBean(candidateName));
}
}
return result;
}
首先从beanFactory
中取出所有符合requiredType
类型的bean
的名称 requiredType
是要被注入的字段的类型(其实这一步就已经完成了@Autowired注解的功能) 然后循环判断这些bean
中有哪些是符合条件的 哪些是不符合条件的(想一想为什么还要继续判断?)
public boolean isAutowireCandidate(String beanName, DependencyDescriptor descriptor)
throws NoSuchBeanDefinitionException {
// Consider FactoryBeans as autowiring candidates.
boolean isFactoryBean = (descriptor != null && descriptor.getDependencyType() != null &&
FactoryBean.class.isAssignableFrom(descriptor.getDependencyType()));
if (isFactoryBean) {
beanName = BeanFactoryUtils.transformedBeanName(beanName);
}
if (containsBeanDefinition(beanName)) {
return isAutowireCandidate(beanName, getMergedLocalBeanDefinition(beanName), descriptor);
}
else if (containsSingleton(beanName)) {
return isAutowireCandidate(beanName, new RootBeanDefinition(getType(beanName)), descriptor);
}
else if (getParentBeanFactory() instanceof ConfigurableListableBeanFactory) {
// No bean definition found in this factory -> delegate to parent.
return ((ConfigurableListableBeanFactory) getParentBeanFactory()).isAutowireCandidate(beanName, descriptor);
}
else {
return true;
}
}
这个方法里面是考虑是很多中情况了 比如是不是factoryBean
等 这里我们还是以最简单的情况分析
最后会进入方法QualifierAnnotationAutowireCandidateResolver#isAutowireCandidate(xxx)
方法
public boolean isAutowireCandidate(BeanDefinitionHolder bdHolder, DependencyDescriptor descriptor) {
if (!bdHolder.getBeanDefinition().isAutowireCandidate()) {
// 如果已经设置了非候选类 直接返回
return false;
}
if (descriptor == null) {
// no qualification necessary
return true;
}
boolean match = checkQualifiers(bdHolder, descriptor.getAnnotations());
if (match) {
MethodParameter methodParam = descriptor.getMethodParameter();
if (methodParam != null) {
Method method = methodParam.getMethod();
if (method == null || void.class.equals(method.getReturnType())) {
match = checkQualifiers(bdHolder, methodParam.getMethodAnnotations());
}
}
}
return match;
}
对于@Autowired
注解 是按类型匹配的 前面已经筛选出了beanFactory
中所有的符合条件的类型 这里为什么还要继续筛选呢 原因就是可能还会有@Qualifier
注解
protected boolean checkQualifiers(BeanDefinitionHolder bdHolder, Annotation[] annotationsToSearch) {
if (ObjectUtils.isEmpty(annotationsToSearch)) {
return true;
}
SimpleTypeConverter typeConverter = new SimpleTypeConverter();
for (Annotation annotation : annotationsToSearch) {
Class extends Annotation> type = annotation.annotationType();
boolean checkMeta = true;
boolean fallbackToMeta = false;
if (isQualifier(type)) {
if (!checkQualifier(bdHolder, annotation, typeConverter)) {
fallbackToMeta = true;
}
else {
checkMeta = false;
}
}
if (checkMeta) {
boolean foundMeta = false;
for (Annotation metaAnn : type.getAnnotations()) {
Class extends Annotation> metaType = metaAnn.annotationType();
if (isQualifier(metaType)) {
foundMeta = true;
// Only accept fallback match if @Qualifier annotation has a value...
// Otherwise it is just a marker for a custom qualifier annotation.
if ((fallbackToMeta && StringUtils.isEmpty(AnnotationUtils.getValue(metaAnn))) ||
!checkQualifier(bdHolder, metaAnn, typeConverter)) {
return false;
}
}
}
if (fallbackToMeta && !foundMeta) {
return false;
}
}
}
return true;
}
这个方法做的工作就是检查有没有@Qualifier
注解 如果有的话 再检查是不是符合条件
例如虽然有多个候选的符合条件的类型 但是@Qualifier
指出了特定的名称 这样就实现了按照名称的匹配
最后返回通过最终筛选的bean