Spring Boot 的核心注解SpringBootApplication引起的探究

星期二, 2019-12-03 | Author: Lee | JAVA-and-J2EE, spring-boot | 1,399 views

Spring Boot 的核心注解SpringBootApplication引起的探究

1.Spring Boot 的核心注解是哪个?

先上一个工程的启动配置项看下:

项目比较老混杂了spring boot,dubbo,jersey注册等

	package com.pomelolee.cms;
 
	import com.ctrip.framework.apollo.spring.annotation.EnableApolloConfig;
	import com.pomelolee.boot.dubbo.annotation.EnableDubboProvider;
	import org.glassfish.jersey.server.ResourceConfig;
	import org.glassfish.jersey.servlet.ServletProperties;
	import org.springframework.beans.factory.config.BeanDefinition;
	import org.springframework.boot.SpringApplication;
	import org.springframework.boot.autoconfigure.SpringBootApplication;
	import org.springframework.boot.builder.SpringApplicationBuilder;
	import org.springframework.boot.web.support.SpringBootServletInitializer;
	import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
	import org.springframework.cloud.netflix.feign.EnableFeignClients;
	import org.springframework.context.annotation.Bean;
	import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
	import org.springframework.context.annotation.ImportResource;
	import org.springframework.util.ClassUtils;
 
	import java.util.HashSet;
	import java.util.Set;
 
	@EnableFeignClients
	@SpringBootApplication
	@EnableApolloConfig
	@EnableDiscoveryClient
	@EnableDubboProvider
	@ImportResource("classpath*:/META-INF/spring/spring-job.xml")
	public class Application extends SpringBootServletInitializer {
	  public static void main(String[] args) {
	    SpringApplication.run(Application.class, args);
	  }
 
	  @Override
	  protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
	    return application.sources(Application.class);
	  }
 
	  @Bean
	  public ResourceConfig resourceConfig() {
	    ResourceConfig resourceConfig = new ResourceConfig();
	    ClassPathScanningCandidateComponentProvider scanner =
	        new ClassPathScanningCandidateComponentProvider(true);
	    Set<BeanDefinition> beanDefinitionSet =
	        scanner.findCandidateComponents("com.pomelolee.cms.service");
	    beanDefinitionSet.addAll(scanner.findCandidateComponents("com.pomelolee.cms.facade"));
	    beanDefinitionSet.addAll(scanner.findCandidateComponents("com.pomelolee.cms.config"));
	    Set<Class<?>> clazzSet = new HashSet<Class<?>>();
	    for (BeanDefinition beanDefinition : beanDefinitionSet) {
	      clazzSet.add(
	          ClassUtils.resolveClassName(
	              beanDefinition.getBeanClassName(), resourceConfig.getClassLoader()));
	    }
	    resourceConfig.registerClasses(clazzSet);
	    resourceConfig.property(ServletProperties.FILTER_FORWARD_ON_404, true);
	    return resourceConfig;
	  }
	}

@SpringBootApplication 注解,就是 Spring Boot 的核心注解。

org.springframework.boot.autoconfigure.@SpringBootApplication 注解的代码如下:

	// SpringBootApplication.java
 
	@Target({ElementType.TYPE})
	@Retention(RetentionPolicy.RUNTIME)
	@Documented
	@Inherited
	@SpringBootConfiguration
	@EnableAutoConfiguration
	@ComponentScan(
	    excludeFilters = {@Filter(
	    type = FilterType.CUSTOM,
	    classes = {TypeExcludeFilter.class}
	), @Filter(
	    type = FilterType.CUSTOM,
	    classes = {AutoConfigurationExcludeFilter.class}
	)}
	)
	public @interface SpringBootApplication {
	    @AliasFor(
	        annotation = EnableAutoConfiguration.class
	    )
	    Class<?>[] exclude() default {};
 
	    @AliasFor(
	        annotation = EnableAutoConfiguration.class
	    )
	    String[] excludeName() default {};
 
	    @AliasFor(
	        annotation = ComponentScan.class,
	        attribute = "basePackages"
	    )
	    String[] scanBasePackages() default {};
 
	    @AliasFor(
	        annotation = ComponentScan.class,
	        attribute = "basePackageClasses"
	    )
	    Class<?>[] scanBasePackageClasses() default {};
	}

它组合了 3 个注解

@Configuration 注解,指定类是 Bean 定义的配置类。

@Configuration 注解,来自 spring-context 项目,用于 Java Config ,不是 Spring Boot 新带来的。

#ComponentScan 注解,扫描指定包下的 Bean 们。

@ComponentScan 注解,来自 spring-context 项目,用于 Java Config ,不是 Spring Boot 新带来的。

@EnableAutoConfiguration 注解,打开自动配置的功能。如果我们想要关闭某个类的自动配置,可以设置注解的 exclude 或 excludeName 属性。

@EnableAutoConfiguration 注解,来自 spring-boot-autoconfigure 项目,它才是 Spring Boot 新带来的。

2.什么是 Spring Boot 自动配置?

上面我们已经看到,使用 @EnableAutoConfiguration 注解,打开 Spring Boot 自动配置的功能。

这个才是自动装配的核心,那些start的启动包都是依赖这个做完成和注入到容器中的,如果你写个start的时候就一切都懂了.

