Java Spring:委托给自定义代理包装器进行接口注入
在一个非常大的遗留应用程序中,我有一些接口和类,它们不实现这些接口 接口是基于类生成的,因此签名是相同的(除了接口在顶部添加了另一个异常),并且名称是相似的(因此很容易从接口名称中找到类名) 为了得到接口的实现,我们进行了大量的处理和日志调用,但基本上使用Java Spring:委托给自定义代理包装器进行接口注入,java,spring,annotations,aop,factory,Java,Spring,Annotations,Aop,Factory,在一个非常大的遗留应用程序中,我有一些接口和类,它们不实现这些接口 接口是基于类生成的,因此签名是相同的(除了接口在顶部添加了另一个异常),并且名称是相似的(因此很容易从接口名称中找到类名) 为了得到接口的实现,我们进行了大量的处理和日志调用,但基本上使用java.lang.reflect.Proxy来委托给类。它看起来是这样的: // This will create a proxy and invoke handler that calls HelloWorld.doSomething He
java.lang.reflect.Proxy
来委托给类。它看起来是这样的:
// This will create a proxy and invoke handler that calls HelloWorld.doSomething
HelloWorldInterface i = MyProxyUtil.getInstance(HelloWorldInterface.class);
i.doSomething();
public interface HelloWorldInterface {
public void doSomething() throws Exception;
}
public class HelloWorld {
public void doSomething() {
//something
}
}
通过Spring注释处理,是否可以一般地@Autowire
所有类型为*接口的字段
,并让Spring使用MyProxyUtil.getInstance(*Interface.class)
注入实现
以致
@Autowire HelloWorldInterface a;
HelloWorldInterface b = MyProxyUtil.getInstance(HelloWorldInterface.class);
@Autowire AnotherInterface c;
AnotherInterface d = MyProxyUtil.getInstance(AnotherInterface.class);
a == b
c == d
如果我没有看错,您应该能够在JavaConfig@Configuration注释类中定义它们,然后在其他地方使用它们 从文档()中: 你可以做类似的事情:
@Configuration
public class InterfaceConfig {
@Bean
public HelloWorldInterface helloWorldInterface() {
return MyProxyUtil.getInstance(HelloWorldInterface.class);
}
}
在这一点上,Spring将在需要bean时使用该定义
您必须以某种方式链接@Configuration类(类路径扫描、编程等),但这取决于您如何设置应用程序上下文
我认为这应该行得通。我经常使用JavaConfig,但从来没有像这样使用过。但这似乎是合理的。是的,您需要实现一个
自动解算器
例如:
public class ProxyAutowiredCandidateResolver extends SimpleAutowireCandidateResolver {
@Override
public Object getSuggestedValue(DependencyDescriptor descriptor) {
String dependencyClassName = descriptor.getDependencyType().getSimpleName();
if (dependencyClassName.endsWith("Interface")) {
return MyProxyUtil.getInstance(descriptor.getDependencyType());
}
return super.getSuggestedValue(descriptor);
}
}
您可以使用BeanFactoryPostProcessor
在应用程序上下文中对其进行配置:
public class AutowireCandidateResolverConfigurer implements BeanFactoryPostProcessor {
private AutowireCandidateResolver autowireCandidateResolver;
public void postProcessBeanFactory(
ConfigurableListableBeanFactory beanFactory) throws BeansException {
DefaultListableBeanFactory bf = (DefaultListableBeanFactory) beanFactory;
bf.setAutowireCandidateResolver(autowireCandidateResolver);
}
public AutowireCandidateResolver getAutowireCandidateResolver() {
return autowireCandidateResolver;
}
public void setAutowireCandidateResolver(
AutowireCandidateResolver autowireCandidateResolver) {
this.autowireCandidateResolver = autowireCandidateResolver;
}
}
<bean id="autowireCandidateResolverConfigurer" class="AutowireCandidateResolverConfigurer">
<property name="autowireCandidateResolver">
<bean class="ProxyAutowiredCandidateResolver" />
</property>
</bean>
公共类AutowireCandidateResolverConfigure实现BeanFactoryPostProcessor{
专用Autowire CandidateResolver Autowire CandidateResolver;
公共无效后处理BeanFactory(
ConfigurableListableBeanFactory(beanFactory)引发BeanException{
DefaultListableBeanFactory bf=(DefaultListableBeanFactory)beanFactory;
bf.setAutowireCandidateResolver(autowireCandidateResolver);
}
公共AutowireCandidateResolver getAutowireCandidateResolver(){
返回自动线解算器;
}
公共无效设置自动线解算器(
AutowireCandidateResolver(AutowireCandidateResolver){
this.autowireCandidateResolver=autowireCandidateResolver;
}
}
在配置中定义这些bean中的每一个(有数百个)对我来说并不实际。相反,我正在寻找一种方法,通过MyProxyUtil解析名称以接口结尾的所有接口。我没有理解这一部分。如果它都是遗留的,那么编写一个脚本一次性生成代码就不难了。虽然Jose的回答听起来很有趣,但我对此并不熟悉。代理是否已经由spring管理?您是否正在尝试对它们执行任何需要spring管理的操作?抱歉,我很难弄清楚您是如何实际配置它以供使用的?我将向我的applicationContext.xml中添加什么?@casenelson您可以使用BeanFactoryPostprocessor
配置AutowireCandidateResolver
使用解决方案注入环境时出现问题->@MariuszS在配置类中直接注册BFPP时出现问题。因为必须实例化配置类才能创建BFPP,所以在注册BPP之前,由于实例化发生得太早,所以跳过了bean后处理。您可以使用静态方法注册BFPP以避免问题。有关更多信息,请参阅。感谢提供有关静态的提示!
public class AutowireCandidateResolverConfigurer implements BeanFactoryPostProcessor {
private AutowireCandidateResolver autowireCandidateResolver;
public void postProcessBeanFactory(
ConfigurableListableBeanFactory beanFactory) throws BeansException {
DefaultListableBeanFactory bf = (DefaultListableBeanFactory) beanFactory;
bf.setAutowireCandidateResolver(autowireCandidateResolver);
}
public AutowireCandidateResolver getAutowireCandidateResolver() {
return autowireCandidateResolver;
}
public void setAutowireCandidateResolver(
AutowireCandidateResolver autowireCandidateResolver) {
this.autowireCandidateResolver = autowireCandidateResolver;
}
}
<bean id="autowireCandidateResolverConfigurer" class="AutowireCandidateResolverConfigurer">
<property name="autowireCandidateResolver">
<bean class="ProxyAutowiredCandidateResolver" />
</property>
</bean>