日常开发中,@Autowired注解我们经常在使用,也会配合其他的注解一起(@Qualifier、@Primary、@lazy)等。
还有就是它跟@Resource的区别在哪里?一定要看到最后!!!
那么它的一个处理流程是怎样的呢?继续看,希望给大家带来对@Autowired注解使用上的一些帮助!
按照一贯的风格,首先给大家一个整体的流程图解
这里我挑出了8个重要的节点,入口类是AutowiredAnnotationBeanPostProcessor,关于这个类使用场景《springboot ApplicationContext之finishBeanFactoryInitialization(getBean())下》
接下来我们对各个节点进行一个解释
- findAutowiringMetadata,这个方法主要是对类进行一个扫描,对字段或者方法存在@Autowired注解进行存储,元素分别对应AutowiredFieldElement、AutowiredMethodElement,扫描的条件,这里列出下关键代码,会忽略带static的字段或方法
//处理字段
ReflectionUtils.doWithLocalFields(targetClass, field -> {
MergedAnnotation<?> ann = findAutowiredAnnotation(field);
if (ann != null) {
//如果是static跳过
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))) {
//如果是static跳过
if (Modifier.isStatic(method.getModifiers())) {
if (logger.isInfoEnabled()) {
logger.info("Autowired annotation is not supported on static methods: " + method);
}
return;
}
//如果参数的个数是0 跳过
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));
}
});
- inject,这个就是开始注入的一个动作,分别调用AutowiredFieldElement、AutowiredMethodElement 的inject方法
- resolveDependency,开始进入具体的处理类DefaultListableBeanFactory,这里会对一些具体的类型分别处理,按照顺序依次是:Optional、ObjectFactory || ObjectProvider、带有@lazy注解
public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
//Optional 处理
if (Optional.class == descriptor.getDependencyType()) {
//这里会直接走第4个步骤,并把结果存储在Optional中
return createOptionalDependency(descriptor, requestingBeanName);
}
else if (ObjectFactory.class == descriptor.getDependencyType() ||
ObjectProvider.class == descriptor.getDependencyType()) {
//返回的类型是包装类型DependencyObjectProvider,在实际调用中获取bean,延迟加载的另外一种处理
return new DependencyObjectProvider(descriptor, requestingBeanName);
}
else if (javaxInjectProviderClass == descriptor.getDependencyType()) {
return new Jsr330Factory().createDependencyProvider(descriptor, requestingBeanName);
}
else {
// @lazy处理,如果返回代理对象就结束流程
Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
descriptor, requestingBeanName);
// 一般的类型,继续
if (result == null) {
result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
}
return result;
}
}
- doResolveDependency,这里是对一般类型字段或方法进行处理,分三步:处理@value注解、处理类型是Array、Collection、Map(这里实际上会调用后面5步骤,获取满足条件的类型,然后根据不同的类型进行组装)、普通类型
@Nullable
// 步骤都是一致的,先调用findAutowireCandidates获取满足条件的类型,按照返回类型进行组装进行返回
private Object resolveMultipleBeans(DependencyDescriptor descriptor, @Nullable String beanName,
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) {
Class<?> type = descriptor.getDependencyType();
if (descriptor instanceof StreamDependencyDescriptor) {
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
if (autowiredBeanNames != null) {
autowiredBeanNames.addAll(matchingBeans.keySet());
}
Stream<Object> stream = matchingBeans.keySet().stream()
.map(name -> descriptor.resolveCandidate(name, type, this))
.filter(bean -> !(bean instanceof NullBean));
if (((StreamDependencyDescriptor) descriptor).isOrdered()) {
stream = stream.sorted(adaptOrderComparator(matchingBeans));
}
return stream;
}
else if (type.isArray()) {
...
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, componentType,
new MultiElementDescriptor(descriptor));
if (matchingBeans.isEmpty()) {
return null;
}
if (autowiredBeanNames != null) {
autowiredBeanNames.addAll(matchingBeans.keySet());
}
TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
Object result = converter.convertIfNecessary(matchingBeans.values(), resolvedArrayType);
if (result instanceof Object[]) {
Comparator<Object> comparator = adaptDependencyComparator(matchingBeans);
if (comparator != null) {
Arrays.sort((Object[]) result, comparator);
}
}
return result;
}
else if (Collection.class.isAssignableFrom(type) && type.isInterface()) {
...
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, elementType,
new MultiElementDescriptor(descriptor));
if (matchingBeans.isEmpty()) {
return null;
}
if (autowiredBeanNames != null) {
autowiredBeanNames.addAll(matchingBeans.keySet());
}
TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
Object result = converter.convertIfNecessary(matchingBeans.values(), type);
if (result instanceof List) {
if (((List<?>) result).size() > 1) {
Comparator<Object> comparator = adaptDependencyComparator(matchingBeans);
if (comparator != null) {
((List<?>) result).sort(comparator);
}
}
}
return result;
}
else if (Map.class == type) {
....
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, valueType,
new MultiElementDescriptor(descriptor));
if (matchingBeans.isEmpty()) {
return null;
}
if (autowiredBeanNames != null) {
autowiredBeanNames.addAll(matchingBeans.keySet());
}
return matchingBeans;
}
else {
return null;
}
}
- findAutowireCandidates,按照类型查找对应的bean类型,这里只是类型、类型、类型,不是具体的对象
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
if (matchingBeans.isEmpty()) {
// require字段的作用,如果找到,require=false,不报错
if (isRequired(descriptor)) {
raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
}
return null;
}
protected Map<String, Object> findAutowireCandidates(
@Nullable String beanName, Class<?> requiredType, DependencyDescriptor descriptor) {
// 按照类型去容器中查询
String[] candidateNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this, requiredType, true, descriptor.isEager());
Map<String, Object> result = new LinkedHashMap<>(candidateNames.length);
// 匹配spring一些已经注册的类
for (Map.Entry<Class<?>, Object> classObjectEntry : this.resolvableDependencies.entrySet()) {
Class<?> autowiringType = classObjectEntry.getKey();
if (autowiringType.isAssignableFrom(requiredType)) {
Object autowiringValue = classObjectEntry.getValue();
autowiringValue = AutowireUtils.resolveAutowiringValue(autowiringValue, requiredType);
if (requiredType.isInstance(autowiringValue)) {
result.put(ObjectUtils.identityToString(autowiringValue), autowiringValue);
break;
}
}
}
for (String candidate : candidateNames) {
if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, descriptor)) {
addCandidateEntry(result, candidate, descriptor, requiredType);
}
}
// 如果是空的一些另外处理
if (result.isEmpty()) {
boolean multiple = indicatesMultipleBeans(requiredType);
// Consider fallback matches if the first pass failed to find anything...
DependencyDescriptor fallbackDescriptor = descriptor.forFallbackMatch();
for (String candidate : candidateNames) {
//isAutowireCandidate 这个方法会处理Qualifier注解,如果带有Qualifier,就按照名字去匹配
if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, fallbackDescriptor) &&
(!multiple || getAutowireCandidateResolver().hasQualifier(descriptor))) {
addCandidateEntry(result, candidate, descriptor, requiredType);
}
}
if (result.isEmpty() && !multiple) {
// Consider self references as a final pass...
// but in the case of a dependency collection, not the very same bean itself.
for (String candidate : candidateNames) {
if (isSelfReference(beanName, candidate) &&
(!(descriptor instanceof MultiElementDescriptor) || !beanName.equals(candidate)) &&
isAutowireCandidate(candidate, fallbackDescriptor)) {
addCandidateEntry(result, candidate, descriptor, requiredType);
}
}
}
}
return result;
}
- determineAutowireCandidate,这个方法只会在找到多个满足条件的时候调用,如果待选的类型包含**@Primary**注解,就使用它,否则报错,因为spring不知道你要用哪个了
- resolveCandidate,这个方法就是按照名称继续bean流程获取
public Object resolveCandidate(String beanName, Class<?> requiredType, BeanFactory beanFactory)
throws BeansException {
return beanFactory.getBean(beanName);
}
- 反射注入属性,这个就不解释了
流程到这里就结束,当然忽略了一些非本文注重的内容例如(java的@inject注解),我想大家应该会有点对这个注解的理解提升吧!
接下来,看看具体的实例,对应的流程的步骤,都举了个例
@Service
public class TestA{
//1
@Autowired
private Optional<OptionalInstance> optionalInstance;
//2
@Autowired
ObjectFactory<ObjectFactoryInstance> objectFactoryInstance;
//3
@Autowired
ObjectProvider<ObjectProviderTest.ObjectProviderInstance> objectProviderInstances;
//4
@Autowired
@Lazy
private LazyTest lazyTest;
//5方法注入,对@value的处理
@Autowired
private void valueTest(@Value("${spring.application.name}")String name){
}
@Autowired
private TestB testB;
private TestC testC;
//方法注入
@Autowired
public void setP(TestC testC){
this.testC =testC;
}
// TestD是个接口,多个类实现
@Autowired
private List<TestD> testDS;
// TestE是个接口,多个类实现
@Autowired
@Qualifier(value = "testE1") 会注入名称为testE1的类,没有这个注解就报错拉。。。
private TestE testE;
// TestE是个接口,多个类实现,这样应该是会报错的但是我在其中的一个类上加了@Primary注解
@Autowired
private TestF testF;
public void sayObjectFactory(){
System.out.println(this.objectFactoryInstance.getObject());
System.out.println(optionalInstance.isPresent());
System.out.println(lazyTest);
}
public void sayObjectProvider(){
System.out.println(this.objectProviderInstances.getIfUnique());
System.out.println(objectProviderInstances.getIfAvailable());
System.out.println(objectProviderInstances.getObject());
}
}
在对代码中的ObjectFactory、ObjectProvider进行下说明吧,它的重要类似@lazy,在使用的时候再进行bean的获取,ObjectFactory还记得它吗?我们在循环依赖中,放入二级缓存的东西《springboot ApplicationContext之finishBeanFactoryInitialization(getBean())上》,ObjectProvider是它的之类扩展了一些方法getIfUnique、getIfAvailable、stream相关等,主要扩展的是,默认require =false,也就是说,如果不存在在启动的时候不会报错,使用的时候会报错
private class DependencyObjectProvider implements BeanObjectProvider<Object> {
private final DependencyDescriptor descriptor;
private final boolean optional;
@Nullable
private final String beanName;
public DependencyObjectProvider(DependencyDescriptor descriptor, @Nullable String beanName) {
this.descriptor = new NestedDependencyDescriptor(descriptor);
this.optional = (this.descriptor.getDependencyType() == Optional.class);
this.beanName = beanName;
}
@Override
public Object getObject() throws BeansException {
if (this.optional) {
return createOptionalDependency(this.descriptor, this.beanName);
}
else {
Object result = doResolveDependency(this.descriptor, this.beanName, null, null);
if (result == null) {
throw new NoSuchBeanDefinitionException(this.descriptor.getResolvableType());
}
return result;
}
}
@Override
public Object getObject(final Object... args) throws BeansException {
if (this.optional) {
return createOptionalDependency(this.descriptor, this.beanName, args);
}
else {
DependencyDescriptor descriptorToUse = new DependencyDescriptor(this.descriptor) {
@Override
public Object resolveCandidate(String beanName, Class<?> requiredType, BeanFactory beanFactory) {
return beanFactory.getBean(beanName, args);
}
};
Object result = doResolveDependency(descriptorToUse, this.beanName, null, null);
if (result == null) {
throw new NoSuchBeanDefinitionException(this.descriptor.getResolvableType());
}
return result;
}
}
@Override
@Nullable
public Object getIfAvailable() throws BeansException {
if (this.optional) {
return createOptionalDependency(this.descriptor, this.beanName);
}
else {
DependencyDescriptor descriptorToUse = new DependencyDescriptor(this.descriptor) {
// 可以允许不存在
@Override
public boolean isRequired() {
return false;
}
};
return doResolveDependency(descriptorToUse, this.beanName, null, null);
}
}
@Override
@Nullable
public Object getIfUnique() throws BeansException {
DependencyDescriptor descriptorToUse = new DependencyDescriptor(this.descriptor) {
// 可以允许不存在
@Override
public boolean isRequired() {
return false;
}
@Override
@Nullable
public Object resolveNotUnique(ResolvableType type, Map<String, Object> matchingBeans) {
return null;
}
};
if (this.optional) {
return createOptionalDependency(descriptorToUse, this.beanName);
}
else {
return doResolveDependency(descriptorToUse, this.beanName, null, null);
}
}
@Nullable
protected Object getValue() throws BeansException {
if (this.optional) {
return createOptionalDependency(this.descriptor, this.beanName);
}
else {
return doResolveDependency(this.descriptor, this.beanName, null, null);
}
}
@Override
public Stream<Object> stream() {
return resolveStream(false);
}
@Override
public Stream<Object> orderedStream() {
return resolveStream(true);
}
@SuppressWarnings("unchecked")
private Stream<Object> resolveStream(boolean ordered) {
DependencyDescriptor descriptorToUse = new StreamDependencyDescriptor(this.descriptor, ordered);
Object result = doResolveDependency(descriptorToUse, this.beanName, null, null);
return (result instanceof Stream ? (Stream<Object>) result : Stream.of(result));
}
}
接下来我们来聊聊@Autowired、@resource的区别在哪里,看到流程图中的那个箭头了吗!!!
就是inject方法再调用具体的类型的inject方法是多了个判断,@resource注解的作用类是CommonAnnotationBeanPostProcessor,她调用findResourceMetadata返回的对象是ResourceElement,我们看下该类的inject方法(实际调用的父类InjectionMetadata.InjectedElement)
protected void inject(Object target, @Nullable String requestingBeanName, @Nullable PropertyValues pvs)
throws Throwable {
if (this.isField) {
Field field = (Field) this.member;
ReflectionUtils.makeAccessible(field);
field.set(target, getResourceToInject(target, requestingBeanName));
}
else {
if (checkPropertySkipping(pvs)) {
return;
}
try {
Method method = (Method) this.member;
ReflectionUtils.makeAccessible(method);
method.invoke(target, getResourceToInject(target, requestingBeanName));
}
catch (InvocationTargetException ex) {
throw ex.getTargetException();
}
}
}
调用都是getResourceToInject,这个方法ResourceElement进行重写,
@Override
protected Object getResourceToInject(Object target, @Nullable String requestingBeanName) {
// @lazy注解分开处理
return (this.lazyLookup ? buildLazyResourceProxy(this, requestingBeanName) :
getResource(this, requestingBeanName));
}
protected Object getResource(LookupElement element, @Nullable String requestingBeanName)
throws NoSuchBeanDefinitionException {
//忽略了其它一些
....
return autowireResource(this.resourceFactory, element, requestingBeanName);
}
autowireResource就是重要的区别方法了,仔细、仔细看下,方法会判断factory.containsBean(name)是否存在,如果不存在就转交成@Autowired处理,如果存在直接按照名称获取(这个时候就不会存在返回多bean了,但是如果名称对应的类型跟定义的类型不一致就会报错)。
protected Object autowireResource(BeanFactory factory, LookupElement element, @Nullable String requestingBeanName)
throws NoSuchBeanDefinitionException {
Object resource;
Set<String> autowiredBeanNames;
String name = element.name;
if (factory instanceof AutowireCapableBeanFactory) {
AutowireCapableBeanFactory beanFactory = (AutowireCapableBeanFactory) factory;
DependencyDescriptor descriptor = element.getDependencyDescriptor();
// 区别在这里。。。。,会判断factory.containsBean(name)是否存在,如果不存在就转交成@Autowired处理
if (this.fallbackToDefaultTypeMatch && element.isDefaultName && !factory.containsBean(name)) {
autowiredBeanNames = new LinkedHashSet<>();
resource = beanFactory.resolveDependency(descriptor, requestingBeanName, autowiredBeanNames, null);
if (resource == null) {
throw new NoSuchBeanDefinitionException(element.getLookupType(), "No resolvable resource object");
}
}
//已经存在的,直接按照名称获取
else {
resource = beanFactory.resolveBeanByName(name, descriptor);
autowiredBeanNames = Collections.singleton(name);
}
}
else {
resource = factory.getBean(name, element.lookupType);
autowiredBeanNames = Collections.singleton(name);
}
if (factory instanceof ConfigurableBeanFactory) {
ConfigurableBeanFactory beanFactory = (ConfigurableBeanFactory) factory;
for (String autowiredBeanName : autowiredBeanNames) {
if (requestingBeanName != null && beanFactory.containsBean(autowiredBeanName)) {
beanFactory.registerDependentBean(autowiredBeanName, requestingBeanName);
}
}
}
return resource;
}
个人总结下两者的区别:
- @Resource,优先按照名称注入,存在,进入bean的获取流程;不存在,回滚到@Autowired
- @Autowired,按照类型注入