Java 通过调用处理程序注入服务
Spring中是否有一种干净的方式(没有XML)将接口连接到调用处理程序?目前,我必须做如下工作:Java 通过调用处理程序注入服务,java,spring,Java,Spring,Spring中是否有一种干净的方式(没有XML)将接口连接到调用处理程序?目前,我必须做如下工作: @Inject private ServiceProxyCreator services; private MyServiceInterface service; private MyServiceInterface getService() { if ( service == null ) service = services.createProxy( MyServiceI
@Inject
private ServiceProxyCreator services;
private MyServiceInterface service;
private MyServiceInterface getService() {
if ( service == null )
service = services.createProxy( MyServiceInterface.class );
return service;
}
@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 );
}
其中#createProxy只是以下内容的实现:
@Inject
private ServiceProxyCreator services;
private MyServiceInterface service;
private MyServiceInterface getService() {
if ( service == null )
service = services.createProxy( MyServiceInterface.class );
return service;
}
@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 );
}
使用以某种方式定制的注入,我不知道如何在幕后创建代理,而不必调用#createProxy
关于更优雅的方法有什么建议吗?请看。你可以这样写你自己的:
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;
}
}
如果要为类路径中的所有带注释的接口自动创建代理,可以定义自己的代理。在这里,您必须使用以下模式扫描类路径:
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());
}
及
就这些。不需要配置
我不确定这段代码是否有效,甚至无法编译。这不是最终的解决方案,只是一种你应该朝着的一般方式。所以您应该进行一些研究和调试。我甚至不知道为什么要使用FactoryBean。我的意思是,如果我必须为每个类在一个配置类上创建一个Bean方法,那么我就不能在myservicebean方法中创建代理吗?我从工厂得到了什么?我希望有一种方法可以做到这一点,而不必为每个远程接口创建bean方法。但我也不能完全理解您的示例。@user1888440,如果我理解您的意思,您不想手动注册这些bean吗?与原型(@Component和其他)非常相似。所以,你们可以轻轻地伸展弹簧来为你们做这件事。我编辑了我的答案,并在那里添加了你应该如何做的描述。
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
public interface MyServiceInterface {
void foo();
}
@Component
public class MyBean {
@Autowired
private MyServiceInterface myService;
}