讓一個普通類創建的對象接受 Spring 容器管理方法總結

想要讓自己寫的一個普通類創建的對象扔到Spring 容器中管理,有以下方法:

  • 使用 常規的註解,@Controller @Service @Repository @Component 註解標註該類,然後確保 @ComponentScan 掃描路徑包含以上的類即可

  • 使用 @Bean 註解的方法裏面 new 出來的對象會進入Spring容器,當然標有@Configuration 的配置類本身也會創建一個對象進入Spring容器(IOC)中的

  • 使用 @ConfigurationProperties@EnableConfigurationProperties 組合的用於接受yml文件中參數的類也會創建對象進入Spring容器(IOC)

  • @Import 方法
    YourBusinessService 是自定義的類
@Configuration
@Import(YourBusinessService.class)
public class YourBusinessImportConfig {

}

當然 可以將類 YourBusinessImportConfig 換成註解也行,例如:

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import({YourBusinessService.class})
public @interface EnableYourBusinessService {
}

然後你就可以在自己的Spring項目中採用 @EnableYourBusinessService 來注入 YourBusinessService對象。


  • 實現ImportSelector接口方法批量注入對象
    這個需要配合 @Import註解
public class YourBusinessServiceSelector implements ImportSelector {
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        return new String[]{"com.baisheng.service.YourBusinessService"};
    }
}

然後通過@Import註解注入到Spring容器裏面

@Configuration
@Import(YourBusinessServiceSelector .class)
public class YourBusinessImportConfig {

}

當然同理,可以將YourBusinessImportConfig 類換成註解也行


  • 實現ImportBeanDefinitionRegistrar 接口方法批量注入對象
    這個需要配合 @Import註解
    這個方法在Spring框架中用的很多,你會發現上面的 @EnableConfigurationProperties 其實就是採用該方法將參數配置類注入spring容器中的,查看源碼如下:

public class EnableConfigurationPropertiesRegistrar implements ImportBeanDefinitionRegistrar {
   
    @Override
    public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
        registerInfrastructureBeans(registry);
        ConfigurationPropertiesBeanRegistrar beanRegistrar = new ConfigurationPropertiesBeanRegistrar(registry);
        this.getTypes(metadata).forEach(beanRegistrar::register);
    }
}

自己寫一個

public class YourBeanDefinitionRegistrat implements ImportBeanDefinitionRegistrar {
    
    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        BeanDefinition beanDefinition = new RootBeanDefinition(YourBusinessService.class);
        registry.registerBeanDefinition("yourBusinessService", beanDefinition);
    }
}

  • 採用 BeanDefinitionRegistry 動態注入bean

這種一般在自定義框架中比較常見,比如dubbo等
如果你採用SpringBoot爲基礎框架時,就比較好做。

  1. 拿到 ApplicationContext
 @Resource
 private ApplicationContext applicationContext;
  1. 通過ApplicationContext獲取 DefaultListableBeanFactory
DefaultListableBeanFactory defaultListableBeanFactory =
                (DefaultListableBeanFactory) applicationContext.getAutowireCapableBeanFactory();

  1. 創建 BeanDefinitionBuilder 用於定義構造函數,初始化、銷燬方法
 BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.rootBeanDefinition(YourBusinessService.class);
 // 如果有構造函數參數
 beanDefinitionBuilder.addConstructorArgValue(object1);
 beanDefinitionBuilder.addConstructorArgValue(object2);
 beanDefinitionBuilder.addConstructorArgValue(object3);
 // 等等 有幾個構造函數的參數就設置幾個
// 設置 init方法
beanDefinitionBuilder.setInitMethodName("initMethodName");

// 設置 destory方法
beanDefinitionBuilder.setDestroyMethodName("destoryMethodName");
  1. 調用 DefaultListableBeanFactory 的 registerBeanDefinition 方法註冊成功
AbstractBeanDefinition beanDefinition = beanDefinitionBuilder.getBeanDefinition();
defaultListableBeanFactory.registerBeanDefinition("beanName", beanDefinitionBuilder.getBeanDefinition());

  • 當然還有其他方式,比如 自定義 starter 等,這裏簡單列舉說明一下
    例如:
    自定義satarter resources -> META-INF -> spring.factories 文件中如下
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
                    com.middol.starter.mq.config.AliyunRocketMqAutoConfigure,\
                    com.middol.starter.mq.config.ApacheRocketMqAutoConfigure

這裏有兩個配置類 AliyunRocketMqAutoConfigure 和 ApacheRocketMqAutoConfigure

配置類大致情況如下:

@Configuration
@ConditionalOnClass({ONSFactory.class})
@ConditionalOnProperty(prefix = "middol.mq.aliyun.rocketmq", value = "enable", havingValue = "true")
@EnableConfigurationProperties({AliyunRocketMqProperties.class})
public class AliyunRocketMqAutoConfigure implements InitializingBean {

}


@Configuration
@ConditionalOnClass({SendMessageContext.class})
@ConditionalOnProperty(prefix = "middol.mq.apache.rocketmq", value = "enable", havingValue = "true")
@EnableConfigurationProperties({ApacheRocketMqProperties.class})
public class ApacheRocketMqAutoConfigure implements InitializingBean {


}

在配置類裏面的 @Bean方法new出的對象都會進入spring容器中。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章