spring 学习-bean创建-refresh前奏
作者:互联网
概述
这篇文章我们将会 注解式生成bean的过程,总的来说就是 :
- 初始化一个Context
- 扫描生成 BeanDefinition
- 调用 refresh 方法 其中第一个步骤由于是注解类,利用第一步初始化生成的 Scan 类进行扫描特定包下的 bean ,然后根据属性,例如作用域,单例模式还是模板模式等属性生成 BeanDefinition ,最后调用 上下文 context 父类的refresh 方法,进行调用(BeanFactoryPostProcess)后置处理器处理方法和BeanPostProcess处理器处理方法。
例子1
public static void main(String[] args) { AnnotationConfigApplicationContext consumerContext = new AnnotationConfigApplicationContext(); //这里看到我们注册了一个 configuration 的类进行配置,然后刷新一下容器得到最新的结果 consumerContext.register(ConsumerConfiguration.class); consumerContext.refresh(); //从容器中获取类 FooServiceConsumer service = consumerContext.getBean(FooServiceConsumer.class); ... }
例子2
idea 中new一个新的 spring项目,然后编写两个类 。
@Component public class MyService { public String sayHello(){ return "hello world "; } } public class SpringTest { public static void main(String[] args) { ApplicationContext ctx = new AnnotationConfigApplicationContext("main");//A MyService myService = ctx.getBean(MyService.class); String s = myService.sayHello(); System.out.println("s : "+ s); } }
我们以例子二为源码阅读,从 A 处 debug 进去,看一下 bean 的加载和创建
AnnotationConfigApplicationContext 的创建过程概述
构造方法很清晰 : 初始化,扫描,刷新三个步骤。
public AnnotationConfigApplicationContext(String... basePackages) { //初始化 this(); //扫描包 scan(basePackages); //刷新 refresh(); }
源码分析
需要知道的类 :
- Resoure 对应读取操作
- BeanDefinitionRead 对应解析操作、
- Registry 对应注册操作。
以 AnnotationConfigApplicationContext 为例子,查看类图主要包含三个类型的接口
- AppContext : 上下文
- Lifecycle : 生命周期
- Registry : 用于注册 BeanDefinition
AnnotationConfigApplicationContext 的初始化创建的两个类作用如下 :
- AnnotatedBeanDefinitionReader :注册几个后置处理器
- ClassPathBeanDefinitionScanner :扫描包内的bean
public AnnotationConfigApplicationContext(String... basePackages) { //初始化 this(); //扫描包 scan(basePackages); //刷新 refresh(); } /** * Create a new AnnotationConfigApplicationContext that needs to be populated * through {@link #register} calls and then manually {@linkplain #refresh refreshed}. * * 构造方法,从注释也可以看到,构造完,需要调用 register 方法进行填充和 refresh 方法进行刷新 */ public AnnotationConfigApplicationContext() { this.reader = new AnnotatedBeanDefinitionReader(this); this.scanner = new ClassPathBeanDefinitionScanner(this); } //============ 父类初始化 ============== //========================== //GenericApplicationContext public GenericApplicationContext() { this.beanFactory = new DefaultListableBeanFactory(); } //AbstractApplicationContext public AbstractApplicationContext() { this.resourcePatternResolver = getResourcePatternResolver(); } //DefaultResourceLoader public DefaultResourceLoader() { this.classLoader = ClassUtils.getDefaultClassLoader(); } public static ClassLoader getDefaultClassLoader() { ClassLoader cl = null; try { cl = Thread.currentThread().getContextClassLoader(); } catch (Throwable ex) { // Cannot access thread context ClassLoader - falling back... } if (cl == null) { // No thread context class loader -> use class loader of this class. cl = ClassUtils.class.getClassLoader(); if (cl == null) { // getClassLoader() returning null indicates the bootstrap ClassLoader try { cl = ClassLoader.getSystemClassLoader(); } catch (Throwable ex) { // Cannot access system ClassLoader - oh well, maybe the caller can live with null... } } } return cl; } //============ 父类初始化 ============== //============ AnnotatedBeanDefinitionReader 类初始化 ============== public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) { Assert.notNull(registry, "BeanDefinitionRegistry must not be null"); Assert.notNull(environment, "Environment must not be null"); //保存父类字段 this.registry = registry; //步骤一 : 用于解析 @Condition 注解相关 this.conditionEvaluator = new ConditionEvaluator(registry, environment, null); //步骤二 : 最终会调用 register®isterBeanDefinition方法注册入几个默认的 BeanDefinition AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry); }
其中步骤二中注入的类包括 :
作用:内部托管配置注释处理器。 对应的类:ConfigurationClassPostProcessor.class 作用:内部管理的自动注入注解处理器 对应的类:AutowiredAnnotationBeanPostProcessor.class 作用:内部管理的JSR-250注释处理器 对应的类:CommonAnnotationBeanPostProcessor.class 作用:内部管理的JPA注释处理器(不一定注入)。 对应的类:PersistenceAnnotationBeanPostProcessor.class 作用:内部管理的@EventListener注释处理器 对应的类:EventListenerMethodProcessor.class 作用:内部管理的EventListenerFactory。 对应的类:DefaultEventListenerFactory.class
BeanDefinition 是个接口,我们看一下 ClassPathBeanDefinitionScanner 会扫描我们项目中的 bean
该类注解 : A bean definition scanner that detects bean candidates on the classpath, registering corresponding bean definitions with a given registry (BeanFactory or ApplicationContext). Candidate classes are detected through configurable type filters. The default filters include classes that are annotated with Spring's @Component, @Repository, @Service, or @Controller stereotype.
下面我们看一下核心的scan 方法,它的调用栈挺长的,我们只需要知道scan 中会进行 :
- 扫描所有 bean
- 添加几个postprocess(后置处理器)作为 beanDefinition ,方便后续的
@Override public void scan(String... basePackages) { Assert.notEmpty(basePackages, "At least one base package must be specified"); //使用上面构造方法生成的 scan 对象,执行 scan 方法 this.scanner.scan(basePackages); } public int scan(String... basePackages) { int beanCountAtScanStart = this.registry.getBeanDefinitionCount(); doScan(basePackages); // Register annotation config processors, if necessary. if (this.includeAnnotationConfig) { AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry); } return (this.registry.getBeanDefinitionCount() - beanCountAtScanStart); } protected Set<BeanDefinitionHolder> doScan(String... basePackages) { Assert.notEmpty(basePackages, "At least one base package must be specified"); Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>(); for (String basePackage : basePackages) { //这里会把配置文件中的 bean 读取出来,然后进行注册 Set<BeanDefinition> candidates = findCandidateComponents(basePackage); for (BeanDefinition candidate : candidates) { ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate); candidate.setScope(scopeMetadata.getScopeName()); String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry); if (candidate instanceof AbstractBeanDefinition) { //为每个 BeanDefinition 填充作为 BeanDefinition 的属性值 postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName); } if (candidate instanceof AnnotatedBeanDefinition) { AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate); } //检查这个 BeanDefinition 是否一件存在,因为默认是单例,可以想象得到肯定是去 DefaultListableBeanFactory 中判断寻找 if (checkCandidate(beanName, candidate)) { //封装成 BeanDefinitionHolder 对象 BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName); definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry); beanDefinitions.add(definitionHolder); // register 注册 registerBeanDefinition(definitionHolder, this.registry); } } } return beanDefinitions; } protected void registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) { BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, registry); } //BeanDefinitionReaderUtils 类方法 public static void registerBeanDefinition( BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) throws BeanDefinitionStoreException { // Register bean definition under primary name. String beanName = definitionHolder.getBeanName(); //最终调用的是 registry 的 registerBeanDefinition 方法 registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition()); // Register aliases for bean name, if any. String[] aliases = definitionHolder.getAliases(); if (aliases != null) { for (String alias : aliases) { registry.registerAlias(beanName, alias); } } }
ok, scan 方法我们就了解这么多,下篇我们看一下 refresh方法。
总结
该篇文章我们介绍了 AnnotationConfigApplicationContext 的初始化过程,剩下的 refresh 方法将会留到下一篇文章进行讲解。
参考资料
- https://blog.csdn.net/csdn_20150804 (spring5 系列分析)
- https://juejin.im/post/5d7afbc6518825345a05c549 (小分析)
标签:basePackages,String,spring,refresh,public,bean,registry,class 来源: https://www.cnblogs.com/Benjious/p/15077921.html