Spring源码 --- AnnotatedGenericBeanDefinition的初始化使用过程

在上一章我们有提到AnnotatedGenericBeanDefinition是用来放通过注解添加的Bean的。

我们找到AnnotatedGenericBeanDefinition在Spring中使用的其中一个方法。其是在AnnotatedBeanDefinitionReader类的doRegisterBean方法:       

 void doRegisterBean(Class annotatedClass, @Nullable Supplier instanceSupplier, @Nullable String name,
      @Nullable Class[] qualifiers, BeanDefinitionCustomizer... definitionCustomizers) {

   AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass);
  ..................
   BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
}

由于最终是要将一个BeanDefinition注册到BeanDefinition容器中,这里方法中用到的放BeanDefinition的容器是this.registry,是需要继承BeanDefinitionRegistry接口:

public class AnnotatedBeanDefinitionReader {

   private final BeanDefinitionRegistry registry;

   private BeanNameGenerator beanNameGenerator = new AnnotationBeanNameGenerator();

   private ScopeMetadataResolver scopeMetadataResolver = new AnnotationScopeMetadataResolver();

   private ConditionEvaluator conditionEvaluator;
        ..................
}
public interface BeanDefinitionRegistry extends AliasRegistry {

   void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
         throws BeanDefinitionStoreException;
   void removeBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;
   BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;
   boolean containsBeanDefinition(String beanName);
   String[] getBeanDefinitionNames();
   int getBeanDefinitionCount();
   boolean isBeanNameInUse(String beanName);
}

这里本次用到的方法主要是registerBeanDefinition方法,注册到容器中

然后来看一个demo:

@Test
public void factoryBeanTest() {
   DefaultListableBeanFactory defaultListableBeanFactory = new DefaultListableBeanFactory();
   AnnotatedBeanDefinitionReader annotatedBeanDefinitionReader = new AnnotatedBeanDefinitionReader(defaultListableBeanFactory);
   annotatedBeanDefinitionReader.register(PersonFactoryBean.class);
}
@Configuration
@Conditional({PersonConditional.class})
@ComponentScan(basePackageClasses=Spr8808Tests.class) // scan *this* package
class Config {
}

@Component
@Scope(DefaultListableBeanFactory.SCOPE_SINGLETON,proxyMode = ScopedProxyMode.NO)
class PersonComponent{

   public Person getObj()
   {
      return new Person();
   }
}

然后 annotatedBeanDefinitionReader.register(PersonFactoryBean.class);方法的调用会来到:

public void registerBean(Class annotatedClass) {
   doRegisterBean(annotatedClass, null, null, null);
}

之后就来到了我们最前面的doRegisterBean方法:

 void doRegisterBean(Class annotatedClass, @Nullable Supplier instanceSupplier, @Nullable String name,
      @Nullable Class[] qualifiers, BeanDefinitionCustomizer... definitionCustomizers) {

   AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass);
   if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
      return;
   }

   abd.setInstanceSupplier(instanceSupplier);
   ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
   abd.setScope(scopeMetadata.getScopeName());
   String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));

   AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
   if (qualifiers != null) {
      for (Class qualifier : qualifiers) {
         if (Primary.class == qualifier) {
            abd.setPrimary(true);
         }
         else if (Lazy.class == qualifier) {
            abd.setLazyInit(true);
         }
         else {
            abd.addQualifier(new AutowireCandidateQualifier(qualifier));
         }
      }
   }
   for (BeanDefinitionCustomizer customizer : definitionCustomizers) {
      customizer.customize(abd);
   }

   BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
   definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
   BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
}

我们一步步看这个方法。

     一:AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass)          

public AnnotatedGenericBeanDefinition(Class beanClass) {
   setBeanClass(beanClass);
   this.metadata = new StandardAnnotationMetadata(beanClass, true);
}

setBeanClass方法就是用来设置当前BeanDefinition描叙的Bean类的名称的:

Spring源码 --- AnnotatedGenericBeanDefinition的初始化使用过程_第1张图片

当前这个就是我们注入的PersonFactoryBean类的带包名。

