我有一个要求,其中我在Spring项目中定义一个合同,并希望在实现合同(接口集)的部署期间自动装配外部JAR。我不想强制外部JAR依赖于Spring,因此它尽可能灵活。在我的Spring项目中,无论在哪里使用我的合同接口,都不可能使用外部JAR中的类作为autowire替换?让我用一个例子来解释:
Spring project:
@Controller
public class MyController {
@Autowired
private MyInterface interface;
}
现在,实现合同接口的JAR可能由客户端提供,我可能不知道包名称,它甚至可能是非Spring项目,因此可能不会使用@Component注释声明它。
e.g。
public class CustomerClass implements MyInterface {
}
现在在我的spring项目中,有没有办法注入CustomerClass来代替MyInterface?我希望我的问题很明确。
由于
答案 0 :(得分:2)
@Paddy, 关于您是否可以通过传统的XML方式来实现相同的目标。以下是显示如何实现它的示例代码。注意:界面 MyInterface 不能以这种方式动态,因为控制器持有 MyInterface 的引用。
Spring应用程序上下文配置:
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations" value="classpath:test.properties" />
</bean>
<bean id="myInterface" class="${myinterface.impl}"></bean>
MyInterface和两个不同的实现类
package au.net.test;
public interface MyInterface {
public String getMessage();
}
public class MyClass1 implements MyInterface{
public String getMessage(){
return "message from class 1";
}
}
public class MyClass2 implements MyInterface{
public String getMessage() {
return "message from class 2";
}
}
classpath下的test.properties文件(可以使用ant脚本和maven配置文件来更改属性值)
myinterface.impl=au.net.test.MyClass2
web layer Controller(您可以根据动态bean候选者注入实现类)
@Autowired
private MyInterface myInterface;
答案 1 :(得分:1)
好的,我告诉你了。如果是这种情况,你的问题标题应该是如何通过Spring容器注入动态类型的类现在让我们来谈谈解决方案。首先,您需要具有某种属性来保存完全限定的类名。然后,您可以在运行时将自定义bean注册到spring容器中。
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:/applicationContext*");
DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) applicationContext.getBeanFactory();
//register your bean at runtime
beanFactory.registerBeanDefinition("myClass", BeanDefinitionBuilder.rootBeanDefinition("au.net.test.DynamicClass").getBeanDefinition());
//retrieve you bean from spring container
Object myBean = applicationContext.getBean("myClass");
//cast to the type of your bean class or interface (be really careful)
System.out.println(((DynamicClass)myBean).getMessage());
package au.net.test;
//this is the bean gets looked up and injected at runtime
public class DynamicClass {
//simple method to verify it is working
public String getMessage(){
return "this is testing message";
}
}
在上面的代码中,您只需要将“au.net.test”属性值驱动而不是硬编码。
答案 2 :(得分:0)
您可以将factory-bean与factory-method
一起使用<bean id="serviceProvider" class="package.ServiceProvider">
<bean id="myInterface"
factory-bean="serviceProvider"
factory-method="createMyInterfaceInstance"/>
//it might or might not to be a singleton factory, depending on your requirement.
public class ServiceProvider{
private static MyInterface myInterface= new CustomerClass();
private ServiceProvider() {}
public MyInterface createMyInterfaceInstance() {
return myInterface;
}
}
所以基本上这里的想法是你必须创建自己的工厂类和工厂方法来创建实例,这取决于你的工厂,它可能会创建单例或原型。然后将剩下的工作留给弹簧容器。