##Spring 注解##java
在springboot环境中,只须要写一个main方法再加上***@SpringBootApplication***,运行main方法就能启动服务器了,那它究竟是怎么工做的?web
探究一下spring boot里面注解是怎么工做的spring
注解的加载springboot
按照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.AnnotationConfigEmbeddedWebApplicationContextapp
//经过反射生成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的构造方法post
public AnnotationConfigEmbeddedWebApplicationContext() { //看字面意思是,将声明的注解加载到容器中 this.reader = new AnnotatedBeanDefinitionReader(this); this.scanner = new ClassPathBeanDefinitionScanner(this); }
早AnnotatedBeanDefinitionReader类中,ui
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)**相关的注解加载到容器里面,this
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(
上面的方法的做用是,判断几个关键的注解处理器是否存在容器中,若是不存在,则将对应的处理器添加到容器里面。lua
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的启动分为两个部分。
一、spring boot必需组件的加载
二、客户端代码的加载
在上述启动成功后,客户端的组件经过@SpringBootConfiguration@EnableAutoConfiguration加载到容器中,它们的注解处理器在第一步已经声明了。