CDI具有Specialization的功能,我在春天的世界里寻找它。
详情。
在CDI中,@Specializes
注释允许人们通过覆盖它来改变bean的行为。这对于该bean的用户是完全透明的,例如如果我们有
public class OneBean {
public String whoAmI() { return "OneBean"; }
}
@Specializes
public class AnotherBean extends OneBean {
@Override
public String whoAmI() { return "AnotherBean"; }
}
我们可以
public class SomewhereElse {
@Inject
OneBean oneBean; // we know nothing of AnotherBean here!
public void guessWhosThere() {
return oneBean.whoAmI(); // yet it returns "AnotherBean"
}
}
只要有OneBean
实际使用AnotherBean
,这就非常有用。例如,如果OneBean
位于one.jar
且AnotherBean
位于another.jar
,我们可以通过重新配置类路径来更改bean的行为。
问题。 Spring中是否也存在类似专业化的内容?
我只能找到@Primary
注释,但是它具有不同的语义:@Primary
不会替换一个bean,而只会将多个备选项中的一个标记为 primary 一。特别是,正如我所理解的那样,我无法构建一个深层继承层次结构,因为它可以@Specializes
。
答案 0 :(得分:2)
简短回答 在春季4,这是不可能的。期。尽管如此,在2016年,Spring的过时依赖注入模型仍然无法做到这一点。
答案 1 :(得分:1)
看起来春天没有类似的注释,但你可以通过@Qualifier来实现它。
豆类:
@Resource("oneBean")
public class OneBean {
public String whoAmI() { return "OneBean"; }
}
@Resource("anotherBean")
public class AnotherBean extends OneBean {
@Override
public String whoAmI() { return "AnotherBean"; }
}
SomewhereElse:
public class SomewhereElse {
@Autowired
@Qualifier("anotherBean")
OneBean oneBean;
public void guessWhosThere() {
return oneBean.whoAmI(); // returns "AnotherBean"
}
}
<强>编辑。强>
您也可以开发自己的注释并在 BeanPostProcessor 中使用它,查看spring docs here
或者甚至更好地使用 CustomAutowireConfigurer ,请参阅here
答案 2 :(得分:0)
如果我们假设:
public interface BeanInterface {
String whoAmI();
}
@Named
public class OneBean implements BeanInterface {
@Override
public String whoAmI() { return "OneBean"; }
}
@Named
@Primary
public class AnotherBean implements BeanInterface {
@Inject
OneBean oneBean;
@Override
public String whoAmI() {
String oneBeanId = oneBean.whoAmI();
return "AnotherBean calling: " + oneBeanId;
}
}
我们可以,而不是扩展OneBean
用一些额外的行为来装饰它。此解决方案的缺点是BeanInterface
的每个方法都必须在AnotherBean
中实施并委托给其oneBean
字段。
答案 3 :(得分:0)
您可以使用@Qualifier执行此操作。
例如:
bean类:
@Component("loginMB")
@Scope(value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS)
public class LoginMB extends AdminSession implements Serializable {
注入点:
@Component
public class AdminFilter implements Filter {
private static final String FACES_RESOURCES = "javax.faces.resource";
private static final Logger log = Logger.getLogger(AdminFilter.class.getName());
private boolean disableFilter;
private String loginPage;
private String errorPage;
private String indexPage;
@Autowired
@Qualifier(value = "loginMB")
AdminSession adminSession;
答案 4 :(得分:0)
使用 Spring boot,您可能会通过利用其自动配置机制获得类似的结果,例如带有 bean condition,例如 @ConditionalOnMissingBean
:
public class OneBean {
public String whoAmI() { return "OneBean"; }
}
@Configuration
public class OneConfiguration {
@Bean
@ConditionalOnMissingBean
public OneBean getBean() { return new OneBean(); }
}
@Component
public class AnotherBean extends OneBean {
@Override
public String whoAmI() { return "AnotherBean"; }
}
但是,如果您不确定哪些配置是专门的,则必须确保所有配置都相应地构建:
public class OneBean {
public String whoAmI() { return "OneBean"; }
}
public class AnotherBean extends OneBean {
@Override
public String whoAmI() { return "AnotherBean"; }
}
public class YetAnotherBean extends AnotherBean {
@Override
public String whoAmI() { return "YetAnotherBean"; }
}
@Configuration
public class OneConfiguration {
@Bean
@ConditionalOnMissingBean
public OneBean getBean() { return new OneBean(); }
}
@Configuration
public class AnotherConfiguration {
@Bean
@ConditionalOnMissingBean
public AnotherBean getBean() { return new AnotherBean(); }
}
@Configuration
public class YetAnotherConfiguration {
@Bean
@ConditionalOnMissingBean
public YetAnotherBean getBean() { return new YetAnotherBean(); }
}
// and so on...