弹簧有选择地使用实现,而不是接口
问题描述:
找不到一个明确的答案,所以问这里 - 是否可以打开只有一个bean的CGLIB代理?场景如下 - 我有一个自动装配的类,没有实现任何接口,现在我想添加一个接口,它将覆盖它的一小部分方法。是否有可能使用CGLIB而不影响Spring的默认行为(首选JDK动态代理)的这个类?
我正在使用基于java的配置。弹簧有选择地使用实现,而不是接口
答
那里(目前)没有任何支持开箱即可为单个类启用基于类的代理。相反,您必须自己创建代理。这样做的缺点是你需要一些关于Spring如何工作的知识(我碰巧拥有:))。
您应该/可以使用ProxyFactory
或ProxyFactoryBean
为您的给定类创建基于类的代理。您的@Bean
方法将返回代理而不是实际的类。 Spring然后足够聪明(至少它应该)检测它已经是代理,而不是代理它再次它应该添加建议到已经创建的代理。为了在不破坏汽车布线和Spring给你的所有其他好东西的情况下进行这项工作,你可能需要创建一个处理这个问题的特定的BeanPostProcessor
。
public YourBeanPostProcessor implements BeanPostProcessor {
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof YourBean) {
ProxyFactory factory = new ProxyFactory(bean);
factory.setProxyTargetClass(true);
return factory.getProxy();
}
return bean;
}
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
}
把这个注册为一个bean,就像你通常会用BeanPostProcessor
做的那样。
@Bean
public static YourBeanPostProcessor yourBeanPostProcessor() {
return new YourBeanPostProcessor();
}
现在你有一个预先创建的基于类的代理,它应该被Spring检测和使用。
为什么?如果您需要在使用界面时对具体实例进行编程,那么您做错了,或者至少您的界面与您试图表达的意图不符。 –
@ M.Deinum我知道,我知道,非常感谢。你知道这个问题的答案吗? – skwisgaar
答案基本上不是这样做,并有一个适当的接口和使用。如果你只希望这个单一的实例代理,你需要手动创建代理或启用基于类的代理,然后它将用于一切。 –