然后是this.metadata的初始化:private final AnnotationMetadata metadata。

这里用的实现这个AnnotationMetadata接口的类是StandardAnnotationMetadata:

public class StandardAnnotationMetadata extends StandardClassMetadata implements AnnotationMetadata {
   private final Annotation[] annotations;
   private final boolean nestedAnnotationsAsMap;
}
public StandardClassMetadata(Class introspectedClass) {
   Assert.notNull(introspectedClass, "Class must not be null");
   this.introspectedClass = introspectedClass;
}

Spring源码 --- AnnotatedGenericBeanDefinition的初始化使用过程_第2张图片

可以看到这个Annotation就是用来描叙在类上面用来哪些注解的。

  二:来到this.conditionEvaluator.shouldSkip(abd.getMetadata())方法,这个方法会返回一个Boolean值,看名称,是判断是否跳过,如果为true,就直接return。不进行下面的将BeanDefinition注册到BeanDefinition容器中。

这里用的conditionEvaluator使我们在进行AnnotatedBeanDefinitionReader初始化的时候默认设置的ConditionEvaluator类:

this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);
public boolean shouldSkip(AnnotatedTypeMetadata metadata) {
   return shouldSkip(metadata, null);
}
public boolean shouldSkip(@Nullable AnnotatedTypeMetadata metadata, @Nullable ConfigurationPhase phase) {
   if (metadata == null || !metadata.isAnnotated(Conditional.class.getName())) {
      return false;
   }

   if (phase == null) {
      if (metadata instanceof AnnotationMetadata &&
            ConfigurationClassUtils.isConfigurationCandidate((AnnotationMetadata) metadata)) {
         return shouldSkip(metadata, ConfigurationPhase.PARSE_CONFIGURATION);
      }
      return shouldSkip(metadata, ConfigurationPhase.REGISTER_BEAN);
   }

   List conditions = new ArrayList<>();
   for (String[] conditionClasses : getConditionClasses(metadata)) {
      for (String conditionClass : conditionClasses) {
         Condition condition = getCondition(conditionClass, this.context.getClassLoader());
         conditions.add(condition);
      }
   }

   AnnotationAwareOrderComparator.sort(conditions);

   for (Condition condition : conditions) {
      ConfigurationPhase requiredPhase = null;
      if (condition instanceof ConfigurationCondition) {
         requiredPhase = ((ConfigurationCondition) condition).getConfigurationPhase();
      }
      if (requiredPhase == null || requiredPhase == phase) {
         if (!condition.matches(this.context, metadata)) {
            return true;
         }
      }
   }

   return false;
}

这个方法首先是metadata.isAnnotated(Conditional.class.getName()))。这个isAnnotated方法是用来判断这个方法的入参注解是不是外部定义的注解(如果我们这里传入的是jdk自带的几个元注解例如@Target、@Retention这些,这个方法返回的是false)。例如我们在前面有在这个类加了3个注解:

Spring源码 --- AnnotatedGenericBeanDefinition的初始化使用过程_第3张图片

 这里如果类上面没有@Conditional注解的话,就返回false,如果返回false的话再上面的方法就不会return,会到下面的流程去注册Beadefinition,这里我们有加@Conditional注解,我们往下走:

      然后会调用ConfigurationClassUtils.isConfigurationCandidate((AnnotationMetadata) metadata)方法去判断,同时这里如果没有没有phase,不管是哪个流程都是一个自调用,然后去走下面的流程:

public static boolean isConfigurationCandidate(AnnotationMetadata metadata) {
   return (isFullConfigurationCandidate(metadata) || isLiteConfigurationCandidate(metadata));
}
public static boolean isFullConfigurationCandidate(AnnotationMetadata metadata) {
   return metadata.isAnnotated(Configuration.class.getName());
}

public static boolean isLiteConfigurationCandidate(AnnotationMetadata metadata) {
   if (metadata.isInterface()) {
      return false;
   }
   for (String indicator : candidateIndicators) {
      if (metadata.isAnnotated(indicator)) {
         return true;
      }
   }
   try {
      return metadata.hasAnnotatedMethods(Bean.class.getName());
   }
   catch (Throwable ex) {
      return false;
   }
}
private static final Set candidateIndicators = new HashSet<>(4);

