JavaWeb Spring依赖注入深入学习
一、依赖注入(di)
依赖注入听起来很高深的样子,其实白话就是:给属性赋值。一共有两种方法,第一是以构造器参数的形式,另外一种就是以setting方法的形式。
1 构造器注入
1 使用构造器注入
使用xml的注入方式
a. 通过参数的顺序
<constructor-arg index="0"><value>张三</value></constructor-arg>
<constructor-arg index="1"><value>56</value></constructor-arg>
b. 通过参数的类型
<constructor-arg type="java.lang.integer"><value>56</value></constructor-arg>
<constructor-arg type="java.lang.string"><value>张三</value></constructor-arg>
具体实例
假如现在要对一个person类注入参数,student是一个另外一个类。
public class person { private string pid; private string name; private student student; public person(string pid, student student){ this.pid= pid; this.student = student; } public person(string pid, string name){ this.pid = pid; this.name = name; } }
配置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" xsi:schemalocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"> <bean id="person" class="com.itheima10.spring.di.xml.constructor.person"> <!-- 不配参数,将会采取默认的构造器 constructor-arg person类中某一个构造器的某一个参数 index 为参数的角标 type 参数的类型 value 如果为基础属性,则用这个赋值 ref 引用类型赋值 --> <constructor-arg index="0" type="java.lang.string" value="aaa"></constructor-arg> <constructor-arg index="1" ref="student"></constructor-arg> </bean> <bean id="person1" class="com.itheima10.spring.di.xml.constructor.person"> <property name="pid" value="1"></property> </bean> <bean id="student" class="com.itheima10.spring.di.xml.constructor.student"></bean> </beans>
编写测试类dixmlconstructortest ,进行断点调试,将会发现根据配置的参数,进入的构造函数是person(string pid, student student)
public class dixmlconstructortest { @test public void test1(){ applicationcontext context = new classpathxmlapplicationcontext("applicationcontext.xml"); person person = (person) context.getbean("person"); } }
2 使用属性setter方法进行注入
使用xml的注入方式:
a. 简单bean的注入
简单bean包括两种类型:包装类型和string
<bean id="personservice" class="com.itcast.bean.impl.personserviceimpl"> <!-- 基本类型,string类型 --> <property name="age" value="20"></property> <property name="name" value="张无忌"></property> </bean>
b. 引用其他bean
<bean id="person" class="com.itcast.bean.person" /> <bean id="personservice" class="com.itcast.bean.impl.personserviceimpl"> <property name="person" ref="person" /> </bean>
1.1 装配list集合
<property name="lists"> <list> <value>list1</value> <value>list2</value> <ref bean="person" /> </list> </property>
1.2 装配set集合
<property name="sets"> <set> <value>list1</value> <value>list2</value> <ref bean="person" /> </set> </property>
1.3 装配map
<property name="maps"> <map> <entry key="01"> <value>map01</value> </entry> <entry key="02"> <value>map02</value> </entry> </map> </property>
map中的<entry>的数值和<list>以及<set>的一样,可以使任何有效的属性元素,需要注意的是key值必须是string的。
1.4 装配properties
<property name="props"> <props> <prop key="01">prop1</prop> <prop key="02">prop2</prop> </props> </property>
具体实例
1.创建两个对象person和student
package xgp.spring.demo; import java.util.list; import java.util.map; import java.util.properties; import java.util.set; public class person { private string pid; private string name; private student student; private list lists; private set sets; private map map; private properties properties; private object[] objects; public person(){ system.out.println("new person"); } //省略getter和setter方法 }
package xgp.spring.demo; public class student { public student(){ system.out.println("new student"); } public void say(){ system.out.println("student"); } }
配置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" xsi:schemalocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"> <!-- 把person和student放入到spring容器中 property 用来描述person类的属性 value 如果是一般属性,则用value赋值 ref 如果该属性是引用类型,用ref赋值 --> <bean id="person" class="com.itheima10.spring.di.xml.setter.person" init-method="init" lazy-init="true"> <property name="pid" value="1"></property> <property name="name" value="王二麻子"></property> <property name="student" ref="student"></property> <property name="lists"> <list> <value>list1</value> <value>list2</value> <ref bean="student"/> </list> </property> <property name="sets"> <set> <value>set1</value> <value>set2</value> <ref bean="student"/> </set> </property> <property name="map"> <map> <entry key="entry1"> <value>map1</value> </entry> <entry key="entry2"> <ref bean="student"/> </entry> </map> </property> <property name="properties"> <props> <!-- 不需要引用类型 --> <prop key="prop1">prop1</prop> <prop key="prop2">prop2</prop> </props> </property> <property name="objects"> <list> <value>aa</value> <value>bb</value> </list> </property> </bean> <bean id="student" class="com.itheima10.spring.di.xml.setter.student"></bean> </beans>
编写测试类dixmlsettertest
package xgp.spring.test; import org.junit.test; import org.springframework.context.applicationcontext; import org.springframework.context.support.classpathxmlapplicationcontext; import xgp.spring.demo.person; public class dixmlsettertest { /** * spring 容器做的事情: * 1、spring容器做了什么?(1)启动spring容器 * (2)为person和student两个bean创建对象 * (3)解析property的name属性,拼接setter方法,解析property的 * value或者ref属性,给setter方法传递参数,利用反射技术给对象赋值。 * (4)从spring容器中,把对象提取出来,对象调用方法。 * 2、spring容器执行顺序是什么? */ @test public void test1(){ applicationcontext context = new classpathxmlapplicationcontext("applicationcontext.xml"); person person = (person) context.getbean("person"); system.out.println(person.getpid()); system.out.println(person.getname()); system.out.println(person.getlists()); system.out.println(person.getsets()); system.out.println(person.getmap()); system.out.println(person.getobjects().length); } } /*1 王五 [list1, list2, xgp.spring.demo.student@76a9b9c] [set1, set2, xgp.spring.demo.student@76a9b9c] {entry1=map1, entry2=map2} 2*/
spring容器的执行顺序
1.都是默认设置
2.设置student(lazy-init=true)
3.设置person(lazy-init=true)
总结
可以采用两种方法注入参数,构造器要写对应的构造函数,setter要生成相应的setter方法,并编写默认的构造器。
2.5 ioc与di的意义
学了这些,发现有什么意义?下面写个文档管理系统例子来说明,需求见下图
1.编写document 接口
public interface document { public void read(); public void write(); }
2、编写实现类worddocument ,exceldocument ,pdfdocument
public class worddocument implements document{ public void read() { system.out.println("word read"); } public void write() { system.out.println("word write"); } }
3、编写文档管理 系统 documentmanager
public class documentmanager { private document document; public void setdocument(document document) { this.document = document; } public documentmanager(){ } public documentmanager(document document) { super(); this.document = document; } public void read(){ this.document.read(); } public void write(){ this.document.write(); } }
4、编写测试类documenttest
/** * 利用ioc和di能做到完全的面向接口编程 * */ public class documenttest { /** * document document = new worddocument(); * 这行代码是不完全的面向接口编程,因为等号的右边出现了具体的类 */ @test public void testdocument_nospring(){ document document = new worddocument(); documentmanager documentmanager = new documentmanager(document); documentmanager.read(); documentmanager.write(); } /** * 在代码端不知道document是由谁来实现的,这个是由spring的配置文件决定的 * <bean id="documentmanager" class="com.itheima10.spring.iocdi.document.documentmanager"> <!-- document为一个接口 --> <property name="document"> <!-- worddocument是一个实现类,赋值给了document接口 --> <ref bean="pdfdocument"/> </property> </bean> */ @test public void testdocument_spring(){ applicationcontext context = new classpathxmlapplicationcontext("applicationcontext.xml"); documentmanager documentmanager =(documentmanager)context.getbean("documentmanager"); documentmanager.read(); documentmanager.write(); } }
从上面可以看出不适用spring和适用spring的区别
<!-- documentmanager,worddocument,exceldocument,pdfdocument放入到spring容器中 --> <bean id="worddocument" class="com.itheima10.spring.iocdi.document.worddocument"></bean> <bean id="exceldocument" class="com.itheima10.spring.iocdi.document.exceldocument"></bean> <bean id="pdfdocument" class="com.itheima10.spring.iocdi.document.pdfdocument"></bean> <bean id="documentmanager" class="com.itheima10.spring.iocdi.document.documentmanager"> <!-- document为一个接口 --> <property name="document"> <!-- worddocument是一个实现类,赋值给了document接口 --> <ref bean="pdfdocument"/> </property> </bean>
使用spring只需要在applicationcontext中配置相应的<ref bean="">对象,而不需要关注具体的实现类,实现完全的面向接口编程,这也是为什么spring能够和这么多工具集成的原因。
2.6 mvc实例–模拟structs2
需求描述
建立工程目录
编码:
1、创建dao层
建立persondao接口和实现类persondaoimpl
public interface persondao { public void saveperson(); } public class persondaoimpl implements persondao { @override public void saveperson() { system.out.println(" save person"); } }
2、建立service层,personservice接口与personserviceimpl实现类
public interface personservice { public void saveperson(); } public class personserviceimpl implements personservice{ private persondao persondao; public void setpersondao(persondao persondao) { this.persondao = persondao; } @override public void saveperson() { this.persondao.saveperson(); } }
3、建立action,personaction类
public class personaction { private personservice personservice; public void setpersonservice(personservice personservice) { this.personservice = personservice; } public void saveperson(){ this.personservice.saveperson(); } }
4、配置applicationcontext.xml
<!-- 把service,dao,action层的类放入到spring容器中 --> <bean id="persondao" class="xgp.spring.demo.persondaoimpl"></bean> <bean id="personservice" class="xgp.spring.demo.personserviceimpl"> <property name="persondao"> <ref bean="persondao"/> </property> </bean> <bean id="personaction" class="xgp.spring.demo.personaction"> <property name="personservice"> <ref bean="personservice"/> </property> </bean>
5、编写测试类testmvc
public class mvctest { @test public void testmvc(){ applicationcontext context = new classpathxmlapplicationcontext("applicationcontext.xml"); personaction personaction = (personaction)context.getbean("personaction"); personaction.saveperson();//save person } }
上述实例很清楚的展现出了spring的面向接口编程,service层只需调用dao层的接口,而不需要关注于dao层的实现类,action也只需调用service的接口,而不需要关注service的实现类。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
下一篇: Java 连接MySql数据库