1、SpringBoot容器启动
版本:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.0.RELEASE</version>
</parent>
1.1.启动容器方法
ConfigurableApplicationContext context = SpringApplication.run(PortalApplication.class, args);
1.2.SpringApplication构造
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
this.resourceLoader = resourceLoader;
Assert.notNull(primarySources, "PrimarySources must not be null");
this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
//推断出是servlet容器还是reactive容器
this.webApplicationType = deduceWebApplicationType();
//设置在应用初始化时的对象
setInitializers((Collection) getSpringFactoriesInstances(
ApplicationContextInitializer.class));
//设置应用的监听器
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
//推断main方法
this.mainApplicationClass = deduceMainApplicationClass();
}
判断容器类型细节
如果包含org.springframework.web.reactive.DispatcherHandler
类并且不包含org.springframework.web.servlet.DispatcherServlet
为reactive服务
包含
javax.servlet.Servlet
org.springframework.web.context.ConfigurableWebApplicationContext
类则为serlvet容器
获取springFactoriesInstances的细节
classpath下的META/spring.factories中配置的各个全路径类名然后
通过SpringFactoriesLoader.loadFactoryNames(type, classLoader)加载到配置的对应实现类class name
再使用BeanUtils.instantiateClass(constructor, args)反射创建对象
推断main方法细节
利用异常中的stackTrace来推断
StackTraceElement[] stackTrace = new RuntimeException().getStackTrace();
for (StackTraceElement stackTraceElement : stackTrace) {
if ("main".equals(stackTraceElement.getMethodName())) {
return Class.forName(stackTraceElement.getClassName());
}
}
1.3.SpringApplication启动
public ConfigurableApplicationContext run(String... args) {
//计时器 用来统计启动时间等
StopWatch stopWatch = new StopWatch();
stopWatch.start();
ConfigurableApplicationContext context = null;
Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
configureHeadlessProperty();
//从spring.factories中获取应用启动监听器
//实现的接口SpringApplicationRunListener,通过构造参数传递SpringApplication以及命令行参数
SpringApplicationRunListeners listeners = getRunListeners(args);
//启动事件
listeners.starting();
try {
//包装命令行参数
ApplicationArguments applicationArguments = new DefaultApplicationArguments(
args);
//准备环境变量
ConfigurableEnvironment environment = prepareEnvironment(listeners,
applicationArguments);
configureIgnoreBeanInfo(environment);
//打印banner
Banner printedBanner = printBanner(environment);
//根据容器类型构造应用上下文对象
context = createApplicationContext();
//从spring.factories中获取对应的SpringBootExceptionReporter并进行实例化
exceptionReporters = getSpringFactoriesInstances(
SpringBootExceptionReporter.class,
new Class[] { ConfigurableApplicationContext.class }, context);
//配置应用上下文对象
prepareContext(context, environment, listeners, applicationArguments,
printedBanner);
//通过refresh来触发对象容器启动
refreshContext(context);
afterRefresh(context, applicationArguments);
stopWatch.stop();
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass)
.logStarted(getApplicationLog(), stopWatch);
}
listeners.started(context);
callRunners(context, applicationArguments);
}
catch (Throwable ex) {
handleRunFailure(context, listeners, exceptionReporters, ex);
throw new IllegalStateException(ex);
}
listeners.running(context);
return context;
}
环境变量细节
如果是servlet容器则使用StandardServletEnvironment
否则使用StandardEnvironment
也可以自定义一个ConfigurableEnvironment
参数优先级
1. 命令行参数
2. 来自于java:comp/env的JNDI属性
3. Java系统属性( System.getProperties())
4. 操作系统环境变量
5. 只有在random.*里包含的属性会产生一个RandomValuePropertySource
6. 在打包的jar外的应用程序配置文件( application.properties, 包含YAML和profile变量)
7. 在打包的jar内的应用程序配置文件( application.properties, 包含YAML和profile变量)
8. 在@Configuration类上的@PropertySource注解
9. 默认属性( 使用SpringApplication.setDefaultProperties指定)
创建的容易对象
一般
org.springframework.context.annotation.AnnotationConfigApplicationContext
web
org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext
reactive
org.springframework.boot.web.reactive.context.AnnotationConfigReactiveWebServerApplicationContext
prepareContext细节
private void prepareContext(ConfigurableApplicationContext context,
ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,
ApplicationArguments applicationArguments, Banner printedBanner) {
//给应用上下文设置环境变量
context.setEnvironment(environment);
postProcessApplicationContext(context);
//调用上面设置的初始化时的对象进行initializer.initialize(context);方法调用
applyInitializers(context);
listeners.contextPrepared(context);
if (this.logStartupInfo) {
logStartupInfo(context.getParent() == null);
logStartupProfileInfo(context);
}
// Add boot specific singleton beans
context.getBeanFactory().registerSingleton("springApplicationArguments",
applicationArguments);
if (printedBanner != null) {
context.getBeanFactory().registerSingleton("springBootBanner", printedBanner);
}
// 根据构造时传入的资源进行资源加载
//可以是类名、包名、或者XML的bean定义资源路径
Set<Object> sources = getAllSources();
Assert.notEmpty(sources, "Sources must not be empty");
//加载资源到context中
load(context, sources.toArray(new Object[0]));
listeners.contextLoaded(context);
}
加载资源细节
根据应用上下文获取到BeanDefinitionRegistry(用来注册扫描到的bean定义)
和资源配置信息来构造出BeanDefinitionLoader loader
然后进行loader.load();加载Bean的定义信息去往BeanDefinitionRegistry中注册
在loader.load();中如果是class类型的会去读取类上面的注解信息,根据注解来解析相关参数再通过AnnotatedBeanDefinitionReader进行
将解析到的BeanDefinition注册到context中
2、构造应用上下文
spring boot中如果是普通的web应用会创建AnnotationConfigServletWebServerApplicationContext作为应用上下文对象
AnnotationConfigServletWebServerApplicationContext的构造方法
public AnnotationConfigServletWebServerApplicationContext() {
//用来处理有spring以及spring支持的ee规范中注解的实现类。
this.reader = new AnnotatedBeanDefinitionReader(this);
//用来组件扫描获取BeanDefinition的实现类
this.scanner = new ClassPathBeanDefinitionScanner(this);
}
2.1.接下来查看spring关于注解解析实现
查看AnnotatedBeanDefinitionReader的构造方法
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry) {
this(registry, getOrCreateEnvironment(registry));
}
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一系列注解实现,用来判断是否满足进行加载处理的条件,不满足则忽略掉不进一步处理。
//比如在spring boot 的autoconfigure模块中一些自动配置的类都是通过@Condition相关的类来进行判断是否自动配置。
this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);
//注册用来处理容器中的spring注解的,注解处理器
AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
}
注解处理器大都是根据spring的xxxPostProcessor来进行实现的。根据注解的性质来决定在对象的哪个阶段进行处理。
下面是registerAnnotationConfigProcessors方法的代码
public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
BeanDefinitionRegistry registry, @Nullable Object source) {
DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
if (beanFactory != null) {
//设置基于@Order注解或者实现Ordered接口的优先级比较器,用来给多实现的依赖对象排序或者获取对象的优先级
if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
}
//设置用来解析需要依赖注入的属性的解析器
if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {
beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
}
}
Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(4);
//注册用来处理配置相关注解的默认对象@Configuration、@Import、@PropertySources、@ComponentScans、@ImportResource、@Bean等等
if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
}
//注册用来处理依赖注入的处理器。包含构造器注入、方法、fields。。。
//默认处理的注解有@Autowired @Value @Inject (JSR-330)
if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
}
//注册验证@Required 的处理器 如果开启验证,而且没有设置注入的对象则抛出BeanInitializationException
if (!registry.containsBeanDefinition(REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(RequiredAnnotationBeanPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
}
// Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor.
//实现@PostConstruct @PreDestroy 生命周期方法以及对@Resource @WebServiceRef @EJB 进行依赖注入的的处理器
if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
}
// Check for JPA support, and if present add the PersistenceAnnotationBeanPostProcessor.
// 处理JPA相关的注解处理器注册
if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition();
try {
def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME,
AnnotationConfigUtils.class.getClassLoader()));
}
catch (ClassNotFoundException ex) {
throw new IllegalStateException(
"Cannot load optional framework class: " + PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, ex);
}
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME));
}
//注册用来@EventListener注解标记方法来实现监听通过容器发布的事件的处理器
//默认是通过ApplicationListenerMethodAdapter 来适配标记方法与ApplicationListener接口。
if (!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME));
}
//注册DefaultEventListenerFactory用来创建上面的ApplicationListenerMethodAdapter来协助完成容器事件总线。
if (!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME));
}
return beanDefs;
}
下面的处理器都可以通过往应用上下文中注册对应的BeanDefinition来去覆盖这里的默认处理器。
2.1.1.处理配置相关注解ConfigurationClassPostProcessor的实现细节
public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPostProcessor,
PriorityOrdered, ResourceLoaderAware, BeanClassLoaderAware, EnvironmentAware {
...
}
查看该类实现的接口可以看到该类实现自BeanDefinitionRegistryPostProcessor
postProcessBeanDefinitionRegistry方法是在所有合适的bean definition都加载完毕后~bean实例化之前时
的一个hook
public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {
/**
* Modify the application context's internal bean definition registry after its
* standard initialization. All regular bean definitions will have been loaded,
* but no beans will have been instantiated yet. This allows for adding further
* bean definitions before the next post-processing phase kicks in.
* @param registry the bean definition registry used by the application context
* @throws org.springframework.beans.BeansException in case of errors
*/
void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;
}
查看ConfigurationClassPostProcessor的实现
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
//不管是否重写了对象的hashCode,只要是同一个对象,都返回相同的hash值
int registryId = System.identityHashCode(registry);
if (this.registriesPostProcessed.contains(registryId)) {
throw new IllegalStateException(
"postProcessBeanDefinitionRegistry already called on this post-processor against " + registry);
}
//保证只会处理一遍
if (this.factoriesPostProcessed.contains(registryId)) {
throw new IllegalStateException(
"postProcessBeanFactory already called on this post-processor against " + registry);
}
this.registriesPostProcessed.add(registryId);
processConfigBeanDefinitions(registry);
}
public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
String[] candidateNames = registry.getBeanDefinitionNames();
for (String beanName : candidateNames) {
BeanDefinition beanDef = registry.getBeanDefinition(beanName);
//这里通过设置检查BeanDefinition中的属性来避免重复处理
if (ConfigurationClassUtils.isFullConfigurationClass(beanDef) ||
ConfigurationClassUtils.isLiteConfigurationClass(beanDef)) {
if (logger.isDebugEnabled()) {
logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
}
}
//检查该BeanDefinition是否符合本处理器处理的范畴,如果符合设置attribute标记防止被重复处理
else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
}
}
// Return immediately if no @Configuration classes were found
if (configCandidates.isEmpty()) {
return;
}
// Sort by previously determined @Order value, if applicable
configCandidates.sort((bd1, bd2) -> {
int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());
int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());
return (i1 < i2) ? -1 : (i1 > i2) ? 1 : 0;
});
// Detect any custom bean name generation strategy supplied through the enclosing application context
SingletonBeanRegistry sbr = null;
if (registry instanceof SingletonBeanRegistry) {
sbr = (SingletonBeanRegistry) registry;
if (!this.localBeanNameGeneratorSet) {
BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton(CONFIGURATION_BEAN_NAME_GENERATOR);
if (generator != null) {
this.componentScanBeanNameGenerator = generator;
this.importBeanNameGenerator = generator;
}
}
}
if (this.environment == null) {
this.environment = new StandardEnvironment();
}
// Parse each @Configuration class
// 构造用来解析处理配置相关注解实例
ConfigurationClassParser parser = new ConfigurationClassParser(
this.metadataReaderFactory, this.problemReporter, this.environment,
this.resourceLoader, this.componentScanBeanNameGenerator, registry);
Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);
Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size());
do {
//开始解析,将根据配置注解解析到对应的配置属性ConfigurationClass
parser.parse(candidates);
parser.validate();
Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());
configClasses.removeAll(alreadyParsed);
// Read the model and create bean definitions based on its content
if (this.reader == null) {
this.reader = new ConfigurationClassBeanDefinitionReader(
registry, this.sourceExtractor, this.resourceLoader, this.environment,
this.importBeanNameGenerator, parser.getImportRegistry());
}
//根据解析到的配置信息作对应的BeanDefinition注册调用等等处理。
this.reader.loadBeanDefinitions(configClasses);
alreadyParsed.addAll(configClasses);
candidates.clear();
//由于处理一轮bean的注解信息之后可能会再产生一批新的BeanDefinition因此,这里需要对新产生的那部分继续循环处理
if (registry.getBeanDefinitionCount() > candidateNames.length) {
String[] newCandidateNames = registry.getBeanDefinitionNames();
Set<String> oldCandidateNames = new HashSet<>(Arrays.asList(candidateNames));
Set<String> alreadyParsedClasses = new HashSet<>();
for (ConfigurationClass configurationClass : alreadyParsed) {
alreadyParsedClasses.add(configurationClass.getMetadata().getClassName());
}
for (String candidateName : newCandidateNames) {
//判断是新增的BeanDefinition 并且是未处理过的 则作为新的一批candidateNames循环处理。
if (!oldCandidateNames.contains(candidateName)) {
BeanDefinition bd = registry.getBeanDefinition(candidateName);
if (ConfigurationClassUtils.checkConfigurationClassCandidate(bd, this.metadataReaderFactory) &&
!alreadyParsedClasses.contains(bd.getBeanClassName())) {
candidates.add(new BeanDefinitionHolder(bd, candidateName));
}
}
}
candidateNames = newCandidateNames;
}
}
while (!candidates.isEmpty());
// Register the ImportRegistry as a bean in order to support ImportAware @Configuration classes
if (sbr != null) {
if (!sbr.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) {
sbr.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry());
}
}
if (this.metadataReaderFactory instanceof CachingMetadataReaderFactory) {
// Clear cache in externally provided MetadataReaderFactory; this is a no-op
// for a shared cache since it'll be cleared by the ApplicationContext.
((CachingMetadataReaderFactory) this.metadataReaderFactory).clearCache();
}
}
通过上面的代码可以看到,spring中的注解是通过这个处理器,在容器中的BeanDefinition注册完毕~实例化之前通过ConfigurationClassParser
进行循环解析这些包含配置相关注解信息的BeanDefinition,去将注解中配置的一些类,或者通过@Bean注解配置的对象等等生成BeanDefinition注册
到容器中。
下面查看ConfigurationClassParser实现细节,看是怎么实现的注解解析。
parser.parse(candidates);
public void parse(Set<BeanDefinitionHolder> configCandidates) {
//需要延后处理的ImportSelector
this.deferredImportSelectors = new LinkedList<>();
for (BeanDefinitionHolder holder : configCandidates) {
BeanDefinition bd = holder.getBeanDefinition();
try {
//获取BeanDefinition中解析到的注解元数据 然后在下面构造出对应的ConfigurationClass对象
//基于注解的BeanDefinition
if (bd instanceof AnnotatedBeanDefinition) {
parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName());
}
//基于Class(下面会通过new StandardAnnotationMetadata(clazz, true)去解析类中的注解元数据)
else if (bd instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) bd).hasBeanClass()) {
parse(((AbstractBeanDefinition) bd).getBeanClass(), holder.getBeanName());
}
//基于类名(下面会通过MetadataReader来读取解析类名对应的类中的注解元数据)
else {
parse(bd.getBeanClassName(), holder.getBeanName());
}
}
catch (BeanDefinitionStoreException ex) {
throw ex;
}
catch (Throwable ex) {
throw new BeanDefinitionStoreException(
"Failed to parse configuration class [" + bd.getBeanClassName() + "]", ex);
}
}
processDeferredImportSelectors();
}
上面主要是想办法从BeanDefinition中获取到注解元数据
下面是处理ConfigurationClass的方法
protected void processConfigurationClass(ConfigurationClass configClass) throws IOException {
//实现@Conditional相关的注解,根据注解配置的条件来判断是否满足而后进一步处理
if (this.conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.PARSE_CONFIGURATION)) {
return;
}
//这部分主要是判断ConfigurationClass是否已经通过其他类导入过了。如果导入过了就直接忽略掉。
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);
this.knownSuperclasses.values().removeIf(configClass::equals);
}
}
// Recursively process the configuration class and its superclass hierarchy.
//这里的处理是为了实现继承关系doProcessConfigurationClass处理完当前类会获取到父类并返回,
//这样就可以通过循环处理完整个 当前类->superclass->superclass->...complete
SourceClass sourceClass = asSourceClass(configClass);
do {
sourceClass = doProcessConfigurationClass(configClass, sourceClass);
}
while (sourceClass != null);
//保存处理过的类
this.configurationClasses.put(configClass, configClass);
}
上面方法主要处理的继承关系层面的问题。具体的处理逻辑在doProcessConfigurationClass方法中
下面查看doProcessConfigurationClass方法的代码
@Nullable
protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass)
throws IOException {
//这里先处理内部类的配置类
// Recursively process any member (nested) classes first
processMemberClasses(configClass, sourceClass);
//这里解析@PropertySources注解属性,然后通过PropertySourceFactory构造出对应的PropertySource<?>对象
//这个主要是用来配置或者拓展容器中environment对象的
// Process any @PropertySource annotations
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");
}
}
//处理@ComponentScans,根据注解上面配置的组件扫描信息来做包扫描获取BeanDefinitions
// Process any @ComponentScan annotations
Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(
sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
//这里判断是否满足注解上面的@Conditional相关的条件
if (!componentScans.isEmpty() &&
!this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
for (AnnotationAttributes componentScan : componentScans) {
//在这里直接进行组件扫描,扫描完会直接注册到应用上下文中
// The config class is annotated with @ComponentScan -> perform the scan immediately
Set<BeanDefinitionHolder> scannedBeanDefinitions =
this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
//这里对新增的这部分BeanDefinition做ConfigurationClass解析,如果不在这里做,
//其他在上面的ConfigurationClassPostProcessor中也会做循环检查的时候也能够检查到并作处理
// Check the set of scanned definitions for any further config classes and parse recursively if needed
for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
if (ConfigurationClassUtils.checkConfigurationClassCandidate(
holder.getBeanDefinition(), this.metadataReaderFactory)) {
parse(holder.getBeanDefinition().getBeanClassName(), holder.getBeanName());
}
}
}
}
//处理@Import注解,getImports(sourceClass)方法是递归收集当前sourceClass上的@Import注解配置的值,
//如果是其他注解会继续递归获取注解中注解的@Import,即收集所有能关联到的@Import注解中的value
//该注解的值分为三类1.ImportSelector的实现类 2.ImportBeanDefinitionRegistrar的实现类 3.一般类(作为普通的需要处理配置注解的类来处理)。
// Process any @Import annotations
processImports(configClass, sourceClass, getImports(sourceClass), true);
//处理@ImportResource注解
// Process any @ImportResource annotations
AnnotationAttributes importResource =
AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);
if (importResource != null) {
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);
}
}
//这里是获取方法中的@Bean,类似xml形式,只不过是通过注解来提供BeanDefinition信息
// Process individual @Bean methods
Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
for (MethodMetadata methodMetadata : beanMethods) {
configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
}
//这里实现的是获取接口中的default方法提供的@Bean注解BeanDefinition信息
// Process default methods on interfaces
processInterfaces(configClass, sourceClass);
//获取superClass交给上面的循环处理父类中的配置注解
// Process superclass, if any
if (sourceClass.getMetadata().hasSuperClass()) {
String superclass = sourceClass.getMetadata().getSuperClassName();
if (superclass != null && !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;
}
上面的方法主要是处理具体各个配置注解的实现。其中@Import实现了通过一般注解来导入@Import注解。
例如:
@GeneralAnnotation
class A {}
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Import(XXX.class)
@intereface GeneralAnnotation{
}
这种是可以解析到GeneralAnnotation上面的@Import并进行处理的。
@PropertySources的处理细节
这个注解主要是对environment的一个补充配置,导入其他配置信息
下面的PropertySource注解中的属性
public @interface PropertySource {
//配置资源的名称
String name() default "";
//资源地址,可以使用占位符
String[] value();
//如果资源未找到是否抛出异常
boolean ignoreResourceNotFound() default false;
//资源编码
String encoding() default "";
//用来创建PropertySource的工厂类,如果不指定则使用org.springframework.core.io.support.DefaultPropertySourceFactory
Class<? extends PropertySourceFactory> factory() default PropertySourceFactory.class;
}
private void processPropertySource(AnnotationAttributes propertySource) throws IOException {
//下面是处理@PropertySource注解的属性
String name = propertySource.getString("name");
if (!StringUtils.hasLength(name)) {
name = null;
}
String encoding = propertySource.getString("encoding");
if (!StringUtils.hasLength(encoding)) {
encoding = null;
}
String[] locations = propertySource.getStringArray("value");
Assert.isTrue(locations.length > 0, "At least one @PropertySource(value) location is required");
boolean ignoreResourceNotFound = propertySource.getBoolean("ignoreResourceNotFound");
Class<? extends PropertySourceFactory> factoryClass = propertySource.getClass("factory");
PropertySourceFactory factory = (factoryClass == PropertySourceFactory.class ?
DEFAULT_PROPERTY_SOURCE_FACTORY : BeanUtils.instantiateClass(factoryClass));
for (String location : locations) {
try {
//根据location以及对象工厂获取对应的Property资源并添加到environment中去,如果已经存在对应的
//Property资源则通过CompositePropertySource来组合拓展
String resolvedLocation = this.environment.resolveRequiredPlaceholders(location);
//这个resourceLoader是通过ConfigurationClassPostProcessor类中的ResourceLoaderAware进行接口注入的,查看应用上下文启动的refresh()方法
//可以知道通过ResourceLoaderAware注入的对象实际是应用上下文对象。
Resource resource = this.resourceLoader.getResource(resolvedLocation);
//将加载到的资源跟environment关联起来
addPropertySource(factory.createPropertySource(name, new EncodedResource(resource, encoding)));
}
catch (IllegalArgumentException | FileNotFoundException | UnknownHostException ex) {
// Placeholders not resolvable or resource not found when trying to open it
if (ignoreResourceNotFound) {
if (logger.isInfoEnabled()) {
logger.info("Properties location [" + location + "] not resolvable: " + ex.getMessage());
}
}
else {
throw ex;
}
}
}
}
@ComponentScans注解处理的细节
该注解的作用于spring XML的 <context:component-scan> 元素一样
组件扫描是通过扫描解析器ComponentScanAnnotationParser类实现的
下面是parse方法的代码
public Set<BeanDefinitionHolder> parse(AnnotationAttributes componentScan, final String declaringClass) {
//构造扫描器对象
ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(this.registry,
componentScan.getBoolean("useDefaultFilters"), this.environment, this.resourceLoader);
//获取注解中配置的nameGenerator并通过反射进行实例化
Class<? extends BeanNameGenerator> generatorClass = componentScan.getClass("nameGenerator");
boolean useInheritedGenerator = (BeanNameGenerator.class == generatorClass);
scanner.setBeanNameGenerator(useInheritedGenerator ? this.beanNameGenerator :
BeanUtils.instantiateClass(generatorClass));
//下面部分都是sanner的一些配置情况
//域模型的代理模式设置,表示这个域模式如果是代理对象是用接口代理(JDK) 还是类代理(CGLIB)
ScopedProxyMode scopedProxyMode = componentScan.getEnum("scopedProxy");
//非默认情况下使用new AnnotationScopeMetadataResolver(scopedProxyMode);
if (scopedProxyMode != ScopedProxyMode.DEFAULT) {
scanner.setScopedProxyMode(scopedProxyMode);
}
else {
//ScopedProxyMode.DEFAULT情况下使用配置的ScopeMetadataResolver
Class<? extends ScopeMetadataResolver> resolverClass = componentScan.getClass("scopeResolver");
scanner.setScopeMetadataResolver(BeanUtils.instantiateClass(resolverClass));
}
//设置要扫描的资源模式,默认是**/*.class
scanner.setResourcePattern(componentScan.getString("resourcePattern"));
//包含过滤器
for (AnnotationAttributes filter : componentScan.getAnnotationArray("includeFilters")) {
for (TypeFilter typeFilter : typeFiltersFor(filter)) {
scanner.addIncludeFilter(typeFilter);
}
}
//不包含过滤器
for (AnnotationAttributes filter : componentScan.getAnnotationArray("excludeFilters")) {
for (TypeFilter typeFilter : typeFiltersFor(filter)) {
scanner.addExcludeFilter(typeFilter);
}
}
//该资源路径下的bean默认的懒加载值
boolean lazyInit = componentScan.getBoolean("lazyInit");
if (lazyInit) {
scanner.getBeanDefinitionDefaults().setLazyInit(true);
}
//要扫面的包
Set<String> basePackages = new LinkedHashSet<>();
String[] basePackagesArray = componentScan.getStringArray("basePackages");
for (String pkg : basePackagesArray) {
String[] tokenized = StringUtils.tokenizeToStringArray(this.environment.resolvePlaceholders(pkg),
ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);
basePackages.addAll(Arrays.asList(tokenized));
}
for (Class<?> clazz : componentScan.getClassArray("basePackageClasses")) {
basePackages.add(ClassUtils.getPackageName(clazz));
}
if (basePackages.isEmpty()) {
basePackages.add(ClassUtils.getPackageName(declaringClass));
}
scanner.addExcludeFilter(new AbstractTypeHierarchyTraversingFilter(false, false) {
@Override
protected boolean matchClassName(String className) {
return declaringClass.equals(className);
}
});
//开始扫描
return scanner.doScan(StringUtils.toStringArray(basePackages));
}
上面代码主要是根据@ComponentSan注解配置对扫描器对象进行配置
下面是组件扫描器对象的扫描细节doScan
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) {
//根据包名以及其他配置信息进行资源扫描解析出对应的BeanDefinition
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) {
postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
}
//处理基于注解的其他属性@Lazy、@Primary、@DependsOn、@Role、@Description。。。
if (candidate instanceof AnnotatedBeanDefinition) {
AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
}
if (checkCandidate(beanName, candidate)) {
//处理代理属性、并注册到应用上下文中
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
//从applyScopedProxyMode这里可以看到spring对象代理对象也是通过Beandefinition进行配置的。
//在创建代理BeanDefinitionHolder的同时也会将原始BeanDefinition进行注册一份,名称为scopedTarget.originalBeanName
definitionHolder =
AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
beanDefinitions.add(definitionHolder);
registerBeanDefinition(definitionHolder, this.registry);
}
}
}
return beanDefinitions;
}
上面代码主要是执行组件扫描,获取到对应包中的BeanDefinition
下面查看@Import的处理细节
@Import的作用类似于spring XML中的<import/>元素
不过这个处理的是:
1.通过指定ImportSelector的实现类导入资源
2.通过指定ImportBeanDefinitionRegistrar的实现类实现自定义的BeanDefinition注册
3.通过指定普通类、接口或者注解的class对象,由ConfigurationClassParser来解析上面的注解信息
private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass,
Collection<SourceClass> importCandidates, boolean checkForCircularImports) throws IOException {
if (importCandidates.isEmpty()) {
return;
}
/*
* 这里实现检察循环导入
* 判断的原理就是利用栈结构在递归处理过程中,对每一个要处理的configClass先进行压栈,这样如果
* 后续解析的configClass已经在栈中存在,而且导入类为当前类,那么则表示为循环导入。
* 下面是个简单的例子:
* @Import(X.class)
* class A{}
* @Import(A.class)
* class X{}
*
*/
if (checkForCircularImports && isChainedImportOnStack(configClass)) {
this.problemReporter.error(new CircularImportProblem(configClass, this.importStack));
}
else {
this.importStack.push(configClass);
try {
for (SourceClass candidate : importCandidates) {
//如果导入的资源是一个ImportSelector的实现类,那么会进行实例化,并调用selectImports方法进行进一步的导入
if (candidate.isAssignable(ImportSelector.class)) {
// Candidate class is an ImportSelector -> delegate to it to determine imports
Class<?> candidateClass = candidate.loadClass();
ImportSelector selector = BeanUtils.instantiateClass(candidateClass, ImportSelector.class);
ParserStrategyUtils.invokeAwareMethods(
selector, this.environment, this.resourceLoader, this.registry);
if (this.deferredImportSelectors != null && selector instanceof DeferredImportSelector) {
//记录需要延迟导入的ImportSelector
this.deferredImportSelectors.add(
new DeferredImportSelectorHolder(configClass, (DeferredImportSelector) selector));
}
else {
String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());
Collection<SourceClass> importSourceClasses = asSourceClasses(importClassNames);
//这里递归调不检查循环导入,是因为导入类还是当前类,不可能会产生循环引用
processImports(configClass, currentSourceClass, importSourceClasses, false);
}
}
//这个是实现根据@Import的配置来注册什么BeanDefinition的接口
//创建完实现类对象,配置到configClass中,在ConfigurationClassPostProcessor中会通过ConfigurationClassBeanDefinitionReader
//实现进行registerBeanDefinitions方法的调用,进行注册Beandefinition。
else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) {
// Candidate class is an ImportBeanDefinitionRegistrar ->
// delegate to it to register additional bean definitions
Class<?> candidateClass = candidate.loadClass();
ImportBeanDefinitionRegistrar registrar =
BeanUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class);
ParserStrategyUtils.invokeAwareMethods(
registrar, this.environment, this.resourceLoader, this.registry);
configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata());
}
else {
//如果是一个一般类或者注解,作为普通的配置类递归处理,这种情况可能会产生循环导入,
//因此在这里记录下这个资源类的导入类,以备循环导入检查使用。
// Candidate class not an ImportSelector or ImportBeanDefinitionRegistrar ->
// process it as an @Configuration class
this.importStack.registerImport(
currentSourceClass.getMetadata(), candidate.getMetadata().getClassName());
processConfigurationClass(candidate.asConfigClass(configClass));
}
}
}
catch (BeanDefinitionStoreException ex) {
throw ex;
}
catch (Throwable ex) {
throw new BeanDefinitionStoreException(
"Failed to process import candidates for configuration class [" +
configClass.getMetadata().getClassName() + "]", ex);
}
finally {
this.importStack.pop();
}
}
}
从上面的代码可以看到spring对注解的注解这种层次关系支持的非常好,这样就可以让我们可以很灵活的组合注解使用,比如需要导入许多资源,
可以自定义一个注解,将那些导入注解打到自己的自定义注解上面。
下面查看@ImportResource的处理细节
该注解的作用于@Import、<import/> 类似 用来导入XML或者.groovy形式BeanDefinition文件的
默认使用GroovyBeanDefinitionReader 处理.groovy文件
默认使用XmlBeanDefinitionReader 是处理.xml文件
对应locations配置同样也支持占位符
// Process any @ImportResource annotations
AnnotationAttributes importResource =
AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);
if (importResource != null) {
String[] resources = importResource.getStringArray("locations");
Class<? extends BeanDefinitionReader> readerClass = importResource.getClass("reader");
for (String resource : resources) {
//占位符替换成实际值
String resolvedResource = this.environment.resolveRequiredPlaceholders(resource);
//待后面通过ConfigurationClassPostProcessor使用ConfigurationClassBeanDefinitionReader来loadBeanDefinition来加载通过该注解导入的资源xml或者.groovy
configClass.addImportedResource(resolvedResource, readerClass);
}
}
下面是@Bean注解方法标记处理细节
@Bean 跟spring XML中的<bean/> 元素是一样的作用
从上面的doProcessConfigurationClass方法中可以看到spring能够处理到当前类 + 接口中默认方法 + 父类中的 @Bean注解
2.1.2.关于AutowiredAnnotationBeanPostProcessor的实现细节
查看该类的继承以及接口信息
1.MergedBeanDefinitionPostProcessor是BeanPostProcessor的子接口,拓展了Bean创建前处理BeanDefinition的回调
2.InstantiationAwareBeanPostProcessorAdapter是一个SmartInstantiationAwareBeanPostProcessor的适配器,
SmartInstantiationAwareBeanPostProcessor的父类是InstantiationAwareBeanPostProcessor的父类是BeanPostProcessor
主要是拓展了Bean实例化时的一些回调。
3.PriorityOrdered
4.BeanFactoryAware
public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter
implements MergedBeanDefinitionPostProcessor, PriorityOrdered, BeanFactoryAware {
...
}
下面查看MergedBeanDefinitionPostProcessor中postProcessMergedBeanDefinition方法的实现
这个方法主要是将BeanDefinition中的依赖注入相关的注解信息解析出来,以备在实例化时进行依赖注入。
@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
//处理依赖注入的元数据信息
InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
metadata.checkConfigMembers(beanDefinition);
}
private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs) {
//检查元数据需不需要创建或者更新
// Fall back to class name as cache key, for backwards compatibility with custom callers.
String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
// Quick check on the concurrent map first, with minimal locking.
InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);
if (InjectionMetadata.needsRefresh(metadata, clazz)) {
synchronized (this.injectionMetadataCache) {
metadata = this.injectionMetadataCache.get(cacheKey);
if (InjectionMetadata.needsRefresh(metadata, clazz)) {
if (metadata != null) {
metadata.clear(pvs);
}
//根据class去构造依赖注入的元数据
metadata = buildAutowiringMetadata(clazz);
this.injectionMetadataCache.put(cacheKey, metadata);
}
}
}
return metadata;
}
private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {
LinkedList<InjectionMetadata.InjectedElement> elements = new LinkedList<>();
Class<?> targetClass = clazz;
do {
final LinkedList<InjectionMetadata.InjectedElement> currElements = new LinkedList<>();
//获取fields上面关于依赖注入的注解信息
ReflectionUtils.doWithLocalFields(targetClass, field -> {
//@Autowired 、@Value 、以及JSR-330中的@Inject
AnnotationAttributes ann = findAutowiredAnnotation(field);
if (ann != null) {
if (Modifier.isStatic(field.getModifiers())) {
if (logger.isWarnEnabled()) {
logger.warn("Autowired annotation is not supported on static fields: " + field);
}
return;
}
//是否必须属性(默认是必须存在)
boolean required = determineRequiredStatus(ann);
currElements.add(new AutowiredFieldElement(field, required));
}
});
//方法上面的依赖注入相关注解处理
ReflectionUtils.doWithLocalMethods(targetClass, method -> {
Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
return;
}
AnnotationAttributes ann = findAutowiredAnnotation(bridgedMethod);
if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
if (Modifier.isStatic(method.getModifiers())) {
if (logger.isWarnEnabled()) {
logger.warn("Autowired annotation is not supported on static methods: " + method);
}
return;
}
if (method.getParameterCount() == 0) {
if (logger.isWarnEnabled()) {
logger.warn("Autowired annotation should only be used on methods with parameters: " +
method);
}
}
boolean required = determineRequiredStatus(ann);
//这里如果方法是read、write方法的话也将对应的javaBean内省信息放到元属性中
PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
currElements.add(new AutowiredMethodElement(method, required, pd));
}
});
elements.addAll(0, currElements);
targetClass = targetClass.getSuperclass();
}
while (targetClass != null && targetClass != Object.class);
return new InjectionMetadata(clazz, elements);
}
下面是解析有效构造方法的回调实现,这个回调是在构造Bean实例时用来确定构造器的
@Override
@Nullable
public Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, final String beanName)
throws BeanCreationException {
...
}
下面是实现依赖注入的方法
通过本处理器处理的是@Autowired注解因此这里面是使用AutowiredFieldElement.inject实现的具体的注入逻辑
@Override
public PropertyValues postProcessPropertyValues(
PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeanCreationException {
//获取实例的依赖注入的元数据信息
InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
try {
//执行依赖注入的逻辑
metadata.inject(bean, beanName, pvs);
}
catch (BeanCreationException ex) {
throw ex;
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex);
}
return pvs;
}
下面是InjectionMetadata中的inject方法。这里是遍历需要执行依赖注入的元素然后通过元素进行注入
public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
Collection<InjectedElement> checkedElements = this.checkedElements;
Collection<InjectedElement> elementsToIterate =
(checkedElements != null ? checkedElements : this.injectedElements);
if (!elementsToIterate.isEmpty()) {
boolean debug = logger.isDebugEnabled();
for (InjectedElement element : elementsToIterate) {
if (debug) {
logger.debug("Processing injected element of bean '" + beanName + "': " + element);
}
element.inject(target, beanName, pvs);
}
}
}
下面是AutowiredFieldElement中inject方法
@Override
protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
Field field = (Field) this.member;
Object value;
if (this.cached) {
value = resolvedCachedArgument(beanName, this.cachedFieldValue);
}
else {
//构造出DependencyDescriptor交给对象工厂来确定要注入的对象
DependencyDescriptor desc = new DependencyDescriptor(field, this.required);
desc.setContainingClass(bean.getClass());
Set<String> autowiredBeanNames = new LinkedHashSet<>(1);
Assert.state(beanFactory != null, "No BeanFactory available");
TypeConverter typeConverter = beanFactory.getTypeConverter();
try {
value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
}
catch (BeansException ex) {
throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex);
}
//处理字段注入的缓存
synchronized (this) {
if (!this.cached) {
if (value != null || this.required) {
this.cachedFieldValue = desc;
registerDependentBeans(beanName, autowiredBeanNames);
if (autowiredBeanNames.size() == 1) {
String autowiredBeanName = autowiredBeanNames.iterator().next();
if (beanFactory.containsBean(autowiredBeanName)) {
if (beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {
this.cachedFieldValue = new ShortcutDependencyDescriptor(
desc, autowiredBeanName, field.getType());
}
}
}
}
else {
this.cachedFieldValue = null;
}
this.cached = true;
}
}
}
if (value != null) {
ReflectionUtils.makeAccessible(field);
field.set(bean, value);
}
}
通过方法注入与fields注入类似
2.1.2.关于RequiredAnnotationBeanPostProcessor的实现细节
这个实现的内容比较简单,在Bean实例化完毕,参数设置完毕之后。
主要是检查如果如果setter上有注解@Required而实例内的对应字段没有值的话,会抛出BeanInitializationException
@Override
public PropertyValues postProcessPropertyValues(
PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
if (!this.validatedBeanNames.contains(beanName)) {
if (!shouldSkip(this.beanFactory, beanName)) {
List<String> invalidProperties = new ArrayList<>();
for (PropertyDescriptor pd : pds) {
if (isRequiredProperty(pd) && !pvs.contains(pd.getName())) {
invalidProperties.add(pd.getName());
}
}
if (!invalidProperties.isEmpty()) {
throw new BeanInitializationException(buildExceptionMessage(invalidProperties, beanName));
}
}
this.validatedBeanNames.add(beanName);
}
return pvs;
}
2.1.2.关于CommonAnnotationBeanPostProcessor的实现细节
该处理器与AutowiredAnnotationBeanPostProcessor类似,只不过是处理关于@Resource、@WebServiceRef、@EJB
注解的依赖注入
实现具体注入逻辑的类分别是ResourceElement、WebServiceRefElement、EjbRefElement
2.1.2.关于EventListenerMethodProcessor的实现细节
该处理器实现了SmartInitializingSingleton接口,
void afterSingletonsInstantiated();
方法是在单例对象实例化之后进行回调的。
@Override
public void afterSingletonsInstantiated() {
List<EventListenerFactory> factories = getEventListenerFactories();
ConfigurableApplicationContext context = getApplicationContext();
String[] beanNames = context.getBeanNamesForType(Object.class);
for (String beanName : beanNames) {
//如果是对象的scope设置为代理方式,会创建一个target对象,这个对象是scopedTarget.xxx的beanName命名
if (!ScopedProxyUtils.isScopedTarget(beanName)) {
Class<?> type = null;
//下面的代码都是获取到目标对象的class对象的处理
try {
type = AutoProxyUtils.determineTargetClass(context.getBeanFactory(), beanName);
}
catch (Throwable ex) {
// An unresolvable bean type, probably from a lazy bean - let's ignore it.
if (logger.isDebugEnabled()) {
logger.debug("Could not resolve target class for bean with name '" + beanName + "'", ex);
}
}
if (type != null) {
if (ScopedObject.class.isAssignableFrom(type)) {
try {
Class<?> targetClass = AutoProxyUtils.determineTargetClass(
context.getBeanFactory(), ScopedProxyUtils.getTargetBeanName(beanName));
if (targetClass != null) {
type = targetClass;
}
}
catch (Throwable ex) {
// An invalid scoped proxy arrangement - let's ignore it.
if (logger.isDebugEnabled()) {
logger.debug("Could not resolve target bean for scoped proxy '" + beanName + "'", ex);
}
}
}
try {
//这里才是真正处理@EventListener的逻辑
processBean(factories, beanName, type);
}
catch (Throwable ex) {
throw new BeanInitializationException("Failed to process @EventListener " +
"annotation on bean with name '" + beanName + "'", ex);
}
}
}
}
}
下面查看processBean(factories, beanName, type);方法
protected void processBean(
final List<EventListenerFactory> factories, final String beanName, final Class<?> targetType) {
if (!this.nonAnnotatedClasses.contains(targetType)) {
Map<Method, EventListener> annotatedMethods = null;
try {
//获取类中带有@EventListener注解标记的方法
//通过查看MethodIntrospector.selectMethods方法可以得知,所有接口中的方法带有@EventListener注解也是有效的。
annotatedMethods = MethodIntrospector.selectMethods(targetType,
(MethodIntrospector.MetadataLookup<EventListener>) method ->
AnnotatedElementUtils.findMergedAnnotation(method, EventListener.class));
}
catch (Throwable ex) {
// An unresolvable type in a method signature, probably from a lazy bean - let's ignore it.
if (logger.isDebugEnabled()) {
logger.debug("Could not resolve methods for bean with name '" + beanName + "'", ex);
}
}
if (CollectionUtils.isEmpty(annotatedMethods)) {
this.nonAnnotatedClasses.add(targetType);
if (logger.isTraceEnabled()) {
logger.trace("No @EventListener annotations found on bean class: " + targetType.getName());
}
}
else {
// Non-empty set of methods
ConfigurableApplicationContext context = getApplicationContext();
for (Method method : annotatedMethods.keySet()) {
//这里的EventListenerFactory是通过应用上下文中根据类型或取的,因此,只要定义了这种类型的接口实现交给spring容器管理,就能参与处理
for (EventListenerFactory factory : factories) {
if (factory.supportsMethod(method)) {
Method methodToUse = AopUtils.selectInvocableMethod(method, context.getType(beanName));
//通过EventListenerFactory构造出ApplicationListener,如果是通过DefaultEventListenerFactory创建的话
//是利用ApplicationListenerMethodAdapter来实现的ApplicationListener接口与注解标记方法的适配。
ApplicationListener<?> applicationListener =
factory.createApplicationListener(beanName, targetType, methodToUse);
if (applicationListener instanceof ApplicationListenerMethodAdapter) {
//ApplicationListenerMethodAdapter实现了@Conditional条件相关的注解,EventExpressionEvaluator是条件相关注解的解析实现。
//这里需要对这个进行初始化设置一下,而context是用来发布ApplicationListener事件的
//在这个方法的实现中会对方法的返回值再次作为容器事件进行发布
((ApplicationListenerMethodAdapter) applicationListener).init(context, this.evaluator);
}
context.addApplicationListener(applicationListener);
break;
}
}
}
if (logger.isDebugEnabled()) {
logger.debug(annotatedMethods.size() + " @EventListener methods processed on bean '" +
beanName + "': " + annotatedMethods);
}
}
}
}
利用@EvenListenter相较基于接口实现类的方式可以更简洁的实现基于容器的消息总线。
另外还可以结合@Asyn注解来实现异步处理事件。
2.1.2.关于DefaultEventListenerFactory
该处理器是spring提供的默认@EventListener的容器监听器的对象工厂。用来创建ApplicationListenerMethodAdapter的