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的注册顺序:

  1. @Configuration / @Import - @Configuration
  2. @Component
  3. @Import -class
  4. @Import -@Bean / @Bean
  5. @Import - ImportBeanDefinitionRegistrar
  6. @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);
    }
}