2.1:Spring Boot 在启动时扫描项目所依赖的 jar 包,寻找包含在 META-INF/spring.factories 文件的 jar 包。

2.2:根据 META-INF/spring.factories 配置加载 AutoConfigure 类。

2.3:根据 @Conditional 等条件注解 的条件,进行自动配置并将 Bean 注入 Spring IoC 中。

3.如果自定义frame下的自动注入?

上面提到的注解类:

EnableDubboProvider.java:

	package com.pomelolee.boot.dubbo.annotation;
 
	import java.lang.annotation.Annotation;
	import java.lang.annotation.Documented;
	import java.lang.annotation.Retention;
	import java.lang.annotation.RetentionPolicy;
	import java.lang.annotation.Target;
 
	@Target({java.lang.annotation.ElementType.TYPE})
	@Retention(RetentionPolicy.RUNTIME)
	@Documented
	public @interface EnableDubboProvider {}

此 DubboProviderAutoConfiguration.java 为配置在spring.factories的自动类

	package com.pomelolee.boot.dubbo;
 
	import com.alibaba.dubbo.config.annotation.Service;
	import com.pomelolee.boot.dubbo.annotation.EnableDubboProvider;
	import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
	import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
	import org.springframework.context.annotation.Configuration;
	import org.springframework.context.annotation.ImportResource;
 
	@Configuration
	@ConditionalOnClass({Service.class})
	@ConditionalOnBean(annotation={EnableDubboProvider.class})
	@ImportResource(locations={"classpath*:dubbo/*-provider.xml"})
	public class DubboProviderAutoConfiguration {}

消费者注解类:EnableDubboConsumer.java

	package com.pomelolee.boot.dubbo.annotation;
 
	import java.lang.annotation.Annotation;
	import java.lang.annotation.Documented;
	import java.lang.annotation.Retention;
	import java.lang.annotation.RetentionPolicy;
	import java.lang.annotation.Target;
 
	@Target({java.lang.annotation.ElementType.TYPE})
	@Retention(RetentionPolicy.RUNTIME)
	@Documented
	public @interface EnableDubboConsumer {}

消费者提供者注入类:DubboConsumerAutoConfiguration

	package com.pomelolee.boot.dubbo;
 
	import com.pomelolee.boot.dubbo.annotation.EnableDubboConsumer;
	import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
	import org.springframework.context.annotation.Configuration;
	import org.springframework.context.annotation.ImportResource;
 
	@Configuration
	@ConditionalOnBean(annotation={EnableDubboConsumer.class})
	@ImportResource(locations={"classpath*:dubbo/*-consumer.xml"})
	public class DubboConsumerAutoConfiguration {}

需要加载的配置文件:dubbo/dubbo-provider.xml

	<?xml version="1.0" encoding="UTF-8"?>
	<beans xmlns="http://www.springframework.org/schema/beans"
	       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	       xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
	       xsi:schemaLocation="http://www.springframework.org/schema/beans
	        http://www.springframework.org/schema/beans/spring-beans.xsd
		    http://code.alibabatech.com/schema/dubbo
		    http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
 
	    <dubbo:application name="${spring.application.name}" owner="${dubbo.application.owner}" organization="${dubbo.application.organization}"/>
	    <dubbo:registry protocol="${dubbo.registry.protocol:zookeeper}" client="${dubbo.registry.client:curator}" address="${dubbo.registry.address}"/>
	    <dubbo:protocol name="dubbo" server="netty" port="${dubbo.protocol.port}"/>
	    <!--<dubbo:monitor protocol="registry"/>-->
	    <!--<dubbo:provider filter="DubboExceptionFilter"/>-->
	    <dubbo:annotation package="${dubbo.annotation.package}"/>
	</beans>

需要加载的配置文件:dubbo/dubbo-consumer.xml

	<?xml version="1.0" encoding="UTF-8"?>
	<beans xmlns="http://www.springframework.org/schema/beans"
	       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	       xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
	       xsi:schemaLocation="http://www.springframework.org/schema/beans
	        http://www.springframework.org/schema/beans/spring-beans.xsd
		    http://code.alibabatech.com/schema/dubbo
		    http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
 
	    <dubbo:application name="${spring.application.name}" owner="${dubbo.application.owner}" organization="${dubbo.application.organization}" />
	    <dubbo:registry protocol="${dubbo.registry.protocol:zookeeper}" client="${dubbo.registry.client:curator}" address="${dubbo.registry.address}" />
	    <!--<dubbo:monitor protocol="registry" />-->
	    <dubbo:annotation />
	</beans>

配置启动文件:META-INF/spring.factories

	org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
	com.pomelolee.boot.dubbo.DubboProviderAutoConfiguration,\
	com.pomelolee.boot.dubbo.DubboConsumerAutoConfiguration

配置提供者:ETA-INF/spring.handlers

	http\://code.alibabatech.com/schema/dubbo=com.alibaba.dubbo.config.spring.schema.DubboNamespaceHandler

小结: 以上总结自网络等,如有雷同还望海涵.

Tags: ,

文章作者: Lee

本文地址: https://www.pomelolee.com/1957.html

除非注明,Pomelo Lee文章均为原创,转载请以链接形式标明本文地址

No comments yet.

Leave a comment

Search

文章分类

Links

Meta