欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

JavaWeb Spring依赖注入深入学习

程序员文章站 2024-03-13 18:19:09
一、依赖注入(di) 依赖注入听起来很高深的样子,其实白话就是:给属性赋值。一共有两种方法,第一是以构造器参数的形式,另外一种就是以setting方法的形式。 1 构造...

一、依赖注入(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.都是默认设置

JavaWeb Spring依赖注入深入学习

2.设置student(lazy-init=true)

JavaWeb Spring依赖注入深入学习

3.设置person(lazy-init=true)

JavaWeb Spring依赖注入深入学习

总结
可以采用两种方法注入参数,构造器要写对应的构造函数,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

需求描述

JavaWeb Spring依赖注入深入学习

建立工程目录

JavaWeb Spring依赖注入深入学习

编码:
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的实现类。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。