SpringBoot 自动装配原理

根据之前的学习,在搭建springboot项目时,我们可以简化很多配置。那springboot是如何做到的呢?

首先我们来看JAVA WEB的启动过程
点这里

web项目需要部署容器(tomcat\weblogic等),容器会首先加载web项目中的 web.xml文件。

项目的启动顺序首先是context-param,接着是listener,在接下来是filter,最后才是servlet。
知识点 过滤器和拦截器

在这里插入图片描述

SpringMVC
springmvc的启动过程也是基于上述过程。

tomcat容器 会将读取到<context-param>转化为键值对,并交给ServletContext(上下文) ,供整个WEB项目使用

 <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:applicationContext-*.xml</param-value>
  </context-param>

在执行玩上下文加载后会建立监听,ServletContextListener作为监听类的根接口contextInitialized,contextDestroyed两个方法。

 <!--监听器-->
  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>

而 ContextLoaderListener 重写了 contextInitialized 方法

@Override
	public void contextInitialized(ServletContextEvent event) {
		initWebApplicationContext(event.getServletContext());
	}

初始化Web应用上下文,initWebApplicationContext中调用configureAndRefreshWebApplicationContext对IoC容器的配置和刷新操作。

该方法主要用于创建并初始化contextConfigLocation类配置的xml文件中的Bean,因此,如果我们在配置Bean时出错,在Web应用启动时就会抛出异常,而不是等到运行时才抛出异常。

filter初始化
servlet初始化
常用DispatcherServlet类,DispatcherServlet类间接父类实现了Servlet接口,创建一个IOC子容器,并加载<servlet>标签的<init-param>配置的xml文件并加载相关Bean。

SpringBoot的启动过程
spring boot

我们来看springboot的启动类

@SpringBootApplication
@Slf4j
public class Application
{


  public static void main(String[] args)
  {
    log.info("=================开始成功=================");
    SpringApplication.run(Application.class, args);
    log.info("=================启动成功=================");
  }

@SpringBootApplication注解是springboot启动的开始,我们来看看

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class))
public @interface SpringBootApplication {
	Class<?>[] exclude() default {};
	String[] excludeName() default {};

	@AliasFor(annotation = ComponentScan.class, attribute = "basePackages")
	String[] scanBasePackages() default {};

	@AliasFor(annotation = ComponentScan.class, attribute = "basePackageClasses")
	Class<?>[] scanBasePackageClasses() default {};
}

@SpringBootConfiguration、@EnableAutoConfiguration、@ComponentScan 是其中最重要的三个注解

@SpringBootConfiguration 注解
@SpringBootConfiguration其实就是@Configuration,熟悉spring的都知道,@Configuration 是一个类级注释,指示对象是一个bean定义的源。@Configuration 类通过 @bean 注解的公共方法声明bean。减少xml配置。

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration
public @interface SpringBootConfiguration {
}

例如:

<beans> 
        <bean id="orderService" class="com.acme.OrderService"/> 
                <constructor-arg ref="orderRepository"/> 
        </bean> 
        <bean id="orderRepository" class="com.acme.OrderRepository"/> 
                <constructor-arg ref="dataSource"/> 
        </bean> 
</beans> 

使用@Configuration

@Configuration 
public class ApplicationConfig { 
   
        public @Bean OrderService orderService() { 
                return new OrderService(orderRepository()); 
        } 
   
        public @Bean OrderRepository orderRepository() { 
                return new OrderRepository(dataSource()); 
        } 
   
        public @Bean DataSource dataSource() { 
        } 
} 

@ComponentScan告诉Spring 哪个packages 的用注解标识的类 会被spring自动扫描并且装入bean容器。

@EnableAutoConfiguration
点这里

