springboot之启动原理解析
题目标签
学习时常:20分钟
题目难度:中级
知识点标签:springboot
产生原因
以往的项目整合起来是比较繁琐复杂的,而且存在架包冲突的问题,这时候SpringBoot应运而生了。
SpringBootApplication背后的秘密
我们开发任何一个Spring Boot项目,都会用到如下的启动类
要揭开SpringBoot的神秘面纱,我们从Annotation定义(@SpringBootApplication)和类定义
(SpringApplication.run)入手。
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
虽然定义使用了多个Annotation进行了原信息标注,但实际上重要的只有三个Annotation:
@Configuration(@SpringBootConfiguration点开查看发现里面还是应用了@Configuration)
@EnableAutoConfiguration
@ComponentScan
即 @SpringBootApplication = (默认属性)@Configuration + @EnableAutoConfiguration +
@ComponentScan。
所以,如果我们使用如下的SpringBoot启动类,整个SpringBoot应用依然可以与之前的启动类功能对
等:
分别介绍这3个Annotation
1、@Configuration
这里的@Configuration对我们来说不陌生,它就是JavaConfig形式的Spring Ioc容器的配置类使用的那
个@Configuration,SpringBoot社区推荐使用基于JavaConfig的配置形式,所以,这里的启动类标注
了@Configuration之后,本身其实也是一个IoC容器的配置类。
举几个简单例子回顾下,XML跟config配置方式的区别:
表达形式层面
基于XML配置的方式是这样:
@Target(ElementType.TYPE) // 注解的适用范围,其中TYPE用于描述类、接口(包括包注解类型)
或enum声明
@Retention(RetentionPolicy.RUNTIME) // 注解的生命周期,保留到class文件中(三个生命周
期)
@Documented // 表明这个注解应该被javadoc记录
@Inherited // 子类可以继承该注解
@SpringBootConfiguration // 继承了Configuration,表示当前是注解类
@EnableAutoConfiguration // 开启springboot的注解功能,springboot的四大神
器之一,其 //借助@import的帮助
@ComponentScan(excludeFilters = { // 扫描路径设置(具体使用待确认)
@Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes =
AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
...
}
@Configuration
@EnableAutoConfiguration
@ComponentScan
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
而基于JavaConfig的配置方式是这样:
任何一个标注了@Configuration的Java类定义都是一个JavaConfig配置类。
注册bean定义层面
基于XML的配置形式是这样:
而基于JavaConfig的配置形式是这样的:
任何一个标注了@Bean的方法,其返回值将作为一个bean定义注册到Spring的IoC容器,方法名将默认
成该bean定义的id。
表达依赖注入关系层面
为了表达bean与bean之间的依赖关系,在XML形式中一般是这样:
而基于JavaConfig的配置形式是这样的:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"
default-lazy-init="true">
<!--bean定义-->
</beans>
@Configuration
public class MockConfiguration{
//bean定义
}
<bean id="mockService" class="..MockServiceImpl">
...
</bean>
@Configuration
public class MockConfiguration{
@Bean
public MockService mockService(){
return new MockServiceImpl();
}
}
<bean id="mockService" class="..MockServiceImpl">
<propery name ="dependencyService" ref="dependencyService" />
</bean>
<bean id="dependencyService" class="DependencyServiceImpl"></bean>
如果一个bean的定义依赖其他bean,则直接调用对应的JavaConfig类中依赖bean的创建方法就可以
了。
@Configuration:提到@Configuration就要提到他的搭档@Bean。使用这两个注解就可以创建一个简
单的spring配置类,可以用来替代相应的xml配置文件。
相当于:
@Configuration的注解类标识这个类可以使用Spring IoC容器作为bean定义的来源。
@Bean注解告诉Spring,一个带有@Bean的注解方法将返回一个对象,该对象应该被注册为在Spring
应用程序上下文中的bean。
@ComponentScan
@Configuration
public class MockConfiguration{
@Bean
public MockService mockService(){
return new MockServiceImpl(dependencyService());
}
@Bean
public DependencyService dependencyService(){
return new DependencyServiceImpl();
}
}
<beans>
<bean id = "car" class="com.test.Car">
<property name="wheel" ref = "wheel"></property>
</bean>
<bean id = "wheel" class="com.test.Wheel"></bean>
</beans>
1 @Configuration
2 public class Conf {
3 @Bean
4 public Car car() {
5 Car car = new Car();
6 car.setWheel(wheel());
7 return car;
8 }
9
10 @Bean
11 public Wheel wheel() {
12 return new Wheel();
13 }
14 }