我有一个需求,我在Spring项目中定义了一个契约,并希望在部署期间自动连接一个外部JAR,以实现契约(一组接口)。我不想强制外部JAR依赖于Spring,以便它尽可能灵活。在我的Spring项目中,无论我在哪里使用我的契约接口,都不可能使用外部JAR中的类作为autowire替换吗?让我举一个例子来解释:
Spring project:
@Controller
public class MyController {
@Autowired
private MyInterface interface;
}
现在,实现契约接口的JAR可能是由客户端提供的,我可能事先不知道包名,它甚至可能是一个非Spring项目,所以它可能不会用@Component注释声明。
例如
public class CustomerClass implements MyInterface {
}
现在,在我的spring项目中,有没有一种方法可以注入CustomerClass来代替MyInterface?我希望我的问题很清楚。
感谢
@Paddy,关于您所关心的是否可以用传统的XML方式来实现同样的目标。以下是演示如何实现它的示例代码。注意:接口MyInterface不能以这种方式动态,因为控制器持有MySinterface Spring应用程序上下文配置: MyInterface和两个不同的实现类 类路径下的test.properties文件(可以使用ant脚本和maven概要文件更改属性值) web层控制器(您可以注入基于动态bean候选者的实现类)<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations" value="classpath:test.properties" />
</bean>
<bean id="myInterface" class="${myinterface.impl}"></bean>
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";
}
}
myinterface.impl=au.net.test.MyClass2
@Autowired
private MyInterface myInterface;
好的,我明白你的意思了。如果是这样的话,您的问题标题应该是如何通过Spring Container注入动态类型的类现在让我们谈谈解决方案。首先,您需要有某种属性来保存完全限定的类名。然后,您可以在运行时将自定义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"属性值驱动,而不是硬编码。
您可以将工厂bean与工厂方法一起使用
<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;
}
}
所以基本上,这里的想法是,您必须创建自己的工厂类和工厂方法来创建实例,根据您的工厂,它可能会创建singleton或prototype istance。然后把剩下的工作留给spring容器。