Spring中有哪些扩展点?和@Import注解的使用
1.BeanDefinitionRegistryPostProcessor
作用
实现该接口后可以注册BeanDefinition对象到Spring IOC容器,是对BeanDefinition的扩展。
代码示例
@Component //这里需要交给Spring管理才会回调
public class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException {
AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder
.genericBeanDefinition(PersonService.class).getBeanDefinition();
// 采用有参构造器初始化时必须传入,默认无参构造器时无需传入
beanDefinition.getConstructorArgumentValues().addGenericArgumentValue(1.0);
// 这里还可以调用为属性传值
beanDefinition.getPropertyValues().add("name","张小明");
beanDefinitionRegistry.registerBeanDefinition(PersonService.class.getSimpleName(),beanDefinition);
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
}
}
创建实体:
public class PersonService {
private Long version;
private String name;
//必须通过这个有参构造器构建
public PersonService(Long version) {
this.version = version;
}
public void test() {
System.out.println("test running");
System.out.println("version:"+version+",name:"+name);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
测试:
public class MyBeanDefinitionRegisterPostProcessorTest {
@Test
public void testBeanDefinitionReister() {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ExpressServiceApplication.class);
PersonService bean = context.getBean(PersonService.class);
bean.test();
}
}
2.BeanFactoryPostProcessor
作用:
将BeanFacotry回传,获取到IOC容器后可用查询、使用、扩展一切IOC容器提供的方法,如:所有的BeanDefintion注册完成后,对beanDefinition对象进行扩展。
调用时机:IOC加载注册beanDefinition完成之后。
代码示例:
@Component
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
for (String beanDefinitionName : beanFactory.getBeanDefinitionNames()) {
System.out.println(beanDefinitionName);
}
//可用通过如下方式进行扩展
// BeanDefinition beanDefinition = beanFactory.getBeanDefinition("xxx");
}
}
3.BeanPostProcessor
作用
可用在bean初始化前和初始化后进行回调,修改bean。
4.SmartInitializingSingletion
作用
在所有的Bean创建完成后的回调
代码示例
@Component
public class MySmartInitializingSingleton implements SmartInitializingSingleton {
@Override
public void afterSingletonsInstantiated() {
System.out.println("所有的单例Bean加载完成了...");
}
}
5.@Import注解的使用
5.1注入普通的对象或配置类对象
如果是普通类会解析生成Bean,配置类会按照配置类正常解析。
@SpringBootApplication
@Import(PersonService.class)
public class ExpressServiceApplication {
public static void main(String[] args) {
new SpringApplicationBuilder(ExpressServiceApplication.class).run(args);
}
}
5.2 实现ImportSelector接口
代码示例如下:
public class MyImportSelector implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
return new String[] {
"org.chenglj.express.spring.ext.PersonService"};
}
}
@SpringBootApplication
@Import(MyImportSelector .class)
public class ExpressServiceApplication {
public static void main(String[] args) {
new SpringApplicationBuilder(ExpressServiceApplication.class).run(args);
}
}
5.3 实现DeferredImportSelector接口
DeferredImportSelector继承至ImportSelector
,用法一样,区别在延迟、分组特性?spring-boot自动配置类常用该接口实现。
BeanDefinition的注册顺序:
- @Configuration / @Import - @Configuration
- @Component
- @Import -class
- @Import -@Bean / @Bean
- @Import - ImportBeanDefinitionRegistrar
- @Import - DeferredImportSelector
5.4导入ImportBeanDefinitionRegistrar 的实现类
public class MyImportBeanDefinitionRegister implements ImportBeanDefinitionRegistrar {
/*@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry, BeanNameGenerator importBeanNameGenerator) {
registerBeanDefinitions(importingClassMetadata,registry);
}*/
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
beanDefinition.setBeanClass(PersonService.class);
beanDefinition.getConstructorArgumentValues().addGenericArgumentValue(2.0);
registry.registerBeanDefinition(PersonService.class.getSimpleName(), beanDefinition);
}
}