Spring让人眼前一亮的11个小技巧( 三 )

通过@Import注解引入A类,spring就能自动实例化A对象,然后在需要使用的地方通过@Autowired注解注入即可:
@Autowiredprivate A a;是不是挺让人意外的?不用加@Bean注解也能实例化bean 。
5.2 配置类这种引入方式是最复杂的,因为@Configuration注解还支持多种组合注解,比如:

  • @Import
  • @ImportResource
  • @PropertySource等 。
public class A {}public class B {}@Import(B.class)@Configurationpublic class AConfiguration {@Beanpublic A a() {return new A();}}@Import(AConfiguration.class)@Configurationpublic class TestConfiguration {}通过@Import注解引入@Configuration注解的配置类,会把该配置类相关@Import@ImportResource@PropertySource等注解引入的类进行递归,一次性全部引入 。
5.3 ImportSelector这种引入方式需要实现ImportSelector接口:
public class AImportSelector implements ImportSelector {private static final String CLASS_NAME = "com.sue.cache.service.test13.A"; public String[] selectImports(AnnotationMetadata importingClassMetadata) {return new String[]{CLASS_NAME};}}@Import(AImportSelector.class)@Configurationpublic class TestConfiguration {}这种方式的好处是selectImports方法返回的是数组,意味着可以同时引入多个类,还是非常方便的 。
5.4 ImportBeanDefinitionRegistrar这种引入方式需要实现ImportBeanDefinitionRegistrar接口:
public class AImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {@Overridepublic void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(A.class);registry.registerBeanDefinition("a", rootBeanDefinition);}}@Import(AImportBeanDefinitionRegistrar.class)@Configurationpublic class TestConfiguration {}这种方式是最灵活的,能在registerBeanDefinitions方法中获取到BeanDefinitionRegistry容器注册对象,可以手动控制BeanDefinition的创建和注册 。
6.项目启动时有时候我们需要在项目启动时定制化一些附加功能,比如:加载一些系统参数、完成初始化、预热本地缓存等,该怎么办呢?
好消息是springboot提供了:
  • CommandLineRunner
  • ApplicationRunner
这两个接口帮助我们实现以上需求 。
它们的用法还是挺简单的,以ApplicationRunner接口为例:
@Componentpublic class TestRunner implements ApplicationRunner {@Autowiredprivate LoadDataService loadDataService;public void run(ApplicationArguments args) throws Exception {loadDataService.load();}}实现ApplicationRunner接口,重写run方法,在该方法中实现自己定制化需求 。
如果项目中有多个类实现了ApplicationRunner接口,他们的执行顺序要怎么指定呢?
答案是使用@Order(n)注解,n的值越小越先执行 。当然也可以通过@Priority注解指定顺序 。
7.修改BeanDefinitionSpring IOC在实例化Bean对象之前,需要先读取Bean的相关属性,保存到BeanDefinition对象中,然后通过BeanDefinition对象,实例化Bean对象 。
如果想修改BeanDefinition对象中的属性,该怎么办呢?
答:我们可以实现BeanFactoryPostProcessor接口 。
@Componentpublic class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {@Overridepublic void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {DefaultListableBeanFactory defaultListableBeanFactory = (DefaultListableBeanFactory) configurableListableBeanFactory;BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(User.class);beanDefinitionBuilder.addPropertyValue("id", 123);beanDefinitionBuilder.addPropertyValue("name", "苏三说技术");defaultListableBeanFactory.registerBeanDefinition("user", beanDefinitionBuilder.getBeanDefinition());}}

经验总结扩展阅读