Spring
初始化一个对象后,立即初始化一些数据,再销毁一个对象之前进行垃圾回收等奥做。下面给出三种方法的总结。
注解方式:
- bean对象里面定义init,destroy方法。再声明Bean的时候指定initMethod和destroyMethod方法。
- 声明Bean的时候,不需要指定initMethod和destroyMethod方法。但是需要用上@PostConstruct和@PreDestroy两个注解
实现接口,重写方法的方式: - 实现InitializingBean, 重写afterPropertiesSet()方法实现自己的逻辑
- 实现DisposableBean, 重写destroy()方法实现自己的逻辑
问题注意:
Bean初始化完成之后,会执行initMethod这些相关的操作。然后创建好一个Bean之后,spring才会创建下一个Bean。
那么:如果@PostConstruct方法内的逻辑处理时间较长,就会增加springBoot应用初始化Bean的时间,进而就会影响启动时间。因为只有在Bean初始化完成后,SpringBoot应用才会打开端口提供服务。
解决:
所以说,对于轻量级的逻辑,可以放在@PostConstruct注解的方法里,非常耗时的逻辑,可以考虑使用多线程处理。
也可以放弃@PostConstruct注解,改用CommandLineRunner和ApplicationRunner
Bean创建的初始化阶段:
- 激活Aware方法。主要设置一些属性。设置BeanName,BeanClassLoader,BeanFactory。需要设置的依据就是实现了三个对应的Aware接口
- before后置处理
- invokeInitMethod():激活自定义的init方法。实现自定义的初始化逻辑
- 首先判断有没有实现InitializingBean接口重写afterPropertiesSet()方法。
- 如果没有实现,那就通过声明式的指出initMethod,执行这个方法。
可以同时使用,执行顺序也是先执行afterPropertiesSet()然后再执行指定的initMethod方法。
@PostConstruct和afterPropertiesSet和init-Method方法的执行顺序式:
- @PostConstruct;再Before方法中找到CommonAnnotationBeanPostProcessor处理的
- afterPropertiesSet;这个方法和init-method方法都是在invokeInitMethod方法时候处理的
- init-Method
CommonAnnotationBeanPostProcessor是InitDestroyAnnotationBeanPostProcessor的子类。
CommonAnnotationBeanPostProcessor设置了initAnnotationType和destroyAnnotationType注解
public CommonAnnotationBeanPostProcessor() {
this.setOrder(2147483644);
this.setInitAnnotationType(PostConstruct.class); //初始化注解
this.setDestoryAnnotationType(PreDestroy.class); //销毁注解
this.ignoreResourceType("javax.xml.ws.WebServiceContext");
}
Bean创建的属性赋值阶段:
- PropertyValues pvs = mbd.hasPropertyValues() ? mbd.getPropertyValues() : null;【就是获取在BD中设置的属性值】
- 然后开始autowiring自动装配:根据名称或者根据类型自动注入
if (mbd.getResolvedAutowireMode() == 1 || mbd.getResolvedAutowireMode() == 2) {} - 对非autowiring的属性进行依赖注入处理
boolean hasInstAwareBpps = this.hasInstantiationAwareBeanPostProcessors();
boolean needsDepCheck = mbd.getDependencyCheck() != 0;
然后会遍历所有的Bean的后置处理器。这里就会进行@Autowired和@Resource的注入工作。以及属性的填充(后置处理器)
所以在populateBean阶段进行自动装配的时候,根据byName或者byType的时候就会去getBean() - 然后自动装配完成以后,通过后置处理器,进行@Autowried和@Resource
@Autowried的处理在AutowiredAnnotationBeanPostProcessor#postProcessPropertyValues中
@Resource注解、@PostConstruct等通用注解的处理在CommonAnnotationBeanPostProcessor#postProcessPropertyValues
SpringBoot
配置文件
配置文件加载顺序:位置 > 类型
位置4个位置:项目根路径下config > 项目根路径 > classPath根路径下的Config > classPath根路径下的
类型: properties > yaml
bootstrap 和 application的区别:
父上下文加载bootstrap,子上下文加载application。所以顺序 bootstrap > application
区别:application中如果有相同的配置,bootstrap不会被覆盖。以bootstrap中配置为准
配置加载顺序
- properties文件
- yaml文件
- 系统环境变量
- 命令行参数
profiles
SpringBoot通过对application配置文件的命名规范进行约定,然后根据当前激活的profile来加载相应的配置文件;
命名规范:application-{你的profile}.properties | application-{你的profile}.yaml
举例:配置文件配置
|—— src
|—— |—— main
|—— |—— |—— java
|—— |—— |—— resource
|—— |—— |—— |—— application.yaml
|—— |—— |—— |—— application-dev.yaml
|—— |—— |—— |—— application-test.yaml
注意:
当profile为default时候,只使用application.yal
如果激活了profile为dev,激活dev配置时候,就会加载dev配置,然后合并到application.yaml中,要是有相同的配置则会【覆盖】
除此之外还能通过@Profile:通过代码的方式使用profile
javaConfig
@Configuration
@PropertySource指定配置文件,通过配合@Value注入类中进行配置
@PropertySource使用:
- 指定配置文件位置
- 配合@Value并使用EL表达式读取到类
- 然后根据读取到的值,创建对象
- 配合@Configuration以及@Bean把创建的对象注册到IO容器中
如何导入Bean(无论是否被管理)
一:@Import:注入后的名称就是全类名
- @Import({Student.class, Dog.class}): 标记@Import注解的类同样会注册到IOC容器,Bean的名称就是类名首字母小写
二:ImportSelector接口
- 创建类继承ImportSelector,重写selectImports方法,在字符数组中指定要导入的类
核心注解
@SpringBootApplication: @SpringBootConfiguration + @EnableAutoConfiguration + @ComponentScan
@EnableAutoConfiguration: @AutoConfigurationPackage + ImportSelector
异常处理,统一结果返回
全局异常处理:@ExceptionHandler + @RestControllerAdvice
全局统一返回:@RestControllerAdvice + 实现ResponseBodyAdvice【重写supports和beforeBodyWrite】
加载配置文件
- @PropertySource:读取指定配置文件
- @Value:读取配置文件信息
- @ConfigurationProperties:把配置信息和类绑定,读取到具体类中
- Environment:实现此接口,通过getProperty()读取