[关闭]
@yulongsun 2018-05-09T01:26:57.000000Z 字数 7320 阅读 1547

Spring核心类 - AnnotationConfigApplicationContext

Spring源码走读


1. AnnotationConfigApplicationContext

由Spring3.0引入,用于处理Spring注解。

org.springframework.context.annotation.AnnotationConfigApplicationContext

  1. public class AnnotationConfigApplicationContext extends GenericApplicationContext implements AnnotationConfigRegistry {
  2. private final AnnotatedBeanDefinitionReader reader;
  3. private final ClassPathBeanDefinitionScanner scanner;
  4. public AnnotationConfigApplicationContext() {
  5. //创建Bean定义读取器
  6. this.reader = new AnnotatedBeanDefinitionReader(this);
  7. //创建Bean定义扫描器
  8. this.scanner = new ClassPathBeanDefinitionScanner(this);
  9. }
  10. public AnnotationConfigApplicationContext(DefaultListableBeanFactory beanFactory) {
  11. super(beanFactory);
  12. this.reader = new AnnotatedBeanDefinitionReader(this);
  13. this.scanner = new ClassPathBeanDefinitionScanner(this);
  14. }
  15. public AnnotationConfigApplicationContext(Class... annotatedClasses) {
  16. this();
  17. this.register(annotatedClasses);
  18. this.refresh();
  19. }
  20. public AnnotationConfigApplicationContext(String... basePackages) {
  21. this();
  22. this.scan(basePackages);
  23. this.refresh();
  24. }
  25. public void setEnvironment(ConfigurableEnvironment environment) {
  26. super.setEnvironment(environment);
  27. this.reader.setEnvironment(environment);
  28. this.scanner.setEnvironment(environment);
  29. }
  30. public void setBeanNameGenerator(BeanNameGenerator beanNameGenerator) {
  31. this.reader.setBeanNameGenerator(beanNameGenerator);
  32. this.scanner.setBeanNameGenerator(beanNameGenerator);
  33. this.getBeanFactory().registerSingleton("org.springframework.context.annotation.internalConfigurationBeanNameGenerator", beanNameGenerator);
  34. }
  35. public void setScopeMetadataResolver(ScopeMetadataResolver scopeMetadataResolver) {
  36. this.reader.setScopeMetadataResolver(scopeMetadataResolver);
  37. this.scanner.setScopeMetadataResolver(scopeMetadataResolver);
  38. }
  39. protected void prepareRefresh() {
  40. this.scanner.clearCache();
  41. super.prepareRefresh();
  42. }
  43. //新注册Bean.需调用refresh()刷新,触发容器对新注册Bean的处理。
  44. public void register(Class... annotatedClasses) {
  45. Assert.notEmpty(annotatedClasses, "At least one annotated class must be specified");
  46. this.reader.register(annotatedClasses);
  47. }
  48. public void scan(String... basePackages) {
  49. Assert.notEmpty(basePackages, "At least one base package must be specified");
  50. this.scanner.scan(basePackages);
  51. }
  52. }

2. 解析

2.1 Spring对于类级别注解和类内部注解的处理方式?

2.2 注解Bean定义读取器 AnnotatedBeanDefinitionReader

  1. public class AnnotatedBeanDefinitionReader {
  2. ......
  3. public void register(Class<?>... annotatedClasses) {
  4. for (Class<?> annotatedClass : annotatedClasses) {
  5. registerBean(annotatedClass);
  6. }
  7. }
  8. public void registerBean(Class<?> annotatedClass) {
  9. registerBean(annotatedClass, null, (Class<? extends Annotation>[]) null);
  10. }
  11. public void registerBean(Class<?> annotatedClass, Class<? extends Annotation>... qualifiers) {
  12. registerBean(annotatedClass, null, qualifiers);
  13. }
  14. public void registerBean(Class<?> annotatedClass, String name, Class<? extends Annotation>... qualifiers) {
  15. AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass);
  16. if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
  17. return;
  18. }
  19. ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
  20. abd.setScope(scopeMetadata.getScopeName());
  21. String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));
  22. AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
  23. if (qualifiers != null) {
  24. for (Class<? extends Annotation> qualifier : qualifiers) {
  25. if (Primary.class == qualifier) {
  26. abd.setPrimary(true);
  27. }
  28. else if (Lazy.class == qualifier) {
  29. abd.setLazyInit(true);
  30. }
  31. else {
  32. abd.addQualifier(new AutowireCandidateQualifier(qualifier));
  33. }
  34. }
  35. }
  36. BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
  37. definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
  38. //
  39. BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
  40. }
  41. }

