• [置顶] spring巧用继承解决bean的id相同的问题


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

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

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

     

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

    spring主配置文件:

    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>

    其中: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

    <?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>


    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:

    <?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>

    其中: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辅助配置文件:

    <?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>


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

    <?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>


    测试程序:

    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


  • 相关阅读:
    hadoop学习笔记(一):hadoop集群搭建
    CITA 快速入门
    Oracle数据库常用十一大操作指令
    Shutdown Abort :亚马逊成功迁移物流业务中最后一个Oracle数据库
    从B站源码泄露事件入手,说一下团队协作中版本管理的安全意识
    Docker三剑客:Compose、Machine和Swarm
    TensorFlow学习笔记之图像大小调整(最全可运行的代码)
    面试Python工程师,这几道编码题有必要背背,Python面试题No8
    WFP之位图效果
    使用ScriptX控件进行Web横向打印
  • 原文地址:https://www.cnblogs.com/iamconan/p/7383521.html
Copyright © 2020-2023  润新知