JavaWeb Spring依赖注入深入学习

作者:i10630226 时间:2022-04-02 08:20:05 

一、依赖注入(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的实现类。

来源:http://blog.csdn.net/i10630226/article/details/50507100

标签:javaweb,spring,依赖注入
0
投稿

猜你喜欢

  • JAVA中String介绍及常见面试题小结

    2021-11-19 03:38:20
  • 解决IDEA无法下载maven依赖的问题

    2023-12-05 17:06:59
  • Flask实现异步非阻塞请求功能实例解析

    2022-02-03 14:03:55
  • Java rmi远程方法调用基本用法解析

    2023-02-20 08:44:19
  • springboot整合quartz项目使用案例

    2023-02-13 19:57:12
  • JAVA抛出异常的三种形式详解

    2022-06-26 22:44:32
  • 英雄联盟辅助lol挂机不被踢的方法(lol挂机脚本)

    2022-03-15 12:57:59
  • Java Thread.currentThread().getName() 和 this.getName()区别详解

    2021-10-31 01:46:18
  • Android客户端与服务端数据加密传输方案详解

    2023-07-14 13:55:37
  • 浅谈Action+Service +Dao 功能

    2023-01-04 13:44:20
  • Java抽象类和接口使用梳理

    2022-10-02 08:38:46
  • Android Studio使用小技巧:提取方法代码片段

    2023-11-14 19:35:20
  • WPF实现动画效果(七)之演示图板

    2021-08-18 20:31:53
  • 关于Scanner对象的输入结束标记问题

    2022-02-20 08:02:11
  • C#多线程爬虫抓取免费代理IP的示例代码

    2023-02-08 01:22:01
  • SpringCloud远程服务调用三种方式及原理

    2023-10-16 07:21:19
  • 浅谈图片上传利用request.getInputStream()获取文件流时遇到的问题

    2023-10-18 10:36:43
  • c#中SAPI使用总结——SpVoice的使用方法

    2022-02-20 09:50:07
  • springmvc接收json串,转换为实体类List方法

    2023-07-28 12:40:00
  • Java解析DICOM图之如何获得16进制数据详解

    2023-06-15 17:37:29
  • asp之家 软件编程 m.aspxhome.com