Spring中是否有一种干净的方式(没有XML)将接口连接到调用处理程序?目前我必须做这样的事情:
@Inject
private ServiceProxyCreator services;
private MyServiceInterface service;
private MyServiceInterface getService() {
if ( service == null )
service = services.createProxy( MyServiceInterface.class );
return service;
}
其中#createProxy只是这样的实现:
@SuppressWarnings( "unchecked" )
public <T> T createProxy( Class<T> type ) {
JobRpcHandler handler = new JobRpcHandler();
handler.setServiceName( type.getSimpleName() );
return (T) Proxy.newProxyInstance(
type.getClassLoader(), new Class[]{type}, handler );
}
但是在Spring中使用所有这些DI功能似乎我应该能够自动执行此操作,以便我可以简单地执行以下操作:
@Inject
private MyService service;
以某种方式定制注入,我不知道在幕后创建代理而无需调用#createProxy。
有关更优雅方法的任何建议吗?
答案 0 :(得分:1)
看看FactoryBean。你可以这样写自己的:
public class ServiceProxyFactoryBean implements FactoryBean<Object>
private Class<T> type;
public DutySetFactoryBean(Class<?> type) {
this.type = type;
}
@Override
public synchronized Object getObject() {
JobRpcHandler handler = new JobRpcHandler();
handler.setServiceName(type.getSimpleName());
return Proxy.newProxyInstance(type.getClassLoader(), new Class[]{type}, handler);
}
@Override
public Class<?> getObjectType() {
return type;
}
@Override
public boolean isSingleton() {
return true;
}
}
并在配置文件中使用它:
<bean class="package.name.ServiceProxyFactoryBean">
<constructor-arg>
<value type="java.lang.Class">package.name.MyServiceInterface</value>
</constructor-arg>
</bean>
或者,使用Java配置,那样:
@Bean
public ServiceProxyFactoryBean myServiceFactoryBean() {
return new ServiceProxyFactoryBean(MyServiceInterface.class);
}
@Bean
public MyServiceInterface myService() {
return (MyServiceInterface)sessionFactoryBean().getObject();
}
如果要为类路径中的所有带注释的接口自动创建代理,可以定义自己的BeanDefinitionRegistryPostProcessor。在这里,您必须使用以下模式使用ResourceLoader扫描类路径:
MetadataReaderFactory metadataReaderFactory = new SimpleMetadataReaderFactory();
Resource[] resources = patternResolver.getResources(
"classpath*:" + packageName.replace('.', '/') + "/**/*.class");
for (Resource resource : resources) {
MetadataReader reader = metadataReaderFactory.getMetadataReader(resource);
if (!reader.getAnnotationMetadata().isAnnotated(
MyProxyAnnotation.class.getName())) {
continue;
}
Class<?> cls = Class.forName(reader.getClassMetadata().getClassName(), true,
resourceLoader.getClassLoader());
String factoryBeanName = createNewName();
BeanDefinitionBuilder bdb = BeanDefinitionBuilder.genericBeanDefinition(
ServiceProxyFactoryBean.class);
bdb.addConstructorArgValue(cls);
registry.registerBeanDefinition(factoryBeanName, bdb.getBeanDefinition());
bdb = BeanDefinitionBuilder.genericBeanDefinition(cls);
bdb.setFactoryBean(factoryBeanName, "getBean");
registry.registerBeanDefinition(createNewName(), bdb.getBeanDefinition());
}
现在,对于所有使用MyProxyAnnotation
注释的接口,您都有一个代理,您可以将其注入到bean中。例如:
@MyProxyAnnotation
public interface MyServiceInterface {
void foo();
}
和
@Component
public class MyBean {
@Autowired
private MyServiceInterface myService;
}
这就是全部。无需配置。
我不确定此代码是否有效甚至可编译。这不是最终的解决方案,只是你应该走向的一般方式。所以你应该研究和调试一下。