Посмотрите на 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
, у вас есть прокси-сервер, который можно впрыснуть в ваши бобы. Например:
@MyProxyAnnotation
public interface MyServiceInterface {
void foo();
}
И
@Component
public class MyBean {
@Autowired
private MyServiceInterface myService;
}
Это все. Конфигурация не требуется.
Я не уверен, что этот код работает или даже компилируется. Это не окончательное решение, просто общий путь, к которому вы должны двигаться. Поэтому вам следует немного исследовать и отлаживать.
Я даже не уверен, почему я хочу использовать FactoryBean. Я имею в виду, если мне нужно создать метод Bean в одном из моих классов конфигурации для каждого класса, тогда я не могу просто создать прокси-сервер в методе myService Bean? Что мне делать с фабрикой? Я надеялся, что есть способ сделать это, не создавая метод bean для КАЖДОГО удаленного интерфейса. Но я также не мог полностью понять ваш пример. –
@ user1888440, если я понял вас, вы не хотите регистрировать эти бобы вручную? Очень похоже на стереотипы (@Component и другие). Таким образом, вы можете увеличить весну, чтобы сделать это за вас. Я отредактировал свой ответ и добавил там описание того, как вы должны это делать. –