这篇文章我们将会 注解式生成bean的过程,总的来说就是 :
public static void main(String[] args) {
AnnotationConfigApplicationContext consumerContext = new AnnotationConfigApplicationContext();
//这里看到我们注册了一个 configuration 的类进行配置,然后刷新一下容器得到最新的结果
consumerContext.register(ConsumerConfiguration.class);
consumerContext.refresh();
//从容器中获取类
FooServiceConsumer service = consumerContext.getBean(FooServiceConsumer.class);
...
}
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 的加载和创建
构造方法很清晰 : 初始化,扫描,刷新三个步骤。
public AnnotationConfigApplicationContext(String... basePackages) {
//初始化
this();
//扫描包
scan(basePackages);
//刷新
refresh();
}
需要知道的类 :
以 AnnotationConfigApplicationContext 为例子,查看类图主要包含三个类型的接口
AnnotationConfigApplicationContext 的初始化创建的两个类作用如下 :
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 中会进行 :
@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://www.cnblogs.com/Benjious/p/15077921.html