static {
   candidateIndicators.add(Component.class.getName());
   candidateIndicators.add(ComponentScan.class.getName());
   candidateIndicators.add(Import.class.getName());
   candidateIndicators.add(ImportResource.class.getName());
}

所以这里是看在类上面有没有加@Component、@ComponentScan、@Import、@ImportResource、@Configuration注解,以及这个类的方法中有没有加@Bean注解去注入Bean(metadata.hasAnnotatedMethods(Bean.class.getName())):

public boolean hasAnnotatedMethods(String annotationName) {
   try {
      Method[] methods = getIntrospectedClass().getDeclaredMethods();
      for (Method method : methods) {
         if (!method.isBridge() && method.getAnnotations().length > 0 &&
               AnnotatedElementUtils.isAnnotated(method, annotationName)) {
            return true;
         }
      }
      return false;
   }
   ..........
}

然后有这些,就返回true,返回true之后,phase就为ConfigurationPhase.PARSE_CONFIGURATION、不然会就为ConfigurationPhase.REGISTER_BEAN。这里就有一个自调用,我们往下走:

   这次传了phase,所以直接到下面会调用到getConditionClasses(metadata)方法:

private List getConditionClasses(AnnotatedTypeMetadata metadata) {
   MultiValueMap attributes = metadata.getAllAnnotationAttributes(Conditional.class.getName(), true);
   Object values = (attributes != null ? attributes.get("value") : null);
   return (List) (values != null ? values : Collections.emptyList());
}

      这里的metadata.getAllAnnotationAttributes方法,就是获取方法上面加的这个注解的属性值,例如:

public @interface Conditional {
   Class[] value();
}

例如这个注解只有value属性。所以这里就是在获取使用注解的时候设置的value的值。由于value的值传的是数组,所以在结果的时候有进行结果强转:

   Spring源码 --- AnnotatedGenericBeanDefinition的初始化使用过程_第4张图片

然后循环遍历,通过这个包含包名的类设置对象添加到conditions中:

private Condition getCondition(String conditionClassName, ClassLoader classloader) {
   Class conditionClass = ClassUtils.resolveClassName(conditionClassName, classloader);
   return (Condition) BeanUtils.instantiateClass(conditionClass);
}
public static  T instantiateClass(Class clazz) throws BeanInstantiationException {
      .................
      Constructor ctor = (KotlinDetector.isKotlinType(clazz) ?
            KotlinDelegate.getPrimaryConstructor(clazz) : clazz.getDeclaredConstructor());
      return instantiateClass(ctor);
     .......
}
public static  T instantiateClass(Constructor ctor, Object... args) throws BeanInstantiationException {
      .............
      ReflectionUtils.makeAccessible(ctor);
      return (KotlinDetector.isKotlinType(ctor.getDeclaringClass()) ?
            KotlinDelegate.instantiateClass(ctor, args) : ctor.newInstance(args));
      .............
}

   这个BeanUtils.instantiateClass就是根据类名产生对象,然后添加到conditions。

    将这个conditions排序后来到:

for (Condition condition : conditions) {
   ConfigurationPhase requiredPhase = null;
   if (condition instanceof ConfigurationCondition) {
      requiredPhase = ((ConfigurationCondition) condition).getConfigurationPhase();
   }
   if (requiredPhase == null || requiredPhase == phase) {
      if (!condition.matches(this.context, metadata)) {
         return true;
      }
   }
}
return false;
public interface ConfigurationCondition extends Condition {
   ConfigurationPhase getConfigurationPhase();
   enum ConfigurationPhase {
      PARSE_CONFIGURATION,
      REGISTER_BEAN
   }
}

      这里可以看到前面传入的phase的作用,是判断这个Condition是否为ConfigurationCondition。如果是获取这个ConfigurationCondition是哪种类型,如果类型不匹配、或者不是ConfigurationCondition类型,直接返回false,去注入Beandefinition,如果类型匹配,或者直接是Condition,就运行condition.matches方法,如果不matche,返回true然后直接return不注册Beandefinition。前面注解加的实现Condition接口类:

