让一个普通类创建的对象接受 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容器中。

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