是否有可能在春天自动装配没有给定限定符的bean?用例是拥有所有bean的列表,但排除一个:
@Autowired
@NotQualifier("excludedBean") //
List someBeanList;
public class Bean1 implements SomeBean {}
public class Bean2 implements SomeBean {}
@Qualifier("excludedBean")
public class Bean3 implements SomeBean {}
在上面的示例中,someList应该包含Bean1和Bean2的实例,但不包含Bean3.
(注意:我知道相反的方法可行,即向Bean1和Bean2添加一些限定符,然后使用该限定符自动装配.)
编辑:进一步澄清:
>所有bean都处于spring环境中(也是被排除的bean).
>配置需要基于注释,而不是基于xml.因此,例如关掉自动候选人does not work.
> bean的自动装配功能必须保持一般.换句话说,我想从注入点List< SomeBean>中排除bean. someBeanList;,但我想在其他地方自动装配它.
解决方法:
主要观点它的排除bean是在上下文中,但没有注入到排除条件的某些情况下.
你可以使用带有自定义注释和BeanPostProcessor的限定符来排除bean. (我为简单的例子做了例子,对于bean类型的集合,但你可以扩展它)
排除注释:
@Component
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ExcludeBeanByQualifierForCollectionAutowired {
String qualifierToExcludeValue();
Class> aClass();
}
带注射的豆后处理器
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.stereotype.Component;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collection;
@Component
public class ExcludeAutowiredBeanPostProcessor implements BeanPostProcessor {
@Autowired
private ConfigurableListableBeanFactory configurableBeanFactory;
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) {
Field[] fields = bean.getClass().getDeclaredFields();
for (Field field : fields) {
field.setAccessible(true);
ExcludeBeanByQualifierForCollectionAutowired myAutowiredExcludeAnnotation = field.getAnnotation(ExcludeBeanByQualifierForCollectionAutowired.class);
if (myAutowiredExcludeAnnotation != null) {
Collection beanForInjection = new ArrayList<>();
String[] beanNamesOfType = configurableBeanFactory.getBeanNamesForType(myAutowiredExcludeAnnotation.aClass());
for (String injectedCandidateBeanName : beanNamesOfType) {
Object beanCandidate = configurableBeanFactory.getBean(injectedCandidateBeanName);
Qualifier qualifierForBeanCandidate = beanCandidate.getClass().getDeclaredAnnotation(Qualifier.class);
if (qualifierForBeanCandidate == null || !qualifierForBeanCandidate.value().equals(myAutowiredExcludeAnnotation.qualifierToExcludeValue())) {
beanForInjection.add(bean);
}
}
try {
field.set(bean, beanForInjection);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) {
return bean;
}
}
和例子:
public class ParentBean {}
public class Bean1Included extends ParentBean {}
public class Bean2Included extends ParentBean {}
public class Bean3Included extends ParentBean {}
@Qualifier("excludedBean")
public class BeanExcluded extends ParentBean {}
组态
@Configuration
public class ConfigurationBean {
@Bean
public Bean1Included getBean1(){
return new Bean1Included();
}
@Bean
public Bean2Included getBean2(){
return new Bean2Included();
}
@Bean
public Bean3Included getBean3(){
return new Bean3Included();
}
@Bean
public BeanExcluded getExcludedBean(){
return new BeanExcluded();
}
@Bean
public ExcludeAutowiredBeanPostProcessor excludeAutowiredBeanPostProcessor(){
return new ExcludeAutowiredBeanPostProcessor();
}
}
结果:
@ContextConfiguration(classes = ConfigurationBean.class)
public class ConditionTest {
@Autowired
private ApplicationContext context;
@Autowired
private BeanExcluded beanExcluded;
@ExcludeBeanByQualifierForCollectionAutowired(qualifierToExcludeValue = "excludedBean" , aClass = ParentBean.class)
private List beensWithoutExclude;
context.getBeanNamesForType(ParentBean.class);//returns all sub type for ParentBean
beensWithoutExclude; // only bean1 ,bean2 , bean3 and NOT beanExcluded
beanExcluded;//been in application context
}
标签:java,spring,dependency-injection
来源: https://codeday.me/bug/20190823/1699984.html