public class PersonConditional implements Condition {

   @Override
   public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
      return true;
   }
}

然后回到doRegisterBean类接着往下:

    然后是ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd)方法,这里是获取ScopeMetadata,即描叙@Scope内容的类:

public class ScopeMetadata {
   private String scopeName = BeanDefinition.SCOPE_SINGLETON;
   private ScopedProxyMode scopedProxyMode = ScopedProxyMode.NO;
  ..........
}
protected Class scopeAnnotationType = Scope.class;
public ScopeMetadata resolveScopeMetadata(BeanDefinition definition) {
   ScopeMetadata metadata = new ScopeMetadata();
   if (definition instanceof AnnotatedBeanDefinition) {
      AnnotatedBeanDefinition annDef = (AnnotatedBeanDefinition) definition;
      AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(
            annDef.getMetadata(), this.scopeAnnotationType);
      if (attributes != null) {
         metadata.setScopeName(attributes.getString("value"));
         ScopedProxyMode proxyMode = attributes.getEnum("proxyMode");
         if (proxyMode == ScopedProxyMode.DEFAULT) {
            proxyMode = this.defaultProxyMode;
         }
         metadata.setScopedProxyMode(proxyMode);
      }
   }
   return metadata;
}

           Spring源码 --- AnnotatedGenericBeanDefinition的初始化使用过程_第5张图片

即通过Scope注解设置ScopeMetadata 的value属性,及proxyMode属性。这个ScopeProxyMode:

public enum ScopedProxyMode {
   /**
    * Default typically equals {@link #NO}, unless a different default
    * has been configured at the component-scan instruction level.
    */
   DEFAULT,
   /**
    * Do not create a scoped proxy.
    * 

This proxy-mode is not typically useful when used with a * non-singleton scoped instance, which should favor the use of the * {@link #INTERFACES} or {@link #TARGET_CLASS} proxy-modes instead if it * is to be used as a dependency. */ NO, /** * Create a JDK dynamic proxy implementing all interfaces exposed by * the class of the target object. */ INTERFACES, /** * Create a class-based proxy (uses CGLIB). */ TARGET_CLASS; }

可以看到没人是NO不使用代理,INTERFACES是使用JDK dynamic proxy(jdk动态代理)、TARGET_CLASS使用class-based proxy (uses CGLIB),通过CGLIB产生代理。CGLIB是通过类去初始代理,JDK动态代理是通过接口。

那这个Scope的动态代理是什么作用呢?首先明白动态代理,即在运行时产生对象。然后在联系Scope的范围。有单例,多例,这些可以直接注入到容器中,但还有request、application、session范围的。例如rquest范围的,需要运行时有请求来的时候再产生对象将其放到request中。所以就要用到代理。可以通过@Scope注解的proxyMode属性设置。例如前面例子中用到的:

@Scope(value = DefaultListableBeanFactory.SCOPE_SINGLETON,proxyMode = ScopedProxyMode.NO)

获取ScopeMetadata后接着往下:

    再回到doRegisterBean方法、设置scopeName,这里是单例

               Spring源码 --- AnnotatedGenericBeanDefinition的初始化使用过程_第6张图片

然后通过abd获取bean的名称,之后调用AnnotationConfigUtils.processCommonDefinitionAnnotations(abd)方法:

