一注解
1.@EnableAutoConfiguration 会从classpath中搜索所有的(包含外部jar)META-INF/spring.factories配置文件,然后将org.springframework.boot.autoconfiguration.EnableAutoConfiguration key对应的配置添加到spring容器中
该文件的value值可以时@configuration类,也可以是普通的类。都可以在其他项目中进行bean对象的获取。
从而完成spring对外部jar包中类的加载。
内部实现的因素:
ImportSelector 该接口的返回值都会被纳入spring容器的管理之内
SpringFactoryLoader可以从classpath中搜索所有的META-INF/spring.factories配置文件,并加载所有配置项
如果当前项目配置spring.boot.enableautoconfiguration=false,则以上所述也是无法正常使用的。此属性默认为true
可以在@AutoConfiguration中使用exculd=.class/类全名 排除不进行自动加载的类
2.@EnableConfigurationProperries 该注解的作用是将配置文件中的属性值加载到具体的实体类对象中
3.@EnableAsync 启动异步执行,在需要异步执行的方法上面添加注解 @Async
4.@Component 该注解会默认将当前类加载到Spring容器中,所以无需再在@Configuration配置类中重新配置一个bean,如果配置之后,不可为类名首字母小写
5.动态适配需要装配的bean对象
① 使用@Ennable* + @Import注解 此种方式相当于被动添加,也就是说Spring容器会自动获取到对应的bean并进行添加
@Enable* @Import() 注解 该注解的参数bean,可以被加载到bean容器中
@ennable 该注解需要结合对应的实现ImportSelector接口的对应类,并将该类使用@Import注解导入自定义的@ennable*注解上。
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(MyImportSelect.class)
public @interface EnnableLog {
String name();
}
//返回值为一个String数组 返回的对象都会交予Spring容器进行托管
//也可以在其方法中获取到指定注解的一些信息,从而进行一系列自定义配置
public class MyImportSelect implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
System.out.println(annotationMetadata.getAllAnnotationAttributes(EnnableLog.class.getName()));;
return new String[]{};
}
}
@EnnableLog(name = "CYAN")
在selectImports方法中可以直接获取该注解的参数值,即:CYAN
②实现InportBeanDefinitionRegistrar接口,该种方式属于主动添加
实现该接口之后需要重写其registerBeanDefinitions()方法。
使用的时候,可以选择Import(MyImportBeanDefinitionRegistrar.class)直接将该类添加到程序入口类上,应该也可以直接@Component将其添加到SPring容器中。
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry beanDefinitionRegistry) {
Map<String, Object> arr = annotationMetadata.getAnnotationAttributes(Logecho.class.getName());
//packages 为Logecho.class注解对象的属性的属性名
String[] ar = (String[]) arr.get("packages");
List<String> packages = Arrays.asList(ar);
//此处可以获取到对应的Logecho.class注解添加的属性值
System.out.println("**************"+packages);
BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.rootBeanDefinition(LogBeanPostProcessor.class);
beanDefinitionBuilder.addPropertyValue("packages", packages);
beanDefinitionRegistry.registerBeanDefinition(LogBeanPostProcessor.class.getName(),beanDefinitionBuilder.getBeanDefinition());
}
六/EnvironmentPostProcessor接口
将该接口的实现类添加到Spring容器中,可以实现加载非项目中文件配置属性内容
@Component
public class MyEnvironmentPostProcessor implements EnvironmentPostProcessor {
@Override
public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
try{
InputStream inputStream = new FileInputStream("E:\\spring.properties");
Properties prop = new Properties();
prop.load(inputStream);
PropertiesPropertySource propertiesPropertySource
= new PropertiesPropertySource("my",prop);
environment.getPropertySources().addLast(propertiesPropertySource);
}catch (IOException e){
}
}
}
二.事件的创建和监听
1.自定义事件:
继承ApplicationEvent抽象类
2.自定义监听器:
实现ApplicationListener接口
3.添加监听器进spring管理
SpringApplication.addListener()
直接在实现了ApplicationListener的监听器上面添加@Component注解将监听器交予Spring容器管理
在application.properties中配置属性context.listener.classes=全类名进行监听器的发布
直接创建一个监听器的类(无需实现ApplicationListener),并交予spring容器进行管理,声明一个参数为需要监听的事件(所有该事件以及该事件的子类都会被监听,不可没有参数)的方法,如果为Object则会监听spring的所有事件。并在方法上添加注解@EventListener
4.发布事件:
ApplicationContext.pushlishEvent() 详细参照EventListenerMethodProcessor,EventListenerFactory
三.Condition接口
@Conditional 基于条件的自动配置,一般配合Condition的实现类一起使用,只有一个或多个接口的实现类全部返回为true才会进行对应bean的装配。否则不装配,可以在单个方法上面也可以在配置类上面。
该接口提供了SPring的自动化配置,重写该接口的matches方法,可以自定义选择加载一些配置文件。
//当该方法的返回值为true时,才会加载对应的bean
@public class GBKCondition implements Condition {
@Override
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
String e = System.getProperty("file.encoding");
if (e != null) {
return "gbk".equals(e.toLowerCase());
}
return false;
}
}
当然此时需要在配置类的对应bean上添加@Conditional(GBKCondition.class)
@SpringBootConfiguration
public class EncodingConvertConguration {
//Convert 为不同加载文件的基类
@Bean
@Conditional(UTF8Condition.class)
public Convert UTF8(){
return new UTF8EncodingConvert();
}
@Bean
@Conditional(GBKCondition.class)
public Convert GBK(){
return new GBKEncodingConvert();
}
}
四.BeanPostProcessor接口
实现该接口的类,加入SPringle容器后,在bean创建未赋值之前调用其postProcessBeforeInitialization(),在赋值之后调用postProcessAfterInitialization(),可以借此做一些自定义的操作。
五 自定义扫描注解包内的bean对象
@SpringBootApplication
//配置的需要扫描的包
@Logecho(packages = {"com.example.log.Dao","com.example.log.Bean"})
@EnableAutoConfiguration
public class LogApp {
public static void main(String[] args) {
ConfigurableApplicationContext context =
SpringApplication.run(LogApp.class, args);
//获取对应的包下的bean
System.out.println(context.getBean(Dog.class));;
System.out.println(context.getBean(Runnable.class));
}
}
//该类会在bean加载的过程中进行执行
public class LogBeanPostProcessor implements BeanPostProcessor {
private List<String> packages;
public List<String> getPackages() {
return packages;
}
public void setPackages(List<String> packages) {
this.packages = packages;
}
//该方法的返回的bean都会被实例化
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
for (String aPackage : packages) {
if (bean.getClass().getName().startsWith(aPackage)) {
System.out.println("==================="+bean.getClass().getName());
}
}
return bean;
}
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
//导入的配置类ImportBeanDefinitionRegistrar,在其中扫描该注解的packages属性,并将该
@Import(MyBeanRegister.class)
public @interface Logecho {
String[] packages();
}
//主动加载bean
public class MyBeanRegister implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry beanDefinitionRegistry) {
Map<String, Object> arr = annotationMetadata.getAnnotationAttributes(Logecho.class.getName());
//获取Logecho.class配置的packages的属性值
String[] ar = (String[]) arr.get("packages");
List<String> packages = Arrays.asList(ar);
System.out.println("**************"+packages);
BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.rootBeanDefinition(LogBeanPostProcessor.class);
beanDefinitionBuilder.addPropertyValue("packages", packages);
beanDefinitionRegistry.registerBeanDefinition(LogBeanPostProcessor.class.getName(),beanDefinitionBuilder.getBeanDefinition());
}
}
六 主要的类
FactoryBean接口 实现该接口,重写该接口的三个方法,getObject() 返回一个需要返回的bean的对象, 第二个方法直接返回该类的类型,第三个设置是否为单例
在配置类中配置返回对应的FactoryBean对象即可获取到对应的bean实例。
也可以在配置类中直接创建一个返回bean的方法,参数设置为对应的facrotyBEAN,一个返回对应的factoryBean的方法,此时,会自动将配置类中的factorybean对象作为参数传递给真正需要返回的bean的配置方法中
指定类的初始化和销毁方法
@Bean(initMethod="",destoryMethod="") 可以指定初始化和销毁方法
也可以在对应的初始化和销毁方法上添加注解@PostConstruct和@PreDestory注解
也可以使用该类实现InitalizingBean,DisposableBean接口,并重写对应的afterPropertiesSet()和destory()方法
标注注解 @Repository一般标注在数据访问层上面 表示该类为bean交予spring容器托管
@Primary 配置类的注解,表示如果在注入时,发现多个bean,则优先加载标注的bean
BeanPostProcessor接口 Bean的后置处理器 会在每个Bean初始化的时候都执行
第一个方法会在bean初始化完成未配置属性值之前执行
第二个方法会在bean属性配置完成之后执行
可以在两个方法中进行一些额外的属性配置等操作
Aware接口经常结合BeanPostProcessor接口进行使用,判断是否是对应aware对象并进行对应的操作。
BeanFactoryPostProcessor接口 在bean容器初始化之后进行执行 旨在SPring容器储时化之后触发一次,在BeanPostProcessor执行之前进行执行
实现该接口的类也需要添加到Spring容器之中
BeanDefinitionRegistryPostProcessor 接口
实现该接口可以拿到BeanDefinitionRegistry对象,从而进行动态bean的装配
需要将该类添加到Spring容器中
BeanDefinitionRegistry 实现该接口可以动态的实现bean的装配
BeanDefinitionBuiler.rootBeanDefinition(?.class).getBeanDefinition();
给对应的bean对象添加属性
BeanDefinitionBuiler.rootBeanDefinition(?.class).addPropertyValue("","");
EnvironmentPostProcessor
实现该类可以实现对外部配置文件的加载
Properties prop = new Properties();
InputStream is = new FileInputStream(“c:/asdada.sadada”);
prop.load(is);
PropertiesPropertySource ps = new PropertiesProperty("",prop);
environment.getPropertySources().addLast(ps);
这种情况需要在META-INF 下配置EnvironmentPostProcessor全类名=实现类的全类名