先感叹一下:最近的项目真的很奇葩!!!

需求是这样的:我们的项目中引用了两个jar包,这两个jar包是其他项目组提供的,不能修改!

奇葩的是:这两个jar中都需要引用方提供一个相同idbean,而bean的定义却是不同的,也就是虽然id相同,但他们对应的却是两个不同的java类,导致出现的问题是:该id对应的java类满足了第一个jar包的要求,则不能满足第二个jar包的要求,满足了第二个jar包的要求,则不能满足第一个jar包的要求,导致spring容器在启动时就报错。

 

那么,该怎么解决该问题呢?如何做才能符合两个jar包的需求呢?经过仔细思考:发现通过java类的继承可以巧妙的实现该需求,现示例如下:

spring主配置文件:

applicationContext.xml


其中:app1.xml和app2.xml是两个jar包app1.jar和app2.jar中对应的spring配置文件


app1.jar和app2.jar中主要就有一个java编译好后的class文件和一个配置文件:

其中app1.jar中的java文件和配置文件分别为:

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依赖的obj类型错误,注入的不是mypacke.Obj1");
			}
		}
		System.out.println("package.Test1");
		return "package.Test1";
	}



}

app1.xml



app2.jar中的java类和配置文件分别为:

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依赖的obj类型错误,注入的不是mypacke.Obj2");
			}
		}
		System.out.println("package.Test2");
		return "package.Test2";
	}




}


app2.xml:


其中:mybean是需要引用方提供的,这两个jar中需要引用方提供的bean的id都是一样的,这就导致了文章开始所提到的的问题。


测试程序:

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 ClassPathXmlApplicationContext("applicationContext.xml");
	
	/*	System.out.println(((Test1)context.getBean("child1")).getObj().getClass().getName());
		System.out.println(((Test1)context.getBean("child2")).getObj().getClass().getName());*/
		
		
		System.out.println(((Test1)context.getBean("test1")).getObj().getClass().getName());
		System.out.println(((Test2)context.getBean("test2")).getObj().getClass().getName());
		

	}

}


运行得到的两个bean是相同的bean,不符合要求!!





解决方案:

引进两个子类Child1和Child2,分别继承jar包需要的Test1和Test2

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依赖的obj注入的类型错误,注入的不是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依赖的obj注入的类型错误,注入的不是mypacke.World");
			}
		}
		return "package.Test2";
	}

	


}



添加一个新的spring辅助配置文件:



在spring主配置文件做修改如下:


测试程序:

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 ClassPathXmlApplicationContext("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"));*/
	}

}

运行得到:获取的是不同的bean,也就是间接实现了两个jar包中需要提供同名id的bean,但bean对应的java类是不同的java类的需求!


总结:实际上就是面向对象的lisp原则,就是里氏替换原则,具体点就是凡是父类出现的地方,都可以用子类来代替!

例子很简单,但是能说明问题。


github上源码地址:https://github.com/iamzken/kuaiqian/tree/master/spring-same-id-bean-test


相关文章:

  • 2021-08-31
  • 2021-06-25
  • 2022-12-23
  • 2022-12-23
  • 2021-10-18
  • 2021-11-06
  • 2022-12-23
猜你喜欢
  • 2022-12-23
  • 2022-12-23
  • 2021-09-26
  • 2021-09-14
  • 2022-01-28
  • 2022-12-23
  • 2021-11-04
相关资源
相似解决方案