(1)SpringBoot启动原理(被问到了QAQ)
我们开发任何一个Springboot项目都用到启动类,启动类上面会加上@SpringBootApplitcation,然后public stattic void main中,SpringApplication.run(Application.class,args)将这个标志位SpringBoot入口。
@SpringBootApplication中有三个核心的注解,其中@Configuration(其实是@SpringBootConfiguration)、@EnableAutoConfiguration、@ComponentScan
@SpringBootApplication=(默认属性)@Configuration+@EnableAutoConfiguration+@ComponentScan
1、@Configuration
这里的@Configuration对我们来说并陌生,他是与Spring中IOC容器配置类使用@Configuration,SpringBoot社区推荐使用基于JavaConfig的配置形式,所以这里的启动类标注了@Configuration之后,本身就变成了IOC容器配置类。
@Configuration的注解类表示了这个类可以使用SpringIOC容器作为bean定义的来源
@Bean注释告诉spring,一个带有@Bean的注解方法将返回一个对象,该对象应该被注册为Spring应用程序上下文的bean定义加载到 IOC容器中。
实际上@Configuration可以立即为xml中的beans标签,而@Bean可以理解为bean标签
(1)表达层面上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定义
}
(2)注册bean的定义上
<bean id="mockService" class="..MockServiceImpl">
...
</bean>
//任何一个标注了bean的方法,其返回值将作为一个bean的定义注册到spring IOC容器中
@Configuration
public class MockConfiguration{
@Bean
public MockService mockService(){
return new MockServiceImpl();
}
}
(3)表达依赖注入层
<bean id="mockService" class="..MockServiceImpl">
<propery name ="dependencyService" ref="dependencyService" />
</bean>
<bean id="dependencyService" class="DependencyServiceImpl"></bean>
//如果一个bean的定义依赖其他bean,则直接调用对应的JavaConfig类中依赖bean创建方法就可以了
@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>
///相当于 beans = @Configuration bean = @bean
@Configuration
public class Conf{
@Bean
public Car car(){
Car car = new Car();
Car.setWheel(wheel());
return car;
}
@Bean
public Wheel wheel(){
return new Wheel();
}
}
2、@ComponentScan
@ComponentScan这个注解在Spring中很重要,他赌赢了XML配置的元素。@ComponentScan的功能其实就是自动扫描并加载到符合条件的组件中(比如@Component和@Repository)或者Bean的定义,最终将这些bean加载IOC容器中。我们可以通过BasePackge等属性来细粒度定制@ComponentScan自动扫描的范围,如果不指定,则任务spring框架会从声明出开始扫描。
3、@EnableAutoConfiguration
个人感觉@EnableAutoConfiguration这个Annotation最为重要,所以放在最后来解读。这个@Enable与@Enable开头的其他Annotation一样,比如@EnableScheduling开启定时任务、@EnableCacheing允许缓存等,其实都是接触@Import的支持,收集和注册特定场景相关的bean的定义。
~@EnableSchduling是通过@Import将Spring调度框架相关的bean定义加载IOC容器
@EnableAutoCOnfiguration也是借助@Import的帮助,将所有符合自动配置的跳江的bean定义加载IOC容器,仅此而已。@EnableAutoConfiguration会根据类路径中jar依赖为项目进行自动配置,如添加了spring-boot-starter-web依赖,会自动添加Tomcat和Spring MVC依赖,Springboot对Tomcat和spring MVC进行自动配置。
最关键要属@Import(EnableAutoConfigurationImportSelector.class)借助EnableAutoConfigurationImportSelector,可以帮助应用将所有符合条件的@Configuration配置都加载当前SpringBoot创建并使用IOC容器,哟一个spring框架中的工具类SpringFactoriesLoader,最终加载到ApplicationContext
INF/spring.factories配置问题,并将其中org.springframework.boot.autoconfigure.EnableautoConfiguration对应的配置项通过java反射实例化为对应的标注@Configuration的javaConfig形式的IOC容器配置类,然后汇总为一个并加载IOC容器中。SpringFactoriesLoader将查询配置文件命名的属性,然后进行逐个自动配置(那个文件里面各个都是配置类)。在装配一个的配置时,首先读取项目中的配置,只有项目中没有相关配置的时候才启用配置的默认值。
这也是其中最核心的一步:通过@EnableAutoConfiguration获取所有的配置以及其他形式的IOC容器配置加载到已经准备完毕ApplicationContext
原理:springboot进行实例化时SpringFactoriesLoader加载META-INF/spring.factories文件,将配置文件载入到spring容器。会过滤出key为org.springframe.boot.autoconfigure.EnableConfiguration全限定名对应的值。(最主要的注解就是@enableAutoConfiguration,而这个注解会导入一个EnableAutoConfigurationImportSelector的类,而这个类会去读取一个spring.factories下key为EnableAutoConfiguration全限定名对应值.) 收集配置文件中配置工厂类
总结: 第一部分进行SpringApplication初始化,配置基本的环境变量、资源、构造器、监听器。 第二部分实现了具体应用的启动方案,包括启动流程的监听模块,加载配置环境模块,以及核心的创建上下文模块 第三部分才是自动化配置模块,该模块作为spring自动配置的核心。
最后还是要说一下再springboot应用程序入口:使用的@SpringBootApplication分为三个注解
@EnableAutoConfiguration:springboot根据应用所声明的依赖来对spring框架进行制动配置
@SpringBootConfiguration(内部为@Configuration):被标注的类等于在spring的xml配置文件中,装配所有bean事务,提供一个spring上下文环境。
@ComponentScan:组件扫描,可以自动发现和装配bean,默认扫描SpringApplication的run方法所在包路径下的所有配置。
Spring查看(CLASSPATH可用框架)已存在的应用程序配置,再此基础上,SpringBoot提供配置应用程序的框架所需要的基本配置,这就是自动配置。
接下来自己写一下吧QAQ 照着网上看的
1、配置属性类:其实就是值对象注入的方式去配置一些spring常用配置,我们编写一个最简单的配置对象
@ConfigurationProperties(prefix = "hello")
//@Conponent如果这里填了注解那么自动配置类的时候就不用添加了@enableConfigurationProperties(HelloProperties.class)
public class HelloProperties{
private String msg ="default";
public String getMsg(){
return msg;
}
public void setMsg(String msg){
this.msg = msg;
}
}
这是一个简单的属性值对象,那么相当于写死的字段就是SpringBoot为我们自动配置的配置,那么我们很多时候就是在自己的application。properties中修改某些配置就是这样的道理,我们不设置就是默认的。
2、自动配置
上面我们构建了简单的属性对象,那么现在我们要通过属性对象的到相应的属性值将其注入到我们bean中,这些bean就是一些SpringBoot启动后为我们自动配置生成的bean,当然SpringBoot优先使用我们配置的Bean这个功能是如何实现的。
//@Component 这是很重要,如果我们添加了这个注解那么,按照我们下面的设置SpringBoot会优先使用我们配置的这个bean,这是符合SpringBoot框架优先使用自动优先使用我们配置的这个Bean,这个符合SpringBoot优先使用自定义Bean的原则的。
public class HelloService{
private String msg = "Service";//如果自动配置没有读入成功,那么为默认值
public String say(){
return "hello"+msg;
}
public String getMsg(){
return msg;
}
public void setMsg(String msg){
this.msg = msg;
}
}
现在编写我们的自动配置类
@Configuration//配置类
@EnableConfigurationProperties(HelloProperties.class)//这里就是前面说的,这个注解读入我们配置对象类
@ConditionalOnClass(HelloService.class)//当类路径存在这个类时才会加载配置类,否则跳过,这个很有用比如不同的jar包间依赖,依赖的类不存在直接跳过,不会报错。
public class HelloAutoConfiguration{
@Autowired
private HelloProperties helloProperties;
@Bean
@ConditionalOnMissingBean(HelloService.class)//这个配置类就是SpringBoot可以优先使用自定义Bean的核心所在,如果没有我们的自定义bean那么才会自动配一个新的Bean
public HelloService auto(){
HelloService helloService = new HelloService();
helloService.setMsg(helloProperties.getMsg());
return helloService;
}
}
3、测试自动配置
@SpringBootApplication
@RestController
public class MyRun{
@Autowired
private HelloService helloService;
@RequestMapping("/auto/home")
public String home(){
return helloService.say();
}
public static void main(String[] args){
SpringApplication.run(MyRun.class,args);
}
}
ok运行后就会有 hello world
还是再说一遍Springboot管理自动配置的过程:
其实在很多时候我们的配置是在很多jar包中的,那么我们新的应用该怎么读入这些Jar里面的配置文件呢,SpringBoot是这样管理的。 最胡要的注解就是@EnableAutoConfiguration,而这个注解会导入一个EnableAutoConfigurationSelector的类,这个类会去读取一个spring.factories下key为EnableAutoConfiguration全限定名对应值。
再说一下@Service与@Service类似的还要很多@Component、@Controller、@。。。。与@Autowired\
@Service在类前注释,将此类实例化,等同于在root-context中配置,就是一个实例化放入工厂的过程
<bean class=".................."></bean>
@Autowired在属性前配置,将属性对应的对象从工厂中取出并注入到该bean中,等同于property属性中
<property ref="myImpl" name="myImpl"></property>
两个注解联合起来等同于
<bean class="................">
<property ref="myImpl" name="myImpl"></property>
</bean>