@SpringBootApplication
SpringBoot应用标注在某个类上说明这个类是SpringBoot的主配置类,SpringBoot就会运行这个类的main方法来启动SpringBoot项目。
########################################################################
那@SpringBootApplication注解到底是什么呢,点进去看看:
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration 允许在上下文中注入额外的bean 或导入其它配置类
@EnableAutoConfiguration 启动springboot的自动配置机制
@ComponentScan( 扫描被@Component (@Service,@Controller)注解的bean,注解默认会
扫描启动类所在的包下所有的类,可以自动以不扫描某些类
excludeFilters = {@Filter(
type = FilterType.CUSTOM,
classes = {TypeExcludeFilter.class}
), @Filter(
type = FilterType.CUSTOM,
classes = {AutoConfigurationExcludeFilter.class}
)}
)
public @interface SpringBootApplication {
}
########################################################################
SpringBootConfiguration
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration
public @interface SpringBootConfiguration {
}
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Configuration {
String value() default “”;
}
说明Spring的配置类也是Spring的一个组件。
#########################################################################
EnableAutoConfiguration 这个注解是开启自动配置的功能。
@EnableAutoConfiguration 是实现自动装配的重要注解,自动装配核心功能的实现实际是通过EnableAutoConfigurationImportSelector 类
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import({EnableAutoConfigurationImportSelector.class})
public @interface EnableAutoConfiguration {
}
-----------------------------------start----------------------------------------
先看看@AutoConfigurationPackage注解:
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import({Registrar.class})
public @interface AutoConfigurationPackage {
}
这个注解是自动配置包,主要是使用的@Import来给Spring容器中导入一个组件 ,这里导入的是Registrar.class。
@Order(-2147483648)
static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {
Registrar() {
}
public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
AutoConfigurationPackages.register(registry, (new AutoConfigurationPackages.PackageImport(metadata)).getPackageName());
}
}
查询结果:
(new AutoConfigurationPackages.PackageImport(metadata)).getPackageName() —> com.hikvision.admin.server
说白了就是将主配置类(即@SpringBootApplication标注的类)的所在包及子包里面所有组件扫描加载到Spring容器。
所以包名一定要注意。
-----------------------------------end ----------------------------------------
@Import注解就是给Spring容器中导入一些组件,这里传入了一个组件的选择器:AutoConfigurationImportSelector。
里面有一个selectImports方法,将所有需要导入的组件以全类名的方式返回;这些组件就会被添加到容器中。
EnableAutoConfigurationImportSelector 这个类实现了 ImportSelector接口,也就实现了接口中的selectImports方法。
该方法主要用于获取所有符合条件的类的全限定类名,这些类需要被加载到IOC容器中
public class AutoConfigurationImportSelector implements DeferredImportSelector{
}
public interface DeferredImportSelector extends ImportSelector {
}
public interface ImportSelector {
String[] selectImports(AnnotationMetadata var1);
}
无状态对象和有状态对象
无状态对象,没有状态,只有只读属性,没有可写属性
有状态就是有数据存储功能。有状态对象(StatefulBean),就是有实例变量的对象,可以保存数据,是非线程安全的。
在不同方法调用期间不保存任何状态。因此有状态对象用于多例
无状态就是一次操作,不能保存数据。无状态对象(Stateless Bean),就是没有实例变量的对象.不能保存数据,是不变类,是线程安全的。
所以在开发中要多使用无状态对象。无状态多用于是单例
BeanPostProcessor
**
-
应用上下文工具类
-
@author liuhan10
*/
@Component
public class ApplicationContextUtil implements StaticUtilInitializer {private static ApplicationContext context;
public ApplicationContextUtil(@Autowired ApplicationContext context){
ApplicationContextUtil.context=context;
}public static T getBean(Class t) {
return context.getBean(t);
}public static String getProperty(String key) {
return context.getEnvironment().getProperty(key);
}public static T getBeanByName(String beanName, Class t) {
return context.getBean(beanName, t);
}
}
/**
-
实现这个接口的Bean会优先加载,适用于依赖Spring应用上下文中其他Bean的静态工具类
-
@author liuhan10
*/
public interface StaticUtilInitializer extends BeanPostProcessor {@Override
default Object postProcessBeforeInitialization(Object var1, String var2) throws BeansException{
return var1;
}@Override
default Object postProcessAfterInitialization(Object var1, String var2) throws BeansException{
return var1;
}
}
postProcessBeforeInitialization 方法中处理标记接口,在 postProcessAfterInitialization 中处理代理 beans。
BeanPostProcessor接口中定义了两个方法,其中方法postProcessBeforeInitialization()将在一个bean被完全初始化前进行回调,
此时对应的bean已经实例化了,但是对应的属性注入等还没有进行,即在调用InitializingBean的
afterPropertiesSet()方法或bean对应的init-method之前;而方法postProcessAfterInitialization()
将在bean被完全初始化后进行回调,此时对应的依赖注入已经完成,即在调用InitializingBean的afterPropertiesSet()方法
或对应init-method方法之后。两个方法的参数以及返回值对应的意义都是一样的,其中参数bean表示当前状态的bean,
参数beanName表示当前bean的名称,而方法对应的返回值即表示需要放入到bean容器中的bean,
所以用户如果有需要完全可以在这两个方法中对bean进行修改,即封装自己的bean进行返回。
BeanPostProcessor <------InstantiationAwareBeanPostProcessor <------SmartInstantiationAwareBeanPostProcessor
public class User {
@Autowired
private UserExt ext;
private String id;
public User() {
}
//其他
}
public class UserExt {
@Autowired
private User user;
private String name;
public UserExt() {
}
//其他
}
InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation - user
在实例化目标bean之前应用此BeanPostProcessor。
InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation - user
在bean实例化之后,通过构造函数或工厂方法,但在Spring属性填充(来自显式属性或自动装配)之前执行操作。
InstantiationAwareBeanPostProcessor#postProcessProperties - user
在工厂将它们应用于给定bean之前对给定属性值进行后处理,不需要属性描述符。
InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation - userExt
在实例化目标bean之前应用此BeanPostProcessor。
InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation - userExt
在bean实例化之后,通过构造函数或工厂方法,但在Spring属性填充(来自显式属性或自动装配)之前执行操作。
InstantiationAwareBeanPostProcessor#postProcessProperties - userExt
在工厂将它们应用于给定bean之前对给定属性值进行后处理,不需要属性描述符。
SmartInstantiationAwareBeanPostProcessor#getEarlyBeanReference - user
获取早期访问指定bean的引用,通常用于解析循环引用。
BeanPostProcessor#postProcessBeforeInitialization - userExt
在任何bean初始化回调(如InitializingBean afterPropertiesSet 或自定义init方法)之前,将此BeanPostProcessor应用于给定的新bean实例。
BeanPostProcessor#postProcessAfterInitialization - userExt
在任何bean初始化回调(如InitializingBean afterPropertiesSet 或自定义init方法)之后,将此BeanPostProcessor应用于给定的新bean实例。
BeanPostProcessor#postProcessBeforeInitialization - user
在任何bean初始化回调(如InitializingBean afterPropertiesSet 或自定义init方法)之前,将此BeanPostProcessor应用于给定的新bean实例。
BeanPostProcessor#postProcessAfterInitialization - user
在任何bean初始化回调(如InitializingBean afterPropertiesSet 或自定义init方法)之后,将此BeanPostProcessor应用于给定的新bean实例。
beanFactoryPostProcessor
- beanFactoryPostProcessor接口可以在bean未被实例化之前获取bean的定义即配置元数据,然后根据需要进行更改。
- beanFactoryPostProcessor里有方法 void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException; 此方法可以通过beanFactory可以获取bean的定义信息,并可以修改bean的定义信息。
- 可以在spring配置文件中定义多个beanFactoryPostProcessor,执行顺序按照定义顺序执行,也可以根据order属性自己定义执行顺序。
public class FactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(
ConfigurableListableBeanFactory configurableListableBeanFactory)
throws BeansException {
System.out.println("******调用了BeanFactoryPostProcessor");
String[] beanStr = configurableListableBeanFactory
.getBeanDefinitionNames();
for (String beanName : beanStr) {
if ("beanFactoryPostProcessorTest".equals(beanName)) {
BeanDefinition beanDefinition = configurableListableBeanFactory
.getBeanDefinition(beanName);
MutablePropertyValues m = beanDefinition.getPropertyValues();
if (m.contains("name")) {
m.addPropertyValue("name", "赵四");
System.out.println("》》》修改了name属性初始值了");
}
}
}
}
}