加入收藏 | 设为首页 | 会员中心 | 我要投稿 安卓应用网 (https://www.0791zz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 程序设计 > 正文

DI(依赖注入)的进阶

发布时间:2020-05-27 20:07:50 所属栏目:程序设计 来源:互联网
导读:首先写接口类: package com.action;public interface HelloApi {void sayHello();} 其次写实现类: package com.action;public class HelloApiImpl implements HelloApi{private String message;private int index;pub

首先写接口类:

package com.action;
public interface HelloApi {
	void sayHello();
}

其次写实现类:
package com.action;
public class HelloApiImpl implements HelloApi{
	private String message;
	private int index;
	public HelloApiImpl(String message,int index){
		this.message = message;
		this.index = index;
	}
	@Override
	public void sayHello() {
		System.out.println(index+" : "+message);
	}
}

第一阶段:通过构造方法注入的各种方式

第一,配置xml文件,从下面开始的每一个xml文件都省略掉beans了。

<?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-3.0.xsd
	http://www.springframework.org/schema/context
	http://www.springframework.org/schema/context/spring-context-3.0.xsd">
	
	<!-- 通过构造器参数索引方式依赖注入 -->
	<bean id="byIndex" class="com.action.HelloApiImpl">
		<constructor-arg index="0" value="Hello Spring byIndex..."></constructor-arg>
		<constructor-arg index="1" value="1"></constructor-arg>
	</bean>
	
	<!-- 通过构造器参数数据类型方式依赖注入 -->
	<bean id="byType" class="com.action.HelloApiImpl">
		<constructor-arg type="java.lang.String" value="Hello Spring byType..."></constructor-arg>
		<constructor-arg type="int" value="2"></constructor-arg>
	</bean>
	
	<!-- 通过构造器参数名称方式依赖注入 -->
	<bean id="byName" class="com.action.HelloApiImpl">
		<constructor-arg name="message" value="Hello Spring byName..."></constructor-arg>
		<constructor-arg name="index" value="3"></constructor-arg>
	</bean>
</beans>

第二:写测试类。
package com.action;

import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class DependencyInjectTest {
	public static void main(String[] args) {
		BeanFactory beanFactory = new ClassPathXmlApplicationContext("com/resource/ConstructorDependencyInject.xml");
		HelloApi byIndex = beanFactory.getBean("byIndex",HelloApi.class);
		byIndex.sayHello();
		HelloApi byType = beanFactory.getBean("byType",HelloApi.class);
		byType.sayHello();
		HelloApi byName = beanFactory.getBean("byName",HelloApi.class);
		byName.sayHello();
		/*通过参数名称依赖注入的时候,需要开启调试模式。以下为比较正式的解释:
		 * 构造器注入可以根据参数索引注入、参数类型注入或Spring3支持的参数名注入,但参数名注入是有限制的,
		 * 需要使用在编译程序时打开调试模式(即在编译时使用“javac –g:vars”在class文件中生成变量调试信息,
		 * 默认是不包含变量调试信息的,从而能获取参数名字,否则获取不到参数名字)
		 * 或在构造器上使用@ConstructorProperties(java.beans.ConstructorProperties)注解来指定参数名。
		 * 
		 * 通过构造器参数名字注入方式,先确保编译时class文件包含“变量信息”
		 * 在myeclipse中的调整步骤为:进入项目属性,java compiler,下面add varible……勾选上。
		 * */
	}
}

第三,静态工厂类和实例工厂类(测试类省略)

静态工厂

package com.action;
public class DependencyInjectByFactory {
	//静态工厂类
	private static HelloApi newInstance(String message,int index){
		return new HelloApiImpl(message,index);
	}
}
xml文件
	<!-- 通过构造器参数索引方式依赖注入 -->
	<bean id="byIndex" class="com.action.DependencyInjectByFactory" factory-method="newInstance">
		<constructor-arg index="0" value="Hello Spring byIndex..."></constructor-arg>
		<constructor-arg index="1" value="1"></constructor-arg>
	</bean>
	
	<!-- 通过构造器参数数据类型方式依赖注入 -->
	<bean id="byType" class="com.action.DependencyInjectByFactory" factory-method="newInstance">
		<constructor-arg type="java.lang.String" value="Hello Spring byType..."></constructor-arg>
		<constructor-arg type="int" value="2"></constructor-arg>
	</bean>
	
	<!-- 通过构造器参数名称方式依赖注入 -->
	<bean id="byName" class="com.action.DependencyInjectByFactory" factory-method="newInstance">
		<constructor-arg name="message" value="Hello Spring byName..."></constructor-arg>
		<constructor-arg name="index" value="3"></constructor-arg>
	</bean>
实例工厂
package com.action;
public class DependencyByInstanceFactory {
	//实例工厂类
	public HelloApi newInstance(String message,index);
	}
}
xml文件
	
	<bean id="DependencyByInstanceFactory" class="com.action.DependencyByInstanceFactory"></bean>
	
	<!-- 通过构造器参数索引方式依赖注入 -->
	<bean id="byIndex" factory-bean="DependencyByInstanceFactory" factory-method="newInstance">
		<constructor-arg index="0" value="Hello Spring byIndex..."></constructor-arg>
		<constructor-arg index="1" value="1"></constructor-arg>
	</bean>
	
	<!-- 通过构造器参数数据类型方式依赖注入 -->
	<bean id="byType" factory-bean="DependencyByInstanceFactory" factory-method="newInstance">
		<constructor-arg type="java.lang.String" value="Hello Spring byType..."></constructor-arg>
		<constructor-arg type="int" value="2"></constructor-arg>
	</bean>
	
	<!-- 通过构造器参数名称方式依赖注入 -->
	<bean id="byName" factory-bean="DependencyByInstanceFactory" factory-method="newInstance">
		<constructor-arg name="message" value="Hello Spring byName..."></constructor-arg>
		<constructor-arg name="index" value="3"></constructor-arg>
	</bean>
这个时候所有的不同,各种方法的各种优势都展现出来了。

对于setter注入的初步了解,测试类省略。

实现类

package com.action;
public class HelloApiSet implements HelloApi{
	private String message;
	private int index;
	public void setMessage(String message) {
		this.message = message;
	}
	public void setIndex(int index) {
		this.index = index;
	}
	public void sayHello(){
		System.out.println(index+" : "+message);
	}
}
xml
	<bean id="bean" class="com.action.HelloApiSet">
		<property name="message" value="Hello TestSet"></property>
		<property name="index" value="123"></property>
	</bean>

常量注入

		<property name="index" value="123"></property>
		<property name="index"><value>123</value></property>
第一种和第二种是表述方式是一样的,第二种中的123是以字符串形式传入的,由spring自动转换成需要的类型,如果转换错误会抛出相应的异常。

Spring类型转换系统对于boolean类型进行了容错处理,除了可以使用“true/false”标准的Java值进行注入,还能使用“yes/no”、“on/off”、“1/0”来代表“对/错”。

先写类。

package com.action;
public class BooleanBean {
	private boolean success;
	public void setSuccess(boolean success){
		this.success = success;
	}
	public void isSuccess(){
		System.out.println(success);
	}
}
xml
	<!-- true/false 以下都是按“对/错”的位置排列的-->
	<bean id="bean1" class="com.action.BooleanBean">
		<property name="success" value="true"></property>
	</bean>
	<!-- yes/no -->
	<bean id="bean2" class="com.action.BooleanBean">
		<property name="success" value="yes"></property>
	</bean>
	<!-- on/off -->
	<bean id="bean3" class="com.action.BooleanBean">
		<property name="success" value="on"></property>
	</bean>
	<!-- 1/0 -->
	<bean id="bean4" class="com.action.BooleanBean">
		<property name="success" value="1"></property>
	</bean>
测试类省略。 集合注入 先测试List,写类
package com.action;
import java.util.List;
public class ListBean {
	private List<String> values;

	public List<String> getValues() {
		return values;
	}

	public void setValues(List<String> values) {
		this.values = values;
	}
	
}
配位文件xml
	<bean name="ListBean" class="com.action.ListBean">
		<property name="values">
			<list>
				<value>1</value>
				<value>2</value>
				<value>3</value>
			</list>
		</property>
	</bean>
测试类
package com.action;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestListBean {
	public static void main(String[] args) {
		BeanFactory beanFactory = new ClassPathXmlApplicationContext("com/resource/ListInject.xml");
		ListBean listBean = beanFactory.getBean("ListBean",ListBean.class);
		System.out.println(listBean.getValues().size());
//		for (Iterator<String> iterator = listBean.getValues().iterator(); iterator.hasNext();) {
//			String type = (String) iterator.next();
//			System.out.println(type);
//		}
	}
}
当注入Set的时候大致如此,xml文件里面的list改写成Set。数组的时候改成array, 二维数组的话array里面可以还有array。最后说map,map的时候需要指定一些东西。
	<bean name="MapBean" class="com.action.MapBean">
	<property name="values">
		<map key-type="java.lang.String" value-type="java.lang.String">
			<entry>
				<key><value>aaa</value></key>
				<value>bbb</value>
			</entry>
			<entry key="ccc" value="ddd"></entry>
		</map>
		</property>
	</bean>

public class MapBean {
	private Map<String,String> values;

	public Map<String,String> getValues() {
		return values;
	}

	public void setValues(Map<String,String> values) {
		this.values = values;
	}
	
}

public class TestMapBean {
	public static void main(String[] args) {
		BeanFactory beanFactory = new ClassPathXmlApplicationContext("com/resource/ListInject.xml");
		MapBean mapBean = beanFactory.getBean("MapBean",MapBean.class);
		for (Iterator<Map.Entry<String,String>> iterator = mapBean.getValues().entrySet().iterator(); iterator.hasNext();) {
			Map.Entry<String,String> temp =  iterator.next();
			System.out.println(temp.getKey()+"==="+temp.getValue());
		}
	}
}

引用其他Bean
package com.action;
public class HelloImpl implements HelloApi{

	@Override
	public void sayHello() {
		System.out.println("I love you,Spring!");
	}
}

package com.action;

public class DecoratorHelloApi implements HelloApi {
	private HelloApi helloApi1;
	//无参
	public DecoratorHelloApi() {
	}
	//有参
	public DecoratorHelloApi(HelloApi helloApi) {
		this.helloApi1 = helloApi;
	}
	//setter方法
	public void setHelloApi(HelloApi helloApi) {
		this.helloApi1 = helloApi;
	}
	
	@Override
	public void sayHello() {
		System.out.println("===========装饰一下=============");
		helloApi1.sayHello();
		System.out.println("===========装饰一下=============");
	}

}

	<!-- 定义依赖bean -->
	<bean id="helloImpl" class="com.action.HelloImpl"></bean>
	
	
	<!-- 下面两种方式注入都可以分为三小种,类型,索引和名字 -->
	
	<!-- 通过构造器注入 -->
	<bean id="bean1" class="com.action.DecoratorHelloApi">
		<constructor-arg index="0" ref="helloImpl"></constructor-arg>
	</bean>
	<!-- 通过setter注入 -->
	<bean id="bean2" class="com.action.DecoratorHelloApi">
		<property name="helloApi"><!-- 注意最好属性名和依赖bean的名字别一样,妈的我找错找了很久 -->
			<ref bean="helloImpl"/>
		</property>
	</bean>

<ref local>和<ref parent>的配置。(这个有点乱……)
package com.action;
public class HelloImpl implements HelloApi{
	
	private String message;
	private String name;
	
	public HelloImpl() {
	}

	public HelloImpl(String message,String name) {
		this.name = name;
		this.message = message;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getMessage() {
		return message;
	}

	public void setMessage(String message) {
		this.message = message;
	}

	@Override
	public void sayHello() {
		System.out.println(message+"==="+name);
	}
}

package com.action;

import com.action.HelloApi;

public class DecoratorHelloApi implements HelloApi {
	private HelloApi helloApi1;
	//无参
	public DecoratorHelloApi() {
	}
	//有参
	public DecoratorHelloApi(HelloApi helloApi) {
		this.helloApi1 = helloApi;
	}
	//setter方法
	public void setHelloApi(HelloApi helloApi) {
		this.helloApi1 = helloApi;
	}
	
	@Override
	public void sayHello() {
		System.out.println("===========装饰一下=============");
		helloApi1.sayHello();
		System.out.println("===========装饰一下=============");
	}

}

<?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-3.0.xsd
	http://www.springframework.org/schema/context
	http://www.springframework.org/schema/context/spring-context-3.0.xsd">
	
	<bean id="helloApi" class="com.action.HelloImpl">
		<property name="message" value="Hello"></property>
		<property name="name" value="parent"></property>
	</bean>
</beans>

<?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-3.0.xsd
	http://www.springframework.org/schema/context
	http://www.springframework.org/schema/context/spring-context-3.0.xsd">
	
	<bean id="helloApi" class="com.action.HelloImpl">
		<property name="message" value="Hello"></property>
		<property name="name" value="local"></property>
	</bean>
	<!-- 通过parent注入 -->
	<bean id="bean1" class="com.action.DecoratorHelloApi">
		<constructor-arg index="0">
			<ref parent="helloApi" ></ref>
		</constructor-arg>
	</bean>
	
	<!-- 通过local注入 -->
	<bean id="bean2" class="com.action.DecoratorHelloApi">
		<!-- <property name="helloApi" ref="helloApi"></property> -->
		<!-- 默认情况下是先查当前 -->
		<property name="helloApi">
			<ref local="helloApi" />
		</property>
	</bean>
		
</beans>

package com.action;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestLocalAndparentBeanInject {
	public static void main(String[] args) {
		//初始化父容器
		ApplicationContext parentContext = new ClassPathXmlApplicationContext("com/resource/parentBeanInject.xml");
		//初始化当前容器  应该是这句话定义父子关系的
		ApplicationContext beanContext = new ClassPathXmlApplicationContext(new String[]{"com/resource/localBeanInject.xml"},parentContext);
		HelloApi helloApi1 = beanContext.getBean("bean1",HelloApi.class);
		helloApi1.sayHello();//该helloApi引用parent
		HelloApi helloApi2 = beanContext.getBean("bean2",HelloApi.class);
		helloApi2.sayHello();//该helloApi2引用local
	}
}

定义内部bean 内部Bean就是在<property>或<constructor-arg>内通过<bean>标签定义的Bean,该Bean不管是否指定id或name,该Bean都会有唯一的匿名标识符,而且不能指定别名,该内部Bean对其他外部Bean不可见。
package com.action;
public class HelloImpl implements HelloApi {
      @Override
      public void sayHello() {
             System.out.println("Hello World!");
      }
}

package com.action;
public class HelloApiDecorator implements HelloApi {
private HelloApi helloApi;
//空参构造器
    public HelloApiDecorator() {
}
//有参构造器
    public HelloApiDecorator(HelloApi helloApi) {
        this.helloApi = helloApi;
}  
public void setHelloApi(HelloApi helloApi) {
        this.helloApi = helloApi;
    }
    @Override
    public void sayHello() {
        System.out.println("==========装饰一下===========");
        helloApi.sayHello();
        System.out.println("==========装饰一下===========");
    }
}

	<bean id="bean" class="com.action.HelloApiDecorator">
		<property name="helloApi">
			<bean id="helloApi" class="com.action.HelloImpl"></bean>
		</property>
	</bean>

public class TestInnerBeanInject {
	public static void main(String[] args) {
		ApplicationContext ac = new ClassPathXmlApplicationContext("com/resource/innerBeanInject.xml");
		HelloApi ha = ac.getBean("bean",HelloApi.class);
		ha.sayHello();
		
	}
}

注入null值 可以通过类似方式注入
	<bean id="bean2" class="com.action.DecoratorHelloApi">
		<property name="message"><null/></property>
	</bean>

对象图导航注入支持(这个应该意义不大,我另写一篇吧,把这个完结了。)

配置简写

(以下为转载。)

一、构造器注入:

1)常量值

简写:<constructor-arg index="0" value="常量"/>

全写:<constructor-arg index="0"><value>常量</value></constructor-arg>

2)引用