@AutoConfigurationPackage
@Import(EnableAutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {

	String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";

	Class<?>[] exclude() default {};
	String[] excludeName() default {};
}

@EnableAutoConfiguration让Spring Boot根据类路径的jar包依赖为当前项目进行自动化配置。

例如,添加了spring-boot-starter-web依赖,会自动添加Tomcat和Spring MVC的依赖,那么Spring Boot会对Tomcat和Spring MVC进行自动配置。

又如,添加了spring-boot-starter-data-jpa依赖,Spring Boot会自动进行JPA相关的配置。

进入@EnableAutoConfiguration
在这里插入图片描述

查看getCandidateConfigurations方法

protected List<String> getCandidateConfigurations(AnnotationMetadata metadata,
			AnnotationAttributes attributes) {
		List<String> configurations = SpringFactoriesLoader.loadFactoryNames(
				getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader());
		Assert.notEmpty(configurations,
				"No auto configuration classes found in META-INF/spring.factories. If you "
						+ "are using a custom packaging, make sure that file is correct.");
		return configurations;
	}

SpringFactoriesLoader.loadFactoryNames加载META-INF/spring.factories文件中jar文件

例如spring-boot-1.4.2.RELEASE.jar 中的META-INF/spring.factories

org.springframework.boot.env.PropertySourceLoader=\
org.springframework.boot.env.PropertiesPropertySourceLoader,\
org.springframework.boot.env.YamlPropertySourceLoader

# Run Listeners
org.springframework.boot.SpringApplicationRunListener=\
org.springframework.boot.context.event.EventPublishingRunListener

# Application Context Initializers
org.springframework.context.ApplicationContextInitializer=\
org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer,\
org.springframework.boot.context.ContextIdApplicationContextInitializer,\
org.springframework.boot.context.config.DelegatingApplicationContextInitializer,\
org.springframework.boot.context.web.ServerPortInfoApplicationContextInitializer

# Application Listeners
org.springframework.context.ApplicationListener=\
org.springframework.boot.ClearCachesApplicationListener,\
org.springframework.boot.builder.ParentContextCloserApplicationListener,\
org.springframework.boot.context.FileEncodingApplicationListener,\
org.springframework.boot.context.config.AnsiOutputApplicationListener,\
org.springframework.boot.context.config.ConfigFileApplicationListener,\
org.springframework.boot.context.config.DelegatingApplicationListener,\
org.springframework.boot.liquibase.LiquibaseServiceLocatorApplicationListener,\
org.springframework.boot.logging.ClasspathLoggingApplicationListener,\
org.springframework.boot.logging.LoggingApplicationListener

# Environment Post Processors
org.springframework.boot.env.EnvironmentPostProcessor=\
org.springframework.boot.cloud.CloudFoundryVcapEnvironmentPostProcessor,\
org.springframework.boot.env.SpringApplicationJsonEnvironmentPostProcessor

# Failure Analyzers
org.springframework.boot.diagnostics.FailureAnalyzer=\
org.springframework.boot.diagnostics.analyzer.BeanCurrentlyInCreationFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.BeanNotOfRequiredTypeFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.BindFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.ConnectorStartFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.NoUniqueBeanDefinitionFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.PortInUseFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.ValidationExceptionFailureAnalyzer

# FailureAnalysisReporters
org.springframework.boot.diagnostics.FailureAnalysisReporter=\
org.springframework.boot.diagnostics.LoggingFailureAnalysisReporter

我们在springmvc中使用redis
spring+redis

需要配置一些bean,如:

   <!-- redis template definition -->
    <bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
        <property name="connectionFactory" ref="jedisConnectionFactory" />
        <property name="keySerializer">
            <bean class="org.springframework.data.redis.serializer.StringRedisSerializer" />
        </property>
        <property name="valueSerializer">
            <bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer" />
        </property>
        <property name="hashKeySerializer">
            <bean class="org.springframework.data.redis.serializer.StringRedisSerializer" />
        </property>
        <property name="hashValueSerializer">
            <bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer" />
        </property>
         <!--开启事务  -->  
        <property name="enableTransactionSupport" value="true"></property>  
    </bean>

才可以使用

@Autowired 
    public RedisTemplate redisTemplate;

在springboot中
可以直接从容器中拿去RedisTemplate bean对象
在spring-boot-autoconfigure依赖包中有一个spring.factories文件
在这里插入图片描述

查看 这个RedisAutoConfiguration类

		@Bean
		@ConditionalOnMissingBean(StringRedisTemplate.class)
		public StringRedisTemplate stringRedisTemplate(
				RedisConnectionFactory redisConnectionFactory)
						throws UnknownHostException {
			StringRedisTemplate template = new StringRedisTemplate();
			template.setConnectionFactory(redisConnectionFactory);
			return template;
		}
发布了29 篇原创文章 · 获赞 12 · 访问量 1万+
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 大白 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览