First sigh: The recent project is really wonderful ...
The requirement is this: two jar packages are referenced in our project, and these two jar packages are provided by other project teams and cannot be modified.
The wonderful thing is: All two jars require a bean with the same ID as the reference, and the bean's definition is different, that is, although the IDs are the same, they correspond to two different Java classes. The problem that occurs is that the corresponding Java class for this ID satisfies the requirements of the first jar package, does not meet the requirements of the second jar package, meets the requirements of the second jar package, and does not meet the requirements of the first jar package, causing the spring container to error when it starts.
so, how to solve the problem. What to do to meet the requirements of two jar packs. After a careful thought: discovering that the need can be implemented subtly through inheritance of Java classes, the following examples are:
Spring master configuration file:
Applicationcontext.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:p=" http://www.springframework.org/ schema/p "
xsi:schemalocation=" Http://www.springframework.org/schema/beans http://www.springframework.org/ Schema/beans/spring-beans-3.1.xsd ">
<import resource=" Classpath*:app1.xml "/>
<import Resource= "Classpath*:app2.xml"/>
<import resource= "Classpath:appContext1.xml"/>
<!-- <import resource= "Classpath:appContext2.xml"/> -->
</beans>
Where: App1.xml and App2.xml are the corresponding spring configuration files in two jar packs App1.jar and App2.jar
The main App1.jar and App2.jar have a Java-compiled class file and a configuration file:
the Java files and configuration files in App1.jar are:
Test1.java
Package mypackage;
public class Test1 {
private Object obj;
Public Object Getobj () {return
obj;
}
public void Setobj (Object obj) {
this.obj = obj;
}
@Override public
String toString () {
if (!this.getobj (). GetClass (). GetName (). Equals ("MyPackage. Obj1 ")) {
try {
throw new Exception ();
} catch (Exception e) {
System.err.println (" Test1---> MyPackage. Test1 dependent obj type error, injection is not mypacke. Obj1 ");
}
}
SYSTEM.OUT.PRINTLN ("package.") Test1 ");
Return "package. Test1 ";
}
}
App1.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:p=" http://www.springframework.org/ schema/p "
xsi:schemalocation=" Http://www.springframework.org/schema/beans http://www.springframework.org/ Schema/beans/spring-beans-3.1.xsd ">
<bean id=" test1 "class=" MyPackage. Test1 ">
<property name=" obj ">
<ref bean=" Mybean "/>
</property>
</bean >
</beans>
the Java classes and configuration files in App2.jar are:
Test2.java
Package mypackage;
public class Test2 {
private Object obj;
Public Object Getobj () {return
obj;
}
public void Setobj (Object obj) {
this.obj = obj;
}
@Override public
String toString () {
if (!this.getobj (). GetClass (). GetName (). Equals ("MyPackage. Obj2 ")) {
try {
throw new Exception ();
} catch (Exception e) {
System.err.println (" Test2---> MyPackage. Test2 dependent obj type error, injection is not mypacke. Obj2 ");
}
}
SYSTEM.OUT.PRINTLN ("package.") Test2 ");
Return "package. Test2 ";
}
}
App2.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:p=" http://www.springframework.org/ schema/p "
xsi:schemalocation=" Http://www.springframework.org/schema/beans http://www.springframework.org/ Schema/beans/spring-beans-3.1.xsd ">
<bean id=" test2 "class=" MyPackage. Test2 ">
<property name=" obj ">
<ref bean=" Mybean "/>
</property>
</bean >
</beans>
Where: Mybean is provided by the reference party, the ID of the bean to be provided by the reference party in these two jars is the same, which leads to the problem mentioned in the beginning of the article.
Test Program:
Package mypackage;
Import Org.springframework.context.ApplicationContext;
Import Org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test {public
static void Main (string[] args) {
ApplicationContext context = new Classpathxmlapplicat Ioncontext ("Applicationcontext.xml");
/* System.out.println ((Test1) Context.getbean ("Child1"). Getobj (). GetClass (). GetName ());
System.out.println ((Test1) Context.getbean ("Child2")). Getobj (). GetClass (). GetName ());
(((Test1) Context.getbean ("Test1")). Getobj (). GetClass (). GetName ());
System.out.println ((Test2) Context.getbean ("Test2")). Getobj (). GetClass (). GetName ());
}
The two beans that were run are the same bean and do not meet the requirements.
Solution:
introduce two subclass Child1 and Child2 to inherit the Test1 and Test2 that the jar package needs, respectively
Child1.java
Package mypackage;
public class Child1 extends Test1 {
private Object obj;
Public Object Getobj () {return
obj;
}
public void Setobj (Object obj) {
this.obj = obj;
}
@Override public
String toString () {
if (!this.getobj (). GetClass (). GetName (). Equals ("MyPackage. Hello ")) {
try {
throw new Exception ();
} catch (Exception e) {
System.err.println (" Child1---> MyPackage. Test dependent obj injection type error, injected not Mypacke. Hello ");
}
Return "package. Test1 ";
}
}
Child2.java
Package mypackage;
public class Child2 extends Test2 {
private Object obj;
Public Object Getobj () {return
obj;
}
public void Setobj (Object obj) {
this.obj = obj;
}
@Override public
String toString () {
if (!this.getobj (). GetClass (). GetName (). Equals ("MyPackage. World ") {
try {
throw new Exception ();
} catch (Exception e) {
System.err.println (" Child2---> MyPackage. Test2 Dependent obj injection type error, not injected Mypacke. World ");
}
Return "package. Test2 ";
}
}
to add a new spring secondary configuration file:
<?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:p=" http://www.springframework.org/ schema/p "
xsi:schemalocation=" Http://www.springframework.org/schema/beans http://www.springframework.org/ Schema/beans/spring-beans-3.1.xsd ">
<bean id=" obj1 "class=" MyPackage. Obj1 "></bean>
<bean id=" obj2 "class=" MyPackage. Obj2 "></bean>
<bean id=" Mybean1 "class=" MyPackage. Obj2 "></bean>
<bean id=" mybean2 "class=" MyPackage. Obj2 "></bean>
<bean id=" child1 "class=" MyPackage. Child1 ">
<property name=" obj ">
<ref bean=" Mybean1 "/>
</property>
</ bean>
<bean id= "child2" class= "MyPackage". Child2 ">
<property name=" obj ">
<ref bean=" mybean2 "/>
</property>
</ Bean>
</beans>
make changes in the Spring master configuration file as follows:
<?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:p=" http://www.springframework.org/ schema/p "
xsi:schemalocation=" Http://www.springframework.org/schema/beans http://www.springframework.org/ Schema/beans/spring-beans-3.1.xsd ">
<!--<import resource=" Classpath*:app1.xml "/>
<import Resource= "Classpath*:app2.xml"/>-->
<import resource= "Classpath:appContext1.xml"/>
< Import resource= "Classpath:appContext2.xml"/>
</beans>
Test Program:
Package mypackage;
Import Org.springframework.context.ApplicationContext;
Import Org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test {public
static void Main (string[] args) {
ApplicationContext context = new Classpathxmlapplicat Ioncontext ("Applicationcontext.xml");
SYSTEM.OUT.PRINTLN (context);
/*system.out.println ((Test2) (Context.getbean ("Test2")). Getobj (). GetClass (). GetName ());
System.out.println ((Test) (Context.getbean ("Test")). Getobj (). GetClass (). GetName ()); *//
System.out.println (Context.getbean ("Mybean"). GetClass (). GetName ());
System.out.println (Context.getbean ("child1"));
System.out.println (Context.getbean ("child2"));
/* System.out.println (Context.getbean ("MyPackage"). Hello "));
System.out.println (Context.getbean ("MyPackage"). Hello#1 ")); */
}
}
run: Get the different beans, that is, the indirect implementation of the two jar package needs to provide the same ID of the bean, but the bean corresponding Java class is the requirements of different Java classes!
Summary: In fact, is the object-oriented Lisp principle, is the Richter replacement principle, the specific point is that wherever the parent appears, can be replaced by subclasses.
The example is simple, but it can explain the problem.
GitHub Source Address: Https://github.com/iamzken/kuaiqian/tree/master/spring-same-id-bean-test