简写:<constructor-arg index="0" ref="引用"/>

全写:<constructor-arg index="0"><ref bean="引用"/></constructor-arg>

二、setter注入:

1)常量值

简写:<property name="message" value="常量"/>

全写:<property name="message"><value>常量</value></ property>

2)引用

简写:<property name="message" ref="引用"/>

全写:<property name="message"><ref bean="引用"/></ property>

3)数组:<array>没有简写形式

4)列表:<list>没有简写形式

5)集合:<set>没有简写形式

6)字典

简写:<map>

<entry key="键常量" value="值常量"/>

<entry key-ref="键引用" value-ref="值引用"/>

</map>

全写:<map>

<entry><key><value>键常量</value></key><value>值常量</value></entry>

<entry><key><ref bean="键引用"/></key><ref bean="值引用"/></entry>

</map>

7)Properties:没有简写形式

三、使用p命名空间简化setter注入:

使用p命名空间来简化setter注入,具体使用如下:

java代码: 查看 复制到剪贴板 打印
  1. <?xmlversion="1.0"encoding="UTF-8"?>
  2. <beansxmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xmlns:p="http://www.springframework.org/schema/p"
  5. xsi:schemaLocation="
  6. http://www.springframework.org/schema/beans
  7. http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
  8. <beanid="bean1"class="java.lang.String">
  9. <constructor-argindex="0"value="test"/>
  10. </bean>
  11. <beanid="idrefBean1"class="cn.javass.spring.chapter3.bean.IdRefTestBean"
  12. p:id="value"/>
  13. <beanid="idrefBean2" p:id-ref="bean1"/>
  14. </beans>
  • xmlns:p="http://www.springframework.org/schema/p":首先指定p命名空间;
  • <bean id="……" class="……" p:id="value"/>:常量setter注入方式,其等价于<property name="id" value="value"/>;
    • <bean id="……" class="……" p:id-ref="bean1"/>:引用setter注入方式,其等价于<property name="id" ref="bean1"/>。



本来就是比着一本书摘录的,写就是为了自己以后复习使用,这一章写的太长了,而且又乱到时候读的时候一定有麻烦。以后得注意前后呼应的格式了。

(编辑:安卓应用网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读