我正在开发一个庞大的应用程序,其中有数千个Spring bean使用注释注册并与@Autowired相互连线 该应用程序将作为"核心"应用程序和我们的客户应该能够自定义添加或覆盖bean。 如果他们需要修改bean,那么通常的方法是扩展类并使Spring上下文注册自定义类而不是" core"一,但这样做Spring会抛出一个错误,因为它找到了同一个接口的两个实现。 我怎样才能做到这一点? 我们的客户如何取消注册"核心类和regster是自定义的吗?
非常感谢!
答案 0 :(得分:2)
You can use a Qualifier. They identify beans by name, not by type.
您还可以将字段设置为bean列表。
@Autowire
private Foobar[] customizedAndCore;
答案 1 :(得分:2)
最简单的处理方法是使用@Primary
注释。 Spring将注入主数据库,而不是使用重复的bean异常进行失败。
答案 2 :(得分:1)
这里是使用@Qualifier和@Autowired注释的基本草稿
以下是Student.java文件的内容:
public class Student {
private Integer age;
private String name;
public void setAge(Integer age) {
this.age = age;
}
public Integer getAge() {
return age;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
以下是Profile.java文件的内容:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
public class Profile {
@Autowired
@Qualifier("student1")
//@Qualifier("student2")
private Student student;
public Profile(){
System.out.println("Inside Profile constructor." );
}
public void printAge() {
System.out.println("Age : " + student.getAge() );
}
public void printName() {
System.out.println("Name : " + student.getName() );
}
}
以下是MainApp.java文件的内容:
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MainApp {
public static void main(String[] args) {
ApplicationContext context =
new ClassPathXmlApplicationContext("Beans.xml");
Profile profile = (Profile) context.getBean("profile");
profile.printAge();
profile.printName();
}
}
考虑以下配置文件Beans.xml的示例:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<context:annotation-config/>
<!-- Definition for profile bean -->
<bean id="profile" class="com.Profile">
</bean>
<!-- Definition for student1 bean -->
<bean id="student1" class="com.Student">
<property name="name" value="Zara" />
<property name="age" value="11"/>
</bean>
<!-- Definition for student2 bean -->
<bean id="student2" class="com.Student">
<property name="name" value="Nuha" />
<property name="age" value="2"/>
</bean>
</beans>
答案 3 :(得分:1)
我认为你有三种一般方法......
第一种选择意味着客户希望用自己的“核心”取代“核心”时,只需要创建一个新工厂,这是核心工厂的孩子。只要孩子中的bean与核心中的on具有相同的名称,一切都很好。
第二个意味着默认bean将处于“默认”(无配置文件),然后替换将在特定配置文件中。当该配置文件处于活动状态时,这些替换bean将覆盖无配置文件中的bean。替换仅针对bean名称而不是针对类型进行更改,因此在使用此方法时,您必须确保新bean与原始bean具有相同的名称,而注入注释指定bean的名称ala
@Inject
@Named("dataSource")
private DataSource storageRepository;
第三个选项要求在使用bean
时在注释中出现以下内容@Resource(name = "${dataSource}")
private DataSource dataSource;
然后在使用它时,您将需要一个名为dataSource的参数,并且需要将其设置为要注入该位置的特定bean名称。 例如
的dataSource = enterpriseDataSource
然后将名为enterpriseDataSource的bean注入该位置。
我认为它接近1的方式可以说是最接近你正在寻找的东西。听起来你有一个“核心”工厂,你提供客户所依赖的工厂,因此他们并不真正拥有你的源代码。 AFAIK方法1也是唯一允许按类型自动装配的方法。
方法2更适合您想要在不同模式下运行...即开发,测试或生产模式。原因是您只能覆盖不在配置文件中的bean。使用这种方法,您不能使用另一个配置文件中的bean覆盖已在配置文件中的bean。
方法3实际上是我最常使用的方法,因为它不需要配置文件或工厂层次结构,只需更改参数的值就允许交换不同的bean。但我希望我不必继续指定bean名称。其他可能的东西 - 以及我经常使用的东西 - 通过激活不同的配置文件来交换一个全新的配置文件。