众所周知,Spring的依赖注入(DI)对Spring IOC 有着举足轻重的作用,是Spring灵魂所在。本篇文章就从日常开发中最常用的注解@Autowired开始,着手分析Spring是如何通过它们将Bean所需的外部资源注入其中.
先定义一个要注入的类
public class WakingLeon{
private Long id;
private String name;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public static WakingLeon createLeon() {
return new WakingLeon();
}
@Override
public String toString() {
return "WakingLeon{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
}
然后我们新建一个被注入的类AutowiredAnnotationInjectionDemo,用@Bean的方式定义一个Bean(也可以用xml去配置)
@Bean
public WakingLeon wakingLeon(){
WakingLeon wakingLeon = new WakingLeon();
wakingLeon.setId(1L);
wakingLeon.setName("Leon");
return wakingLeon;
}
我们通过main中自定义上下文的方式演示:
public static void main(String[] args) {
//新建一个容器
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
//将当前被注入的类注册到容器中
applicationContext.register(AutowiredAnnotationInjectionDemo.class);
//启动容器
applicationContext.refresh();
//查找AutowiredAnnotationInjectionDemo
AutowiredAnnotationInjectionDemo demoBean = applicationContext.getBean(AutowiredAnnotationInjectionDemo.class);
System.out.println("demoBean.wakingLeon: " + demoBean.wakingLeon);
//手动销毁容器
applicationContext.close();
}
首先,我们看@Autowired的定义里可以发现,它是通过AutowiredAnnotationBeanPostProcessor去实现解析的
* @author Juergen Hoeller
* @author Mark Fisher
* @author Sam Brannen
* @since 2.5
* @see AutowiredAnnotationBeanPostProcessor
* @see Qualifier
* @see Value
*/
@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Autowired {
/**
* Declares whether the annotated dependency is required.
* Defaults to {@code true}.
*/
boolean required() default true;
}
先看一下AutowiredAnnotationBeanPostProcessor继承结构图(图画的有点丑,哈哈):
通过此图可得出一些基本结论:AutowiredAnnotationBeanPostProcessor分别实现了InstantiationAwareBeanPostProcessorAdapter(Bean实例化相关)、MergedBeanDefinitionPostProcessor(合并BeanDefinition)、
PriorityOrdered(排序), BeanFactoryAware(BeanFactory的回调)
AutowiredAnnotationBeanPostProcessor
第一阶段:元信息解析
首先, 通过构造方法:
/**
* Create a new {@code AutowiredAnnotationBeanPostProcessor} for Spring's
* standard {@link Autowired @Autowired} annotation.
* Also supports JSR-330's {@link javax.inject.Inject @Inject} annotation,
* if available.
*/
@SuppressWarnings("unchecked")
public AutowiredAnnotationBeanPostProcessor() {
this.autowiredAnnotationTypes.add(Autowired.class);
this.autowiredAnnotationTypes.add(Value.class);
try {
//Inject要生效需讲javax.inject.Inject加入classpath中
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.
}
}
AutowiredAnnotationBeanPostProcessor执行构造方法时集合autowiredAnnotationTypes中依次放入了三个注解类Autowired、Value和JSR-330标准的Inject
/**
* 这两个setAutowiredAnnotationType是用于实现自定义依赖注入注解类型,首先它会把autowiredAnnotationTypes里面的元素全部clear,
* 然后加入自定义的依赖注入注解类型,所以我们要注意在实现自定义注解注入时,这里会先把默认的注解类型清除
*/
public void setAutowiredAnnotationType(Class<? extends Annotation> autowiredAnnotationType) {
Assert.notNull(autowiredAnnotationType, "'autowiredAnnotationType' must not be null");
this.autowiredAnnotationTypes.clear();
this.autowiredAnnotationTypes.add(autowiredAnnotationType);
}
public void setAutowiredAnnotationTypes(Set<Class<? extends Annotation>> autowiredAnnotationTypes) {
Assert.notEmpty(autowiredAnnotationTypes, "'autowiredAnnotationTypes' must not be empty");
this.autowiredAnnotationTypes.clear();
this.autowiredAnnotationTypes.addAll(autowiredAnnotationTypes);
}
/**
* 从这里开始有三个依次在执行中调用的方法,是解析注解元信息非常重要的核心方法
*/
@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
metadata.checkConfigMembers(beanDefinition);
}
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());
// 这里用bean的名称作为key
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;
}
//这里是核心,它的作用就是把所有@Autowired注解标注的依赖都转换为InjectionMetadata元信息给后面使用
//
private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {
if (!AnnotationUtils.isCandidateClass(clazz, this.autowiredAnnotationTypes)) {
return InjectionMetadata.EMPTY;
}
List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();
Class<?> targetClass = clazz;
//这里的do while 循环每个Class
do {
final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>();
//doWithLocalFields方法会递归的去找父类所有标注@Autowired的属性
ReflectionUtils.doWithLocalFields(targetClass, field -> {
MergedAnnotation<?> ann = findAutowiredAnnotation(field);
if (ann != null) {
//注: Autowired放在静态字段方法上,不会注入,但不会报错,会无效
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);
}
至此,通过postProcessMergedBeanDefinition()把我们注解标注的依赖及其父类的属性、方法进行合并Mergerd并全部转换成
InjectionMetadata,接下来进入注入阶段
第二阶段 注入
根据Bean的生命周期,Bean在实例化以后, 会调用AbstractAutowireCapableBeanFactory#populateBean()方法完成对Bean的属性填充,这个方法里面会触发postProcessPropertyValues()方法给属性赋值:
//AbstractAutowireCapableBeanFactory#populateBean()里找到这个循环,它会取出容器中的所有BeanPostProcessor
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
if (filteredPds == null) {
filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
}
//postProcessPropertyValues是一个模板方法
pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
return;
}
}
pvs = pvsToUse;
}
}
围绕着这个模板方法postProcessPropertyValues, 我们回到AutowiredAnnotationBeanPostProcessor,找到postProcessPropertyValues的重写:
//postProcessProperties在所有setter方法之前执行
@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
//从缓存中取出对应已经解析好的元信息
InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
try {
//这里就是依赖注入的核心,InjectionMetadata的inject
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;
}
@Deprecated //已过期
@Override
public PropertyValues postProcessPropertyValues(
PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) {
return postProcessProperties(pvs, bean, beanName);
}
终于找到了核心InjectionMetadata#inject(),那么我们找一个实现,AutowiredFieldElement
//继承静态抽象内部类InjectionMetadata.InjectedElement,且为AutowiredAnnotationBeanPostProcessor的私有类,很高的内聚性
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 {
//InjectedElement 的member是反射里面的顶层接口,Field Method还有Constructor都是他的实现
Field field = (Field) this.member;
Object value;
if (this.cached) {
//这里面会调用到beanFactory.resolveDependency
value = resolvedCachedArgument(beanName, this.cachedFieldValue);
}
else {
//这里将field包装成DependencyDescriptor
DependencyDescriptor desc = new DependencyDescriptor(field, this.required);
//设置containingClass
desc.setContainingClass(bean.getClass());
//从LinkedHashSet看出注入的是有顺序的,按BeanDefinition定义先后的顺序
Set<String> autowiredBeanNames = new LinkedHashSet<>(1);
Assert.state(beanFactory != null, "No BeanFactory available");
TypeConverter typeConverter = beanFactory.getTypeConverter();
try {
//重点方法, beanFactory#resolveDependency 从beanFactory里面获取依赖值
value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
}
catch (BeansException ex) {
throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex);
}
//这里把value缓存起来,当同一个Field多次注入时提高效率
synchronized (this) {
if (!this.cached) {
if (value != null || this.required) {
//缓存值为DependencyDescriptor对象
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赋值到feild
if (value != null) {
ReflectionUtils.makeAccessible(field);
field.set(bean, value);
}
}
}
我们跟进这里的beanFactory.resolveDependency,进入DefaultListableBeanFactory, 这个方法有个重要的入参DependencyDescriptor:
/**
* Descriptor for a specific dependency that is about to be injected.
* Wraps a constructor parameter, a method parameter or a field,
* allowing unified access to their metadata.
*
* @author Juergen Hoeller
* @since 2.5
*/
@SuppressWarnings("serial")
public class DependencyDescriptor extends InjectionPoint implements Serializable {
//被申明的类,也就是注入的容器
private final Class<?> declaringClass;
@Nullable //方法注入名 这里可为空 因为不都是方法注入
private String methodName;
@Nullable //参数类型
private Class<?>[] parameterTypes;
//参数索引顺序
private int parameterIndex;
@Nullable //字段注入的字段名
private String fieldName;
//是否必需
private final boolean required;
//是否是饥饿的 对应@Lazy
private final boolean eager;
//嵌入层次
private int nestingLevel = 1;
@Nullable
private Class<?> containingClass;
@Nullable //类型处理
private transient volatile ResolvableType resolvableType;
@Nullable//类型描述 描述类型相关的内容
private transient volatile TypeDescriptor typeDescriptor;
通过DependencyDescriptor 的每个描述字段可以大致猜到注入的wakingLeon依赖对应的相关描述
1: 实时注入(eager=true)并且是required=true
2:通过类型(WakingLeon.class)依赖查找
3: 字段名称 wakingLeon
在resolveDependency里面debug, 观察DependencyDescriptor 里的值和猜测的基本一致 :
回到resolveDependency方法:
@Override
@Nullable
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()) {
return createOptionalDependency(descriptor, requestingBeanName);
}
//支持ObjectFactory和ObjectProvider(延迟注入)
else if (ObjectFactory.class == descriptor.getDependencyType() ||
ObjectProvider.class == descriptor.getDependencyType()) {
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) {
//绝大多数情况下都会执行doResolveDependency
result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
}
return result;
}
}
@Nullable
public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
//这个方法是通过依赖描述符处理注入多次嵌套
InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
try {
Object shortcut = descriptor.resolveShortcut(this);
if (shortcut != null) {
return shortcut;
}
...
//这里判断是否是集合类型的多个bean,包括Array、 Collection、Map
Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
if (multipleBeans != null) {
return multipleBeans;
}
//这里的beanName指的是被注入的bean的名称,本文中指的就是AutowiredAnnotationInjectionDemo,type指的就是注入的类(WakingLeon.class)
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
if (matchingBeans.isEmpty()) {
if (isRequired(descriptor)) {
raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
}
return null;
}
...
return result;
}
finally {
//设置到当前的注入点
ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
}
}
Spring使用了大量的委托代理还有模板方法等,实现了高内聚低耦合的特点。整个对@Autowired依赖注入的流程分为两个周期,第一个是解析元信息并放入缓存中,第二个周期是注入,
在我看来,每个阶段有每个阶段的核心,解析元信息核心是模仿双亲委派的父类优先的原则去合并BeanDefition, 并全部转换成InjectionMetadata, 第二个阶段就是InjectionMetadata的inject方法的实现,其中会涉及到beanFactory.resolveDependency,这里可以处理多种注入类型的封装,包括Optional、ObjectFactory、ObjectProvider和jsr330 里面的依赖注入方案,最后处理默认注入操作,最终通过反射将值设置到字段当中。
理解了依赖注入的流程后,可以做个扩展。如果遇到一些必须提早注册一些Bean的场景的时候,就可以自定义依赖注入注解和AutowiredAnnotationBeanPostProcessor去提早触发注入机制,代码简单演示一下:
//注解是没法通过extends继承,可以将原注解标注在我们自定义注解上的方式继承
@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Autowired
public @interface LeonAutowired {
}
**
* 自定义注入演示类
*/
public class AutowiredAnnotationInjectionDemo {
@LeonAutowired
private WakingLeon wakingLeon;
@Bean
public WakingLeon wakingLeon(){
WakingLeon wakingLeon = new WakingLeon();
wakingLeon.setId(1L);
wakingLeon.setName("Leon");
return wakingLeon;
}
//注意这里要设置成static,不然依赖注入会失效,因为这个AutowiredAnnotationBeanPostProcessor定义在当前demo类中,想要拿到自定义的AutowiredAnnotationBeanPostProcessor,就必须实例化demo类
//但是在实例化demo类LeonAutowired也同时被处理了,此时还没有自定义的AutowiredAnnotationBeanPostProcessor,因此不认识@LeonAutowired,
//因此被注入了null。然后等实例化完了之后自定义的AutowiredAnnotationBeanPostProcessor才拿到
@Bean(value = "LeonAutowiredAnnotationBeanPostProcessor")
public static AutowiredAnnotationBeanPostProcessor autowiredAnnotationBeanPostProcessor(){
AutowiredAnnotationBeanPostProcessor beanPostProcessor = new AutowiredAnnotationBeanPostProcessor();
//这里可以把默认的注解放进来或者用@Order注解去实现优先级
beanPostProcessor.setAutowiredAnnotationType(LeonAutowired.class);
return beanPostProcessor;
}
public static void main(String[] args) {
//新建一个容器
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
//将当前被注入的类注册到容器中
applicationContext.register(AutowiredAnnotationInjectionDemo.class);
//启动容器
applicationContext.refresh();
//查找AutowiredAnnotationInjectionDemo
AutowiredAnnotationInjectionDemo demoBean = applicationContext.getBean(AutowiredAnnotationInjectionDemo.class);
System.out.println("demoBean.wakingLeon: " + demoBean.wakingLeon);
//手动销毁容器
applicationContext.close();
}
}
执行一下:
这个Bean就通过自定义的@LeonAutowired注解注入进来了。
至此,@Autowired的依赖注入流程就分析完毕。与@Autowired等效的@Resource注解虽然注入效果一样,但是是通过另一个BeanPostProcessor–CommonAnnotationBeanPostProcessor去实现的,实现流程大同小异,提供对jdk注入注解和ejb WebServiceRef等注入注解的支持,这里就不再总结了。