Spring skillfully uses inheritance to resolve the same problem with the Bean's ID

Source: Internet
Author: User

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


Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.