整理的灵感:被封号的怪咖凹凸曼
注解源码
bean定义和bean是有区别的
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(MainConfig.class);
AnnotationConfigApplicationContextextends GenericApplicationContext implements AnnotationConfigRegistry
会执行以下方法
public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
//调用本身的两个方法 定义ban信息
this();
//注册bean配置类 MainConfig.class
register(annotatedClasses);
//刷新容器
refresh();
}
步骤拆解
this();会调用本身的构造方法
在构造方法中做了两件事
this.reader = new AnnotatedBeanDefinitionReader(this);
this.scanner = new ClassPathBeanDefinitionScanner(this);
this.reader = new AnnotatedBeanDefinitionReader(this);//获取环境之后创建几个bean 的定义
其中包含了以下七个bean的定义:
/**
* The bean name of the internally managed Configuration annotation processor.
* 内部管理的Configuration注解处理器的Bean名称 rConfigurationClassPostProcessor
*/
public static final String CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME =
"org.springframework.context.annotation.internalConfigurationAnnotationProcessor";
/**
* The bean name of the internally managed Autowired annotation processor.
* 内部管理的Autowired注解处理器的bean名称 AutowiredAnnotationBeanPostProcessor
*/
public static final String AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME =
"org.springframework.context.annotation.internalAutowiredAnnotationProcessor";
/**
* The bean name of the internally managed Required annotation processor.
* 内部管理的Required注释处理器的bean名称。RequiredAnnotationBeanPostProcessor
*/
public static final String REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME =
"org.springframework.context.annotation.internalRequiredAnnotationProcessor";
/**
* The bean name of the internally managed JSR-250 annotation processor.
* 内部管理的 JSR-250注释处理器的bean名称。CommonAnnotationBeanPostProcessor
*/
public static final String COMMON_ANNOTATION_PROCESSOR_BEAN_NAME =
"org.springframework.context.annotation.internalCommonAnnotationProcessor";
/**
* The bean name of the internally managed JPA annotation processor.
* 内部管理的JPA 注释处理器的bean名称。
* 读取以下这个
* private static final String PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME =
"org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor";
* def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME,
AnnotationConfigUtils.class.getClassLoader()));
*/
public static final String PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME =
"org.springframework.context.annotation.internalPersistenceAnnotationProcessor";
/**
* The bean name of the internally managed @EventListener annotation processor.
* 内部管理的@EventListener 注释处理器的bean名称。EventListenerMethodProcessor
*/
public static final String EVENT_LISTENER_PROCESSOR_BEAN_NAME =
"org.springframework.context.event.internalEventListenerProcessor";
/**
* The bean name of the internally managed EventListenerFactory.
* 内部管理的EventListenerFactory的bean名称。DefaultEventListenerFactory
*/
public static final String EVENT_LISTENER_FACTORY_BEAN_NAME =
"org.springframework.context.event.internalEventListenerFactory";
this.scanner = new ClassPathBeanDefinitionScanner(this);中比较重要的就是注册了几个bean的过滤器
Component
javax.annotation.ManagedBean
javax.inject.Named
说白了就是注册具有@Component元注释的所有注释,包括@ Repository,@ Service和@Controller构造型注释
另外做几个补充:
实现 ApplicationListener 监听接口,可以在refresh刷新容器过程中(初始化应用程序事件多播器和初始化监听器之后)利用观察者模式监听到发出来的信息。
实现BeanFactoryPostProcessor 接口 beanFactory后置处理器 可以在beanFactory创建完成之后,bean实例话之前对bean的初始化信息做修改
实现BeanDefinitionRegistryPostProcessor 接口 Bean定义注册表后处理器 可以在bean定义没有加载之前,自己做加入。
refresh()刷新容器原理:
// Prepare this context for refreshing.
//上下文刷新准备
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
//告诉子类刷新内部bean工厂
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
//配置工厂的标准上下文特征,例如上下文的ClassLoader和后处理器
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
//在标准初始化之后,修改应用程序上下文的内部bean工厂。所有bean定义都将被加载,但是还没有实例化bean *。这允许在某些ApplicationContext实现中注册特殊* BeanPostProcessors等
//目前方法没有明确实现
postProcessBeanFactory(beanFactory);
在这里调用invokeBeanFactoryPostProcessors方法,进行装载bean定义信息。
调用PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());方法,意思是在bean工厂的后置处理器,开始加载bean定义。
从下面可以看出这里从工厂中取出了在之前放到里面的一个org.springframework.context.annotation.internalConfigurationAnnotationProcessor
结合上面的代码定义得出这是个解析Configuration的定义。先进行排序,之后放入registryProcessors中
简单复述一下这里的逻辑,首先去获取实现了PriorityOrdered接口的 返回的值越小优先级越高
根据接口返回值做一个排序
在获取实现了Ordered接口的
根据返回值做排序
最后获取普通的
这里是处理BeanDefinitionRegistryPostProcessors 实现了这个接口的都会在这里被处理
因为一开是进入的时候有几个注解 org.springframework.context.annotation.internalConfigurationAnnotationProcessor
这个实现了BeanDefinitionRegistryPostProcessors接口 且优先级最高 所以会调用实现方法 就开始加载config注解下的定义信息
接着开始加载BeanFactoryPostProcessors ,跟上面的逻辑是一样的
BeanDefinitionRegistryPostProcessor继承了BeanFactoryPostProcessor接口 所以实现BeanDefinitionRegistryPostProcessor的类 这里也会被处理
可以看出这里循环调用postProcessor.postProcessBeanDefinitionRegistry(registry);方法
从注册表中的配置类派生更多的Bean定义
接着哈希出一个int值,判断注册后处理的集合是否存在。判断工厂后置处理中是否存在,不存在则加入。
最后调用 processConfigBeanDefinitions(registry); 方法,开始正式基于@Configuration处理bean定义
这里我们发现开始解析已经存在的一些bean定义,我们之前在refresh()方法加载之前,加载了七个bean定义和一个配置类
这里取出之后判断是否是配置类,并检查是否为配置类。会发现只有一个mainconfig 是(我们加了config注解),并new Bean定义持有人 (BeanDefinitionHolder)放入集合中
下面代码就是生成bean名称(没太仔细看,不太关注)有时间在看
接着看到根据环境 配置解读器和名称生成器等对象创建了一个parser对象(解析config对象)
接着调用了parse方法 非常非常重要的一步!!!
这里就不截屏了 先是循环获取到bean定义信息,然后判断是否是注解形式。接着重载parse方法
调用processConfigurationClass方法 传入ConfigurationClass对象(根据注解原信息和beanname构建)注解原信息我们指放在maincofig上的注解
直接上代码
protected void processConfigurationClass(ConfigurationClass configClass) throws IOException {
if (this.conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.PARSE_CONFIGURATION)) {
return;
}
//进入方方法从本身的的集合中尝试获取配置类,这里获取判null,我们第一次进入 肯定是没有的
ConfigurationClass existingClass = this.configurationClasses.get(configClass);
if (existingClass != null) {
if (configClass.isImported()) {
if (existingClass.isImported()) {
existingClass.mergeImportedBy(configClass);
}
// Otherwise ignore new imported config class; existing non-imported class overrides it.
return;
}
else {
// Explicit bean definition found, probably replacing an import.
// Let's remove the old one and go with the new one.
this.configurationClasses.remove(configClass);
for (Iterator<ConfigurationClass> it = this.knownSuperclasses.values().iterator(); it.hasNext();) {
if (configClass.equals(it.next())) {
it.remove();
}
}
}
}
//开始递归处理配置类及其超类层次结构
//得到SourceClass
SourceClass sourceClass = asSourceClass(configClass);
do {
//核心方法
sourceClass = doProcessConfigurationClass(configClass, sourceClass);
}
while (sourceClass != null);
this.configurationClasses.put(configClass, configClass);
}
开始进入doProcessConfigurationClass方法,spring有个特别好玩的地方,就是做事的方法都有个do
可以看出下面很重要了
总结:处理几个注解,bean ComponentScan bean注解只加入到集合 不定义 ComponentScan直接扫描到定义
protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass)
throws IOException {
// Recursively process any member (nested) classes first
processMemberClasses(configClass, sourceClass);
// 处理 @PropertySource 注解 我们没用过,也没加直接忽略
for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(
sourceClass.getMetadata(), PropertySources.class,
org.springframework.context.annotation.PropertySource.class)) {
if (this.environment instanceof ConfigurableEnvironment) {
processPropertySource(propertySource);
}
else {
logger.warn("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() +
"]. Reason: Environment must implement ConfigurableEnvironment");
}
}
// 处理 @ComponentScan 注解,这个有,获取到注解信息。比如我们配置的value值
Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(
sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
if (!componentScans.isEmpty() &&
!this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
//开始循环获取到的所有的注解
for (AnnotationAttributes componentScan : componentScans) {
// 这里获取到所有的扫描到的子bean定义
Set<BeanDefinitionHolder> scannedBeanDefinitions =
this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
// 这里获取到所有的子定义循环
for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();
if (bdCand == null) {
bdCand = holder.getBeanDefinition();
}
//检查配置 类是否继续含有Component ComponentScan Import ImportResource注解 有的话再滚去解析一遍
//知道将所有的底解析完 不在含有这几个注解 @controller@ service 这些都得在这个地方再进去解析
if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
//开始接着解析
parse(bdCand.getBeanClassName(), holder.getBeanName());
}
}
}
}
// 这个方法用栈处理 @Import 注解 判断是否是ImportSelector 这个好像是boot自动装配的核心 ImportBeanDefinitionRegistrar 我们这里都不是
//那就把他当作@Configuration处理 指定的bean没有被定义 除非你指定的bean还有controller server import等注解
processImports(configClass, sourceClass, getImports(sourceClass), true);
// Process any @ImportResource annotations 用的不多
if (sourceClass.getMetadata().isAnnotated(ImportResource.class.getName())) {
AnnotationAttributes importResource =
AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);
String[] resources = importResource.getStringArray("locations");
Class<? extends BeanDefinitionReader> readerClass = importResource.getClass("reader");
for (String resource : resources) {
String resolvedResource = this.environment.resolveRequiredPlaceholders(resource);
configClass.addImportedResource(resolvedResource, readerClass);
}
}
// Process individual @Bean methods bean注解 扫面出来方法 放入集合
Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
for (MethodMetadata methodMetadata : beanMethods) {
configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
}
// Process default methods on interfaces
processInterfaces(configClass, sourceClass);
// Process superclass, if any 不知道干啥
if (sourceClass.getMetadata().hasSuperClass()) {
String superclass = sourceClass.getMetadata().getSuperClassName();
if (!superclass.startsWith("java") && !this.knownSuperclasses.containsKey(superclass)) {
this.knownSuperclasses.put(superclass, configClass);
// Superclass found, return its annotation metadata and recurse
return sourceClass.getSuperClass();
}
}
// No superclass -> processing is complete
return null;
}
componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());方法调用之后就是一顿赋值 不细看了 最后调用一个doscan方法出入了包名 得知是componentScan注解的value的值
protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
Assert.notEmpty(basePackages, "At least one base package must be specified");
Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<BeanDefinitionHolder>();
for (String basePackage : basePackages) {
//这个方法也很好玩 查找候选组件 拼接路径 查看文件是否可读 扫到含有component的注解的类定义成bean定义
Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
for (BeanDefinition candidate : candidates) {
//解析元数据
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
//设置单例
candidate.setScope(scopeMetadata.getScopeName());
//生成bean名称
String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
if (candidate instanceof AbstractBeanDefinition) {
postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
}
if (candidate instanceof AnnotatedBeanDefinition) {
AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
}
//检查是否已存在bean名称等
if (checkCandidate(beanName, candidate)) {
//就是注册bean定义
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
definitionHolder =
AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
beanDefinitions.add(definitionHolder);
registerBeanDefinition(definitionHolder, this.registry);
}
}
}
return beanDefinitions;
}
整体出来后进入这个方法
去上面找找 整理整理逻辑 不行就自己再debug
this.reader.loadBeanDefinitions(configClasses);开始进入这个方法
可以看出下图 我们的bean模型都出来 但是通过import指定的service类没有beanName 而且缺少了一个用@bean注解定义的dao类接着看
private void loadBeanDefinitionsForConfigurationClass(
ConfigurationClass configClass, TrackedConditionEvaluator trackedConditionEvaluator) {
if (trackedConditionEvaluator.shouldSkip(configClass)) {
String beanName = configClass.getBeanName();
if (StringUtils.hasLength(beanName) && this.registry.containsBeanDefinition(beanName)) {
this.registry.removeBeanDefinition(beanName);
}
this.importRegistry.removeImportingClass(configClass.getMetadata().getClassName());
return;
}
//判断是否是import导入的 没有名字的service类在这里正式定义到工厂中 定义不是注册
if (configClass.isImported()) {
registerBeanDefinitionForImportedConfigurationClass(configClass);
}
for (BeanMethod beanMethod : configClass.getBeanMethods()) {
//这里加载通过bean注解的
//设置名称 默认以方法名称起名
//设置init和销毁方法 有默认的
//设置注入方式 代理等东西注册定义到bean工厂
loadBeanDefinitionsForBeanMethod(beanMethod);
}
loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());
loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
}
到现在位置@config注解注册bean定义过程结束,只是定义 还没有注册