在上一章我们有提到AnnotatedGenericBeanDefinition是用来放通过注解添加的Bean的。
我们找到AnnotatedGenericBeanDefinition在Spring中使用的其中一个方法。其是在AnnotatedBeanDefinitionReader类的doRegisterBean方法:
void doRegisterBean(Class annotatedClass, @Nullable Supplier instanceSupplier, @Nullable String name, @Nullable Class extends Annotation>[] 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 extends Annotation>[] 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 extends Annotation> 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类的名称的:
当前这个就是我们注入的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; }
可以看到这个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个注解:
这里如果类上面没有@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 ListgetConditionClasses(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 extends Condition>[] value(); }
例如这个注解只有value属性。所以这里就是在获取使用注解的时候设置的value的值。由于value的值传的是数组,所以在结果的时候有进行结果强转:
然后循环遍历,通过这个包含包名的类设置对象添加到conditions中:
private Condition getCondition(String conditionClassName, ClassLoader classloader) { Class> conditionClass = ClassUtils.resolveClassName(conditionClassName, classloader); return (Condition) BeanUtils.instantiateClass(conditionClass); }public staticT instantiateClass(Class clazz) throws BeanInstantiationException { ................. Constructor ctor = (KotlinDetector.isKotlinType(clazz) ? KotlinDelegate.getPrimaryConstructor(clazz) : clazz.getDeclaredConstructor()); return instantiateClass(ctor); ....... } public staticT 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 extends Annotation> 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; }
即通过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,这里是单例
然后通过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);
方法结束。