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.都是默认设置
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的实现类。
来源:http://blog.csdn.net/i10630226/article/details/50507100


猜你喜欢
- Actuator简介监控分类Actuator 提供Rest接口,展示监控信息。接口分为三大类:应用配置类:获取应用程序中加载的应用配置、环境
- 加密配置文件的SQL账号密码一般项目的配置文件里的信息都是明文的,导致有时候比较敏感的信息也直接暴露得超级明显,比如SQL的链接 账号 密码
- 本文实例讲述了Android操作SQLite数据库(增、删、改、查、分页等)及ListView显示数据的方法。分享给大家供大家参考,具体如下
- 对JVM运行参数进行修改是JVM性能调优的重要手段,下面介绍在应用程序开发过程中JVM参数设置的几种方式。方式一java程序运行时指定 -D
- 1. 经过简化的Property 早些时候我们这样声明Property private string _myName; public str
- hadoop做的一个简单grep程序,可从文档中提取包含某些字符串的行/* * 一个简单grep程序,可从文档中提取包含莫些字符串
- 文件写入为提供相对较高性能的文件读写操作,这里果断选择了 NIO 对文件的操作,因为业务背景需要数据的安全落盘。这里主要采用 ByteBuf
- 很久没写文章了,一方面是最近几个月比较忙,没太多时间,另一方面是最近拖延症严重,写文章的想法总是一拖再拖。今天找一个小案例写一下,与懒惰对抗
- 本文实例为大家分享了OpenGL绘制Bezier曲线的具体代码,供大家参考,具体内容如下最近在看Francis S Hill ,Jr 和 S
- 工具:jdk1.8win10spring5.01.准备工作:下载Spring开发应用的插件,api1.spring插件包:springsou
- logback输出日志屏蔽quartz的debug等级日志在一个spring的老项目中,使用了logback来作为日志管理,logback.
- 通常在C#的实际开发过程中,会发现设置其属性ScriptErrorsSuppressed无法达到屏蔽脚本错误效果,但是可以通过下面两种方式实
- Gradle 属性( Gradle build environment)[详细信息]("https://docs.gradle.o
- 本文实例为大家分享了Android Socket实现多个客户端聊天布局的具体代码,供大家参考,具体内容如下服务器Socket接受到客户端发送
- 两张表SystemParam(系统参数表) Suit (主题)SystemParam 与 Suit 是多对一Suit 的higerSuit字
- Authentication使用SpringSecurity可以在任何地方注入Authentication进而获取到当前登录的用户信息,可谓
- Swing中的常用按钮在Swing中,常见的按钮组件有JButton,JCheckBox,JRadioButton等,它们都是抽象类Abst
- 在上篇文章给大家介绍了FastDFS安装和配置整合Nginx-1.13.3的方法,大家可以点击查看下。今天使用Java代码实现文件的上传和下
- 说明Spring Boot Admin 是一个管理和监控你的 Spring Boot 应用程序的应用程序。 这些应用程序通过 Spring
- HandlerThread 简介:我们知道Thread线程是一次性消费品,当Thread线程执行完一个耗时的任务之后,线程就会被自动销毁了。