Spring 通过实现 Aware 接口注册 bean
Spring register bean by implementating Aware interface
我正在使用 spring 引导程序,它会在启动期间自动扫描 bean。
通常我知道它会扫描标有@service
、@repository
和@component
.
的bean
比起@Configuration
我们有@Bean
注解。
有什么方法可以实现一些接口,如果包名称不同,它将成为扫描的一部分,这是在
@SpringBootApplication(scanBasePackages = "xyz.yah.*")
问题是我的库有不同的包名,更改 scanBasePackages 变得有点麻烦 属性 所以我想知道我的 bean 是否可以实现一些接口,通过它它立即成为自动扫描的一部分。有什么解决办法吗?
也不确定我是否只实现 Aware 接口就足以符合自动扫描的条件。
仔细考虑一下,这应该对你有用。然而,这是额外的黑魔法,where/how bean 的隐藏正在创建、命名、范围等。我建议创建配置 classes 等
使用 https://github.com/ronmamo/reflections、
Reflections reflections = new Reflections("com.mycompany.basepackage");
Set<Class<? extends MyInterface>> classes = reflections.getSubTypesOf(MyInterface.class);
将为您提供一组所有 class 界面。可以将它们组合在一起以在启动时动态加载 bean,
@Configuration
public class AwareConfig implements BeanDefinitionRegistryPostProcessor {
private static final Logger LOG = LoggerFactory.getLogger(AwareConfig.class);
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
Reflections reflections = new Reflections(this.getClass().getPackage().getName());
Set<Class<? extends Aware>> classes = reflections.getSubTypesOf(Aware.class);
classes.stream().forEach(clazz -> {
try {
BeanDefinitionBuilder builder = BeanDefinitionBuilder
.genericBeanDefinition(Class.forName(clazz.getName())).setLazyInit(false);
((DefaultListableBeanFactory) beanFactory).registerBeanDefinition(clazz.getName(),
builder.getBeanDefinition());
} catch (ClassNotFoundException e) {
throw new IllegalArgumentException(e);
}
LOG.info("Creating - {} bean", clazz.getName());
});
}
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry arg0) throws BeansException {
//NoOp
}
}
您可以根据用例使用其他类型的 bean post 处理器。也不一定是接口可以通过注释驱动它,允许您更轻松地指定参数而不是通过接口实现它们。
我在这里创建了一个工作示例,
https://github.com/Flaw101/dynamically-load-spring-bean
请记住,这相当简单,您的 bean 越复杂,加载和注入它们的问题就越多。
我更新了示例,将两个动态 bean 注入 service
class。
我正在使用 spring 引导程序,它会在启动期间自动扫描 bean。
通常我知道它会扫描标有@service
、@repository
和@component
.
比起@Configuration
我们有@Bean
注解。
有什么方法可以实现一些接口,如果包名称不同,它将成为扫描的一部分,这是在
@SpringBootApplication(scanBasePackages = "xyz.yah.*")
问题是我的库有不同的包名,更改 scanBasePackages 变得有点麻烦 属性 所以我想知道我的 bean 是否可以实现一些接口,通过它它立即成为自动扫描的一部分。有什么解决办法吗?
也不确定我是否只实现 Aware 接口就足以符合自动扫描的条件。
仔细考虑一下,这应该对你有用。然而,这是额外的黑魔法,where/how bean 的隐藏正在创建、命名、范围等。我建议创建配置 classes 等
使用 https://github.com/ronmamo/reflections、
Reflections reflections = new Reflections("com.mycompany.basepackage");
Set<Class<? extends MyInterface>> classes = reflections.getSubTypesOf(MyInterface.class);
将为您提供一组所有 class 界面。可以将它们组合在一起以在启动时动态加载 bean,
@Configuration
public class AwareConfig implements BeanDefinitionRegistryPostProcessor {
private static final Logger LOG = LoggerFactory.getLogger(AwareConfig.class);
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
Reflections reflections = new Reflections(this.getClass().getPackage().getName());
Set<Class<? extends Aware>> classes = reflections.getSubTypesOf(Aware.class);
classes.stream().forEach(clazz -> {
try {
BeanDefinitionBuilder builder = BeanDefinitionBuilder
.genericBeanDefinition(Class.forName(clazz.getName())).setLazyInit(false);
((DefaultListableBeanFactory) beanFactory).registerBeanDefinition(clazz.getName(),
builder.getBeanDefinition());
} catch (ClassNotFoundException e) {
throw new IllegalArgumentException(e);
}
LOG.info("Creating - {} bean", clazz.getName());
});
}
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry arg0) throws BeansException {
//NoOp
}
}
您可以根据用例使用其他类型的 bean post 处理器。也不一定是接口可以通过注释驱动它,允许您更轻松地指定参数而不是通过接口实现它们。
我在这里创建了一个工作示例,
https://github.com/Flaw101/dynamically-load-spring-bean
请记住,这相当简单,您的 bean 越复杂,加载和注入它们的问题就越多。
我更新了示例,将两个动态 bean 注入 service
class。