一、常用的注入spring Bean的几种方式:
1.常用的@controller、@Service、@Repository、@Configuration、@Component等注解,默认都会注入单例的Bean,如果这些类在启动类的同级包或同级包下面则会被自动注入,若不在,则需要加上@ComponentScan或者@ComponentScans将包名加入扫描才起作用
2.@Bean,也比较常用,一般通过构造方式返回一个类实例,然后会被spring加入IOC
3.@Import注解,可以直接将需要注入的class填入即可注入,一般用于自定义注解时使用
4.实现ImportSelector接口中selectImports方法,该方法返回一个String数组,String就是你需要实例化的类的包+类名,此方法也可用于读取自定义注解的值:
public class AliasRegister implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
Map<String, Object> map = importingClassMetadata.getAnnotationAttributes(EnableKitIo.class.getName());
if (map == null || map.isEmpty()) {
throw new EnerkitIoException("No attrs for enerkit-io");
}
String[] alias = (String[]) map.get("alias");
String defaultAlias = (String)map.get("defaultAlias");
if (defaultAlias.trim().length() == 0){
defaultAlias = alias[0];
}
IoClientInitializer.setDefaultAlias(defaultAlias);
Set<String> clientAlias = new HashSet<>();
clientAlias.addAll(Arrays.asList(alias));
IoClientInitializer.setClientAlias(clientAlias);
return new String[0];
}
}
5.实现ImportBeanDefinitionRegistrar接口中registerBeanDefinitions方法
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
/**
* AnnotationMetadata:当前类的注解信息
* BeanDefinitionRegistry:BeanDefinition注册类;
* 把所有需要添加到容器中的bean;调用
* BeanDefinitionRegistry.registerBeanDefinition手工注册进来
*/
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
boolean definition = registry.containsBeanDefinition(Red.class.getName());
boolean definition2 = registry.containsBeanDefinition(Blue.class.getName());
if (definition && definition2) {
// 指定Bean定义信息;(Bean的类型,Bean。。。)
RootBeanDefinition beanDefinition = new RootBeanDefinition(Yellow.class);
// 注册一个Bean,指定bean名
registry.registerBeanDefinition(Yellow.class.getName(), beanDefinition);
}
}
}6.通过实现FactoryBean中的方法注入:
//1. 这里的接口泛型参数为要注入Bean的类型
public class MyFactoryBean implements FactoryBean<Department> {
//2.重写的第一个方法返回Bean的实例
@Override
public Department getObject() throws Exception {
return new Department();
}
//3.重写的第二个方法返回Bean的类型
@Override
public Class<?> getObjectType() {
return Department.class;
}
//4.重写的第三个方法返回一个boolean值,决定该Bean的类型是单例还是多实例。这里返回true,为单例。
@Override
public boolean isSingleton() {
return true;
}
}
二、有时会有需求:根据不通条件判断是否注入该Bean
spring中提供了很多个条件注入的注解,全都是 @ConditionalOnxxx,这边例举几个:
@ConditionalOnBean(A.class) //需要注入了A的前提下才会注入B
@Bean
public B b(){
return new B();
}
@ConditionalOnMissingBean(B.class) //当容器中不存在B时会注入B
@Bean
public B b(){
return new B();
}
//当有spring.batch.job.names配置,且值为order-cancelorder才注入
@Configuration
@ConditionalOnProperty(name = "spring.batch.job.names",havingValue = "order-cancelorder")
public class CancelOrderConfig {...}
最近用了一个@ConditionalOnClass,遇到点问题,记录下,该注解可通过判断运行中的包中是否存在该类来动态注入Bean,
使用时必须加在单独一个类上,且类中只能有一个条件注入的Bean,否则就会报classNotFound,不知道是不是我使用错误的问题。
@ConditionalOnClass(MinioOSSClient.class)
public class OSSMinioConfiguration {
@Bean
@ConditionalOnMissingBean
public MinioOSSClient minioOSSClient(OSSProperties ossProperties){
return new MinioOSSClient(ossProperties.getMinio().getEndpoint(),
ossProperties.getMinio().getAccessKey(),
ossProperties.getMinio().getSecretKey(),
ossProperties.getMinio().getBucket());
}
}最后也可自己通过实现Condition接口来自定义注入的条件:
示例(参考自:https://blog.csdn.net/qq_27470131/article/details/79538046)
@Configuration
public class ConditionConfig {
@Conditional(WindowsCondition.class)
@Bean("bill")
public Person bill(){
return new Person("bill",10);
}
@Conditional(LinuxCondition.class)
@Bean("Linus")
public Person person(){
return new Person("Linus",10);
}
}
public class WindowsCondition implements Condition {
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
//获取当前运行环境信息
Environment environment = context.getEnvironment();
//获取当前环境名称
String osName = environment.getProperty("os.name");
return osName.contains("Windows");
}
}
public class LinuxCondition implements Condition {
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
//获取当前运行环境信息
Environment environment = context.getEnvironment();
//获取当前环境名称
String osName = environment.getProperty("os.name");
return osName.contains("Linux");
}
}
版权声明:本文为u010737670原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。