static void processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd, AnnotatedTypeMetadata metadata) {
   AnnotationAttributes lazy = attributesFor(metadata, Lazy.class);
   if (lazy != null) {
      abd.setLazyInit(lazy.getBoolean("value"));
   }
   else if (abd.getMetadata() != metadata) {
      lazy = attributesFor(abd.getMetadata(), Lazy.class);
      if (lazy != null) {
         abd.setLazyInit(lazy.getBoolean("value"));
      }
   }

   if (metadata.isAnnotated(Primary.class.getName())) {
      abd.setPrimary(true);
   }
   AnnotationAttributes dependsOn = attributesFor(metadata, DependsOn.class);
   if (dependsOn != null) {
      abd.setDependsOn(dependsOn.getStringArray("value"));
   }

   if (abd instanceof AbstractBeanDefinition) {
      AbstractBeanDefinition absBd = (AbstractBeanDefinition) abd;
      AnnotationAttributes role = attributesFor(metadata, Role.class);
      if (role != null) {
         absBd.setRole(role.getNumber("value").intValue());
      }
      AnnotationAttributes description = attributesFor(metadata, Description.class);
      if (description != null) {
         absBd.setDescription(description.getString("value"));
      }
   }
}

如果加了@Lazy、@Primary等这些注解。将这些注解的属性值设置到Beandefinition中。

然后判断doRegisterBean方法的入参qualifiers,如果有这些会覆盖掉前面设置的@Lazy、@Primary的值(优先级更高)。

在之后通过BeanDefinitionCustomizer接口去自定义修改Beandefinition的内容:

public interface BeanDefinitionCustomizer {
   /**
    * Customize the given bean definition.
    */
   void customize(BeanDefinition bd);

}

   然后构建Beandefinition的持有对象:BeanDefinitionHolder

public class BeanDefinitionHolder implements BeanMetadataElement {
   private final BeanDefinition beanDefinition;
   private final String beanName;
   @Nullable
   private final String[] aliases;
.........
}
然后是AnnotationConfigUtils.applyScopedProxyMode方法调用。这个方法是根据scopeMetadata,例如设置proxyMode属性是INTERFACES、TARGET_CLASS,就产生一个代理对象Deandefinition。主要是将Beandefinition的beanClass修改为实现FactoryBean接口的类,通过FactoryBean类去产生需要的目的类:
static BeanDefinitionHolder applyScopedProxyMode(
      ScopeMetadata metadata, BeanDefinitionHolder definition, BeanDefinitionRegistry registry) {

   ScopedProxyMode scopedProxyMode = metadata.getScopedProxyMode();
   if (scopedProxyMode.equals(ScopedProxyMode.NO)) {
      return definition;
   }
   boolean proxyTargetClass = scopedProxyMode.equals(ScopedProxyMode.TARGET_CLASS);
   return ScopedProxyCreator.createScopedProxy(definition, registry, proxyTargetClass);
}
public static BeanDefinitionHolder createScopedProxy(BeanDefinitionHolder definition,
      BeanDefinitionRegistry registry, boolean proxyTargetClass) {

   String originalBeanName = definition.getBeanName();
   BeanDefinition targetDefinition = definition.getBeanDefinition();
   String targetBeanName = getTargetBeanName(originalBeanName);
   RootBeanDefinition proxyDefinition = new RootBeanDefinition(ScopedProxyFactoryBean.class);
   proxyDefinition.setDecoratedDefinition(new BeanDefinitionHolder(targetDefinition, targetBeanName));
   
   proxyDefinition.getPropertyValues().add("targetBeanName", targetBeanName);
   if (proxyTargetClass) {
      targetDefinition.setAttribute(AutoProxyUtils.PRESERVE_TARGET_CLASS_ATTRIBUTE, Boolean.TRUE);
   }
   else {
      proxyDefinition.getPropertyValues().add("proxyTargetClass", Boolean.FALSE);
   }
         ............
   registry.registerBeanDefinition(targetBeanName, targetDefinition);
      .......
return new BeanDefinitionHolder(proxyDefinition, originalBeanName, definition.getAliases());
}

代理BeanDefintion:proxyDefinition = new RootBeanDefinition(ScopedProxyFactoryBean.class);

这里的ScopedProxyFactoryBean就实现了FactoryBean。关于FactoryBean的内容,到下一篇再进行源码分析。

    然后将targetBeanName Beanfinition注册到到容器。再回到doRegisterBean方法。将originalBeanName Beandefintion注册到容器。

BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);

方法结束。

你可能感兴趣的:(#,Spring系列)