2.3 类路径Bean定义扫描器 ClassPathBeanDefinitionScanner

  1. public class ClassPathBeanDefinitionScanner extends ClassPathScanningCandidateComponentProvider {
  2. ...
  3. public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters, Environment environment) {
  4. // 调用父类的构造方法,设置过滤规则
  5. super(useDefaultFilters, environment);
  6. // 为容器设置Bean定义的注册器
  7. this.registry = registry;
  8. // 如果注册器是资源加载器,则为容器设置资源加载器
  9. if (this.registry instanceof ResourceLoader) {
  10. setResourceLoader((ResourceLoader) this.registry);
  11. }
  12. }
  13. public int scan(String... basePackages) {
  14. //获取已注册的Bean个数
  15. int beanCountAtScanStart = this.registry.getBeanDefinitionCount();
  16. //启动扫描器 扫描指定package
  17. doScan(basePackages);
  18. // 注册注解配置处理器
  19. if (this.includeAnnotationConfig) {
  20. AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
  21. }
  22. //返回新注册的Bean个数
  23. return (this.registry.getBeanDefinitionCount() - beanCountAtScanStart);
  24. }
  25. protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
  26. //创建一个集合,存放扫描到Bean定义的封装类
  27. Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<BeanDefinitionHolder>();
  28. for (String basePackage : basePackages) {
  29. //获取符合条件的BeanDefinition
  30. Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
  31. for (BeanDefinition candidate : candidates) {
  32. //获取Bean的作用域
  33. ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
  34. //为Bean设置注解配置的作用域
  35. candidate.setScope(scopeMetadata.getScopeName());
  36. //为Bean设置名字
  37. String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
  38. //【重要】 如果扫描到的不是注解的Bean
  39. if (candidate instanceof AbstractBeanDefinition) {
  40. postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
  41. }
  42. //【重要】 如果扫描到的是注解的Bean,调用工具类处理通用的注解
  43. if (candidate instanceof AnnotatedBeanDefinition) {
  44. AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
  45. }
  46. //根据Bean名称,检查Bean是否需要在容器中注册。
  47. if (checkCandidate(beanName, candidate)) {
  48. BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
  49. //根据注解中配置的作用域,为Bean设置相应的代理模式
  50. definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
  51. beanDefinitions.add(definitionHolder);
  52. //向容器中注册扫描到的Bean
  53. registerBeanDefinition(definitionHolder, this.registry);
  54. }
  55. }
  56. }
  57. return beanDefinitions;
  58. }
  59. ....
  60. }

3. 实践:如何实现自定义Spring注解?

1、定制注册表

  1. public class CustomBeanDefinitionRegistry implements BeanDefinitionRegistryPostProcessor {
  2. @Override
  3. public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException {
  4. ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(beanDefinitionRegistry);
  5. // 指定include注解
  6. AnnotationTypeFilter includeFiliter = new AnnotationTypeFilter(CustomComponent.class);
  7. scanner.addIncludeFilter(includeFiliter);
  8. // 指定扫描包
  9. String[] basePackages = {"win.yulongsun.demo.spring.di.scan"};
  10. scanner.scan(basePackages);
  11. }
  12. @Override
  13. public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
  14. }
  15. }

2、自定义注解

  1. public @interface CustomComponent {
  2. }

3、使用注解

  1. @CustomComponent
  2. public class Foo {
  3. public void say() {
  4. System.out.println("i am class");
  5. }
  6. }

4、测试

  1. @RunWith(SpringJUnit4ClassRunner.class)
  2. @ContextConfiguration(classes = {CustomBeanDefinitionRegistry.class})
  3. public class CustomBeanDefinitionRegistryTest {
  4. @Autowired
  5. private ApplicationContext applicationContext;
  6. @Test
  7. public void testAssertBean() {
  8. Assert.notNull(applicationContext.getBean(Foo.class));
  9. Foo bean = applicationContext.getBean(Foo.class);
  10. bean.say();
  11. }
  12. }

4. 参考

1、Spring对注解(Annotation)处理源码分析1——扫描和读取Bean定义
2、Spring(25)——ClassPathBeanDefinitionScanner

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注