DI(依赖注入)的进阶
|
首先写接口类: 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代码: 查看 复制到剪贴板 打印
本来就是比着一本书摘录的,写就是为了自己以后复习使用,这一章写的太长了,而且又乱到时候读的时候一定有麻烦。以后得注意前后呼应的格式了。 (编辑:安卓应用网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
