##Spring 注解##
在springboot环境中,只需要写一个main方法再加上***@SpringBootApplication***,运行main方法就能启动服务器了,那它到底是怎么工作的?
探究一下spring boot里面注解是怎么工作的
1.Spring Boot的启动过程
注解的加载
按照Spring Boot启动的一步一步分析,最主要的是进到这个方法。
public ConfigurableApplicationContext run(String... args) {
// 省下部分代码,以下代码是将一些必要的组件加载到容器中
context = createApplicationContext();
//.......
return context;
}
catch (Throwable ex) {
handleRunFailure(context, listeners, analyzers, ex);
throw new IllegalStateException(ex);
}
}
org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext
//通过反射生成ApplicationContext对象,返回的对象实例是:
//org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext
protected ConfigurableApplicationContext createApplicationContext() {
Class<?> contextClass = this.applicationContextClass;
if (contextClass == null) {
try {
contextClass = Class.forName(this.webEnvironment
? DEFAULT_WEB_CONTEXT_CLASS : DEFAULT_CONTEXT_CLASS);
}
catch (ClassNotFoundException ex) {
throw new IllegalStateException(
"Unable create a default ApplicationContext, "
+ "please specify an ApplicationContextClass",
ex);
}
}
//通过反射生成对应的实例
return (ConfigurableApplicationContext) BeanUtils.instantiate(contextClass);
}
进到AnnotationConfigEmbeddedWebApplicationContext的构造方法
public AnnotationConfigEmbeddedWebApplicationContext() {
//看字面意思是,将声明的注解加载到容器中
this.reader = new AnnotatedBeanDefinitionReader(this);
this.scanner = new ClassPathBeanDefinitionScanner(this);
}
早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;
this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);
AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
}
最终起作用的是 registerAnnotationConfigProcessors,从注释中可以看到他会将与**registry(AnnotationConfigEmbeddedWebApplicationContext)**相关的注解加载到容器里面,
public static void registerAnnotationConfigProcessors(BeanDefinitionRegistry registry) {
registerAnnotationConfigProcessors(registry, null);
}
/**
* Register all relevant annotation post processors in the given registry.
* @param registry the registry to operate on
* @param source the configuration source element (already extracted)
* that this registration was triggered from. May be {@code null}.
* @return a Set of BeanDefinitionHolders, containing all bean definitions
* that have actually been registered by this call
*/
public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
上面的方法的作用是,判断几个关键的注解处理器是否存在容器中,如果不存在,则将对应的处理器添加到容器里面。
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));
}
这些处理类分别是:
public static final String CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME =
"org.springframework.context.annotation.internalConfigurationAnnotationProcessor";
public static final String CONFIGURATION_BEAN_NAME_GENERATOR =
"org.springframework.context.annotation.internalConfigurationBeanNameGenerator";
public static final String AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME =
"org.springframework.context.annotation.internalAutowiredAnnotationProcessor";
public static final String REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME =
"org.springframework.context.annotation.internalRequiredAnnotationProcessor";
public static final String COMMON_ANNOTATION_PROCESSOR_BEAN_NAME =
"org.springframework.context.annotation.internalCommonAnnotationProcessor";
public static final String PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME =
"org.springframework.context.annotation.internalPersistenceAnnotationProcessor";
private static final String PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME =
"org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor";
/**
* The bean name of the internally managed @EventListener annotation processor.
*/
public static final String EVENT_LISTENER_PROCESSOR_BEAN_NAME =
"org.springframework.context.event.internalEventListenerProcessor";
/**
* The bean name of the internally managed EventListenerFactory.
*/
public static final String EVENT_LISTENER_FACTORY_BEAN_NAME =
"org.springframework.context.event.internalEventListenerFactory";
private static final boolean jsr250Present =
ClassUtils.isPresent("javax.annotation.Resource", AnnotationConfigUtils.class.getClassLoader());
private static final boolean jpaPresent =
ClassUtils.isPresent("javax.persistence.EntityManagerFactory", AnnotationConfigUtils.class.getClassLoader()) &&
ClassUtils.isPresent(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, AnnotationConfigUtils.class.getClassLoader());
进行上面操作后,添加了如下的注解处理器到容器中了
result = {LinkedHashSet@2388} size = 6
0 = {DelegatingApplicationContextInitializer@2349}
1 = {ContextIdApplicationContextInitializer@2350}
2 = {ConfigurationWarningsApplicationContextInitializer@2351}
3 = {ServerPortInfoApplicationContextInitializer@2352}
4 = {SharedMetadataReaderFactoryContextInitializer@2353}
5 = {AutoConfigurationReportLoggingInitializer@2354}
以上的步骤是将spring boot(SpringApplication类)运行所需要的组件加载到容器中,这一步完成后。加载用户所写的main方法。
这一块是加载客户代码。拿到代码标注注解的实际处理器
// Load the sources
//返回springboot的启动类
Set<Object> sources = getSources();
Assert.notEmpty(sources, "Sources must not be empty");
load(context, sources.toArray(new Object[sources.size()]));
listeners.contextLoaded(context);
将启动类加载到容器中
其中框红的部分是通过BeanDefinitionLoader 来获取启动类中用到注解的处理器。
这样就这个容器的启动接完成了,总的来说,spring boot的启动分为两个部分。
1、spring boot必需组件的加载
2、客户端代码的加载
2.Spring 客户端代码加载
在上述启动成功后,客户端的组件通过@SpringBootConfiguration@EnableAutoConfiguration加载到容器中,它们的注解处理器在第一步已经声明了。