Spring IOC

Spring IOC

  1. Spring** 框架

2.1. Spring 框架概念

Spring 是众多开源java项⽬中的⼀员,基于分层的javaEE应⽤⼀站式轻量级开源框架,主要核⼼是IOC(控制反转/依赖注⼊)与 AOP(⾯向切⾯)两⼤技术,实现项⽬在开发过程中的轻松解耦,提⾼项⽬的开发效率。

在项⽬中引⼊ Spring ⽴即可以带来下⾯的好处 降低组件之间的耦合度,实现软件各层之间的解耦。可以使⽤容器提供的众多服务,如:事务管理服务、消息服务等等。当我们使⽤容器管理事务时,开发⼈员就不再需要⼿⼯控制事务.也不需处理复杂的事务传播。 容器提供单例模式⽀持,开发⼈员不再需要

⾃⼰编写实现代码。 容器提供了AOP技术,利⽤它很容易实现如权限拦截、运⾏期监控等功能。2.2. Spring 源码架构Spring 总共⼤约有20个模块,由1300多个不同的⽂件构成。⽽这些组件被分别整合在核⼼容器(Core Container)、Aop(Aspect Oriented Programming)和设备⽀持(Instrmentation)、数据

访问及集成(Data Access/Integeration)、Web、报⽂发送(Messaging)、测试6个模块集合中。

\1. 核⼼容器:Spring-beans 和 Spring-core 模块是 Spring 框架的核⼼模块,包含控制反转

(Inversion of Control, IoC)和依赖注⼊(Dependency Injection, DI),核⼼容器提供 Spring 框

架的基本功能。核⼼容器的主要组件是 BeanFactory,⼯⼚模式的实现。BeanFactory 使⽤控制

反转(IOC) 思想将应⽤程序的配置和依赖性规范与实际的应⽤程序代码分开。

Spring 上下⽂Spring Context:Spring 上下⽂是⼀个配置⽂件,向 Spring 框架提供上下⽂信息。

Spring 上下⽂包括企业服务,例如 JNDI、EJB、电⼦邮件、国际化、校验和调度功能。

Spring-Expression 模块是统⼀表达式语⾔(unifified EL)的扩展模块,可以查询、管理运⾏中的

对象,同时也⽅便的可以调⽤对象⽅法、操作数组、集合等。它的语法类似于传统EL,但提供了额

外的功能,最出⾊的要数函数调⽤和简单字符串的模板函数。

\2. Spring-AOP:Spring-aop是Spring的另⼀个核⼼模块, 在Spring中,他是以JVM的动态代理技术为

基础,然后设计出了⼀系列的Aop横切实现,⽐如前置通知、返回通知、异常通知等。通过其配置

管理特性,Spring AOP 模块直接将⾯向切⾯的编程功能集成到了 Spring 框架中。所以,可以很容

易地使 Spring 框架管理的任何对象⽀持 AOP。

\3. Spring Data Access(数据访问):由Spring-jdbc、Spring-tx、Spring-orm、Spring-jms和Spring

oxm 5个模块组成 Spring-jdbc 模块是 Spring 提供的JDBC抽象框架的主要实现模块,⽤于简化

Spring JDBC。Spring-tx 模块是SpringJDBC事务控制实现模块。使⽤Spring框架,它对事务做了很好的封装,通

过它的Aop配置,可以灵活的配置在任何⼀层。

Spring-Orm 模块是ORM框架⽀持模块,主要集成 hibernate, Java Persistence API (JPA) 和 Java

Data Objects (JDO) ⽤于资源管理、数据访问对象(DAO)的实现和事务策略。

Spring-Jms 模块(Java Messaging Service)能够发送和接受信息。

Spring-Oxm 模块主要提供⼀个抽象层以⽀撑OXM(OXM 是 Object-to-XML-Mapping 的缩写,

它是⼀个O/M-mapper,将java对象映射成 XML 数据,或者将 XML 数据映射成 java 对象),例

如:JAXB, Castor, XMLBeans, JiBX 和 XStream 等。

\4. Web 模块:由Spring-web、Spring-webmvc、Spring-websocket和Spring-webmvc-portlet 4个

模块组成,Web 上下⽂模块建⽴在应⽤程序上下⽂模块之上,为基于 Web 的应⽤程序提供了上下

⽂。Web 模块还简化了处理多部分请求以及将请求参数绑定到域对象的⼯作。

\5. 报⽂发送:即Spring-messaging模块。

Spring-messaging是Spring4 新加⼊的⼀个模块,主要职责是为Spring 框架集成⼀些基础的报⽂

传送应⽤。

\6. 单元测试:即Spring-test模块。Spring-test模块主要为测试提供⽀持

2.3. Spring 框架环境搭建

2.3.1. 环境要求

JDK 版本:

JDK 1.7 及以上版本

Spring版本:

Spring 5.x版本

2.3.2. 新建 Maven 项⽬

\1. 创建 Maven 的普通 Java 项⽬2. 设置项⽬的坐标

\3. 设置项⽬的 Maven 环境4. 设置项⽬的名称和存放的⼯作空间

2.3.3. 调整项⽬环境

\1. 修改 JDK 版本2. 修改单元测试 JUnit 版本

\3. build标签中的pluginManagement标签

2.3.4. 添加 Spring 框架的依赖坐标

Maven仓库:https://mvnrepository.com/

2.3.5. 编写 Bean 对象

<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

<maven.compiler.source>1.8</maven.compiler.source>

<maven.compiler.target>1.8</maven.compiler.target>

junit

junit

4.12

test

org.springframework

spring-context

5.2.4.RELEASE

package com.xxxx.service;

public class UserService {

public void test(){

System.out.println(“Hello Spring!”);

}

}2.3.6. 添加Spring 配置⽂件

\1. 在项⽬的src下创建⽂件夹 resources(Alt+insert)

\2. 将 resources 标记为资源⽬录

\3. 在 src\main\resources ⽬录下新建 spring.xml ⽂件,并拷⻉官⽹⽂档提供的模板内容到 xml

中。

配置 bean 到 xml 中,把对应 bean 纳⼊到 Spring 容器来管理

spring.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

https://www.springframework.org/schema/beans/spring-beans.xsd">

4. 在 spring.xml 中配置 Bean 对象

2.3.7. 加载配置⽂件,获取实例化对象

3. Spring IOC 容器 Bean 对象实例化模拟

思路:

\1. 定义Bean ⼯⼚接⼝,提供获取bean⽅法

\2. 定义Bean⼯⼚接⼝实现类,解析配置⽂件,实例化Bean对象

\3. 实现获取Bean⽅法

3.1. 定义 Bean 属性对象

package com.xxxx;

import com.xxxx.service.UserService;

import org.springframework.context.ApplicationContext;

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class App {

public static void main(String[] args) {

// 获取Spring上下⽂环境 (加载配置⽂件)

ApplicationContext ac = new

ClassPathXmlApplicationContext(“spring.xml”);

// 通过getBean⽅法得到Spring容器中实例化好的Bean对象 (实例化Bean对象)

// userService代表的是配置⽂件中bean标签的id属性值

UserService userService = (UserService) ac.getBean(“userService”);

// 调⽤⽅法 (使⽤实例化对象)

userService.test();

}

}

package com.xxxx.spring;3.2. 添加 dom4j 坐标依赖

/**

* bean对象

* ⽤来接收配置⽂件中bean标签的id与class属性值

*/

public class MyBean {

private String id; // bean对象的id属性值

private String clazz; // bean对象的类路径

public MyBean() {

}

public MyBean(String id, String clazz) {

this.id = id;

this.clazz = clazz;

}

public String getId() {

return id;

}

public void setId(String id) {

this.id = id;

}

public String getClazz() {

return clazz;

}

public void setClazz(String clazz) {

this.clazz = clazz;

}

}3.3. 准备⾃定义配置⽂件

spring.xml

3.4. 定义 Bean ⼯⼚接⼝

3.5. 定义 Bean 接⼝的实现类

dom4j

dom4j

1.6.1

jaxen

jaxen

1.1.6

<?xml version="1.0" encoding="utf-8" ?>

package com.xxxx.spring;

/**

* Bean ⼯⼚接⼝定义

*/

public interface MyFactory {

// 通过id值获取对象

public Object getBean(String id);

}

package com.xxxx.spring;

import org.dom4j.Document;

import org.dom4j.DocumentException;import org.dom4j.Element;

import org.dom4j.XPath;

import org.dom4j.io.SAXReader;

import java.net.URL;

import java.util.ArrayList;

import java.util.HashMap;

import java.util.List;

import java.util.Map;

/**

* 模拟Spring的实现

* 1、通过构造器得到相关配置⽂件

* 2、通过dom4j解析xml⽂件,得到List 存放id和class

* 3、通过反射实例化得到对象 Class.forName(类的全路径).newInstance(); 通过

Map<id,Class>存储

* 4、得到指定的实例化对象

*/

public class MyClassPathXmlApplicationContext implements BeanFactory {

private Map beans = new HashMap(); // 实例化后的对象放⼊map

private List myBeans; // 存放已读取bean 配置信息

/* 1、通过构造器得到相关配置⽂件 */

public MyClassPathXmlApplicationContext(String fileName) {

/* 2、通过dom4j解析xml⽂件,得到List (存放id和class) */

this.parseXml(fileName);

/* 3、通过反射实例化得到对象Class.forName(类路径).newInstance(); 通过Map存储

*/

this.instanceBean();

}

/**

* 通过dom4j解析xml⽂件,得到List 存放id和class

* 1、获取解析器

* 2、得到配置⽂件的URL

* 3、通过解析器解析xml⽂件(spring.xml)

* 4、通过xpath语法,获取beans标签下的所有bean标签

* 5、通过指定语法解析⽂档对象,返回集合

* 6、判断集合是否为空,遍历集合

* 7、获取标签元素中的属性

* 8、得到Bean对象,将Bean对象设置到集合中

* @param fileName

*/

private void parseXml(String fileName) {

// 1、获取解析器

SAXReader reader = new SAXReader(); // 2、得到配置⽂件的URL

URL url = this.getClass().getClassLoader().getResource(fileName);

try {

// 3、通过解析器解析xml⽂件(spring.xml)

Document document = reader.read(url);

// 4、通过xpath语法,获取beans标签下的所有bean标签

XPath xPath = document.createXPath(“beans/bean”);

// 通过指定语法解析⽂档对象,返回集合

List list = xPath.selectNodes(document);

// 判断集合是否为空,遍历集合

if (list != null && list.size() > 0) {

myBeans = new ArrayList<>();

for(Element el : list) {

// 获取标签元素中的属性

String id = el.attributeValue(“id”); // id 属性值

String clazz = el.attributeValue(“class”); // class 属性值

System.out.println(el.attributeValue(“id”));

System.out.println(el.attributeValue(“class”));

// 得到Bean对象

MyBean bean = new MyBean(id, clazz);

// 将Bean对象设置到集合中

myBeans.add(bean);

}

}

} catch (DocumentException e) {

e.printStackTrace();

}

}

/**

* 通过反射实例化得到对象

* Class.forName(类的全路径).newInstance();

* 通过Map<id,Class>存储

*/

private void instanceBean() {

// 判断bean集合是否为空,不为空遍历得到对应Bean对象

if (myBeans != null && myBeans.size() > 0) {

for (MyBean bean : myBeans){

try {

// 通过类的全路径实例化对象

Object object =

Class.forName(bean.getClazz()).newInstance();

// 将id与实例化对象设置到map对象中

beans.put(bean.getId(), object);

} catch (Exception e) {

e.printStackTrace();

}

}

}3.6. 测试⾃定义 IOC 容器

\1. 创建与配置⽂件中对应的Bean对象

UserService.java

AccountService.java

\2. 测试是否可以获取实例化的Bean对象

}

/**

* 通过key获取map中的指定value

* @param id

* @return

*/

@Override

public Object getBean(String id) {

Object object = beans.get(id);

return object;

}

}

package com.xxxx.service;

public class UserService {

public void test(){

System.out.println(“UserService Test…”);

}

}

package com.xxxx.service;

public class AccountService {

public void test(){

System.out.println(“AccountService Test…”);

}

}

package com.xxxx;

import com.xxxx.spring.MyFactory;

import com.xxxx.spring.MyClassPathXmlApplicationContext;

import com.xxxx.service.AccountService;

import com.xxxx.service.UserService;Spring 容器在启动的时候 读取xml配置信息,并对配置的 bean 进⾏实例化(这⾥模拟的⽐较

简单,仅⽤于帮助⼤家理解),同时通过上下⽂对象提供的 getBean() ⽅法拿到我们配置的 bean

对象,从⽽实现外部容器⾃动化维护并创建 bean 的效果。

4. Spring IOC 配置⽂件加载

4.1. Spring 配置⽂件加载

spring.xml

4.1.1. 根据相对路径加载资源

public class App {

public static void main(String[] args) {

MyFactory factory = new

MyClassPathXmlApplicationContext(“spring.xml”);

// 得到实例化对象

UserService userService = (UserService)

factory.getBean(“userService”);

userService.test();

UserService userService2 = (UserService)

factory.getBean(“userService”);

System.out.println(userService+"=====" + userService2);

AccountService accountService =

(AccountService)factory.getBean(“accountService”);

accountService.test();

}

}

<?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

https://www.springframework.org/schema/beans/spring-beans.xsd">

ApplicationContext ac = new ClassPathXmlApplicationContext(“spring.xml”);4.1.2. 根据绝对路径加载资源(了解)

4.2. Spring 多配置⽂件加载

Spring 框架启动时可以加载多个配置⽂件到环境中。对于⽐较复杂的项⽬,可能对应的配置⽂件有多

个,项⽬在启动部署时会将多个配置⽂件同时加载进来。

service.xml

dao.xml

4.2.1. 可变参数,传⼊多个⽂件名

4.2.2. 通过总的配置⽂件import其他配置⽂件

spring.xml

ApplicationContext ac = new

FileSystemXmlApplicationContext("C:/IdeaWorkspace/spring01/src/main/resources/

spring.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

https://www.springframework.org/schema/beans/spring-beans.xsd">

<?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

https://www.springframework.org/schema/beans/spring-beans.xsd">

// 同时加载多个资源⽂件

ApplicationContext ac = new

ClassPathXmlApplicationContext(“spring.xml”,“dao.xml”);加载时只需加载总的配置⽂件即可

5. Spring IOC 容器 Bean 对象实例化

5.1. 构造器实例化

注:通过默认构造器创建 空构造⽅法必须存在 否则创建失败

\1. 设置配置⽂件 spring.xml

\2. 获取实例化对象

5.2. 静态⼯⼚实例化(了解)

注:

<?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

https://www.springframework.org/schema/beans/spring-beans.xsd">

// 加载总的资源⽂件

ApplicationContext ac = new ClassPathXmlApplicationContext(“spring.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

https://www.springframework.org/schema/beans/spring-beans.xsd">

ApplicationContext ac = new ClassPathXmlApplicationContext(“spring.xml”);

UserService userService = (UserService) ac.getBean(“userService”);

userService.test();要有该⼯⼚类及⼯⼚⽅法

⼯⼚⽅法为静态的

\1. 定义静态⼯⼚类

package com.xxxx.factory;

import com.xxxx.service.UserService;

/**

* 定义静态⼯⼚类

*/

public class StaticFactory {

/**

* 定义对应的静态⽅法,返回实例化对象

* @return

*/

public static UserService createUserService() {

return new UserService();

}

}

\2. 设置配置⽂件 spring.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

https://www.springframework.org/schema/beans/spring-beans.xsd">

<bean id=“userService” class=“com.xxxx.factory.StaticFactory” factory

method=“createUserService”>

\3. 获取实例化对象

ApplicationContext ac = new ClassPathXmlApplicationContext(“spring.xml”);

UserService userService = (UserService) ac.getBean(“userService”);

userService.test();当我们指定Spring使⽤静态⼯⼚⽅法来创建Bean实例时,Spring将先解析配置⽂件,并根据配

置⽂件指定的信息,通过反射调⽤静态⼯⼚类的静态⼯⼚⽅法,并将该静态⼯⼚⽅法的返回值作为

Bean实例,在这个过程中,Spring不再负责创建Bean实例,Bean实例是由⽤户提供的静态⼯⼚

⽅法提供的。

5.3. 实例化⼯⼚实例化(了解)

注:

⼯⼚⽅法为⾮静态⽅法

需要配置⼯⼚bean,并在业务bean中配置factory-bean,factory-method属性

\1. 定义⼯⼚类

\2. 设置配置⽂件 spring.xml

package com.xxxx.factory;

import com.xxxx.service.UserService;

/**

* 定义⼯⼚类

*/

public class InstanceFactory {

/**

* 定义⽅法,返回实例化对象

* @return

*/

public UserService createUserService() {

return new UserService();

}

}

<?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

https://www.springframework.org/schema/beans/spring-beans.xsd">

3. 获取实例化对象

5.4. Spring三种实例化Bean的⽅式⽐较

⽅式⼀:通过bean的缺省构造函数创建,当各个bean的业务逻辑相互⽐较独⽴的时候或者和外界

关联较少的时候可以使⽤。

⽅式⼆:利⽤静态factory⽅法创建,可以统⼀管理各个bean的创建,如各个bean在创建之前需要

相同的初始化处理,则可⽤这个factory⽅法险进⾏统⼀的处理等等。

⽅式三:利⽤实例化factory⽅法创建,即将factory⽅法也作为了业务bean来控制,1可⽤于集成

其他框架的bean创建管理⽅法,2能够使bean和factory的⻆⾊互换。

开发中项⽬⼀般使⽤⼀种⽅式实例化bean,项⽬开发基本采⽤第⼀种⽅式,交给Spring托管,使⽤

时直接拿来使⽤即可。另外两种了解

6. Spring IOC 注⼊

⼿动实例化与外部引⼊

图⼀:

图⼆:

<bean id=“userService” factory-bean=“instanceFactory” factory

method=“createUserService”>

ApplicationContext ac = new ClassPathXmlApplicationContext(“spring.xml”);

UserService userService = (UserService) ac.getBean(“userService”);

userService.test();对⽐发现:图⼆中对于 UserDao 对象的创建并没有像图⼀那样主动的去实例化,⽽是通过带参⽅法

形式将UserDao 传⼊过来,从⽽实现 UserService 对UserDao类 的依赖。

⽽实际创建对象的幕后对象即是交给了外部来创建。

6.1. Spring IOC ⼿动装配(注⼊)

Spring ⽀持的注⼊⽅式共有四种:set 注⼊、构造器注⼊、静态⼯⼚注⼊、实例化⼯⼚注⼊。

6.1.1. set⽅法注⼊

注:

属性字段需要提供set⽅法

四种⽅式,推荐使⽤set⽅法注⼊

6.1.1.1. 业务对象 JavaBean

\1. 属性字段提供set⽅法

\2. 配置⽂件的bean标签设置property标签

public class UserService {

// 业务对象UserDao set注⼊(提供set⽅法)

private UserDao userDao;

public void setUserDao(UserDao userDao) {

this.userDao = userDao;

}

}

<?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/beans6.1.1.2. 常⽤对象和基本类型

\1. 属性字段提供set⽅法

\2. 配置⽂件的bean标签设置property标签

https://www.springframework.org/schema/beans/spring-beans.xsd">

public class UserService {

// 常⽤对象String set注⼊(提供set⽅法)

private String host;

public void setHost(String host) {

this.host = host;

}

// 基本类型Integer set注⼊(提供set⽅法)

private Integer port;

public void setPort(Integer port) {

this.port = port;

}

}

<?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

https://www.springframework.org/schema/beans/spring-beans.xsd">

6.1.1.3. 集合类型和属性对象

\1. 属性字段提供set⽅法

\2. 配置⽂件的bean标签设置property标签

public class UserService {

// List集合 set注⼊(提供set⽅法)

public List list;

public void setList(List list) {

this.list = list;

}

// Set集合 set注⼊(提供set⽅法)

private Set set;

public void setSet(Set set) {

this.set = set;

}

// Map set注⼊(提供set⽅法)

private Map<String,Object> map;

public void setMap(Map<String, Object> map) {

this.map = map;

}

// Properties set注⼊(提供set⽅法)

private Properties properties;

public void setProperties(Properties properties) {

this.properties = properties;

}

}

<?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 https://www.springframework.org/schema/beans/spring-beans.xsd”>

上海

北京

杭州

上海SH

北京BJ

杭州HZ

周杰伦

我是如此相信

林俊杰

可惜没如果

陈奕迅

⼗年

东⽅明珠

天安⻔6.1.1.4. 测试代码

UserService.java

⻄湖

public class UserService {

// 业务对象UserDao set注⼊(提供set⽅法)

private UserDao userDao;

public void setUserDao(UserDao userDao) {

this.userDao = userDao;

}

// 常⽤对象String set注⼊(提供set⽅法)

private String host;

public void setHost(String host) {

this.host = host;

}

// 基本类型Integer set注⼊(提供set⽅法)

private Integer port;

public void setPort(Integer port) {

this.port = port;

}

// List集合 set注⼊(提供set⽅法)

public List list;

public void setList(List list) {

this.list = list;

}

// List集合输出

public void printList() {

list.forEach(s -> System.out.println(s));

}

// Set集合 set注⼊(提供set⽅法)

private Set set;

public void setSet(Set set) {

this.set = set;

}

// Set集合输出

public void printSet() {

set.forEach(s -> System.out.println(s));

} // Map set注⼊(提供set⽅法)

private Map<String,Object> map;

public void setMap(Map<String, Object> map) {

this.map = map;

}

// Map输出

public void printMap() {

map.forEach((k,v) -> System.out.println(k + “,” + v));

}

// Properties set注⼊(提供set⽅法)

private Properties properties;

public void setProperties(Properties properties) {

this.properties = properties;

}

// Properties输出

public void printProperties(){

properties.forEach((k,v) -> System.out.println(k + “,”+ v ));

}

public void test(){

System.out.println(“UserService Test…”);

userDao.test();

studentDao.test();

System.out.println(“Host:” + host + “,port:” + port);

// List集合

printList();

// Set集合

printSet();

// Map

printMap();

// Properties

printProperties();

}

}spring.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

https://www.springframework.org/schema/beans/spring-beans.xsd">

上海

北京

杭州

上海SH

北京BJ

杭州HZ

6.1.2. 构造器注⼊

注:

提供带参构造器

6.1.2.1. 单个Bean对象作为参数

Java 代码

周杰伦

我是如此相信

林俊杰

可惜没如果

陈奕迅

⼗年

东⽅明珠

天安⻔

⻄湖

public class UserService {

private UserDao userDao; // JavaBean 对象

public UserService(UserDao userDao) {

this.userDao = userDao;

}

public void test(){

System.out.println(“UserService Test…”);XML配置

6.1.2.2. 多个Bean对象作为参数

Java 代码

userDao.test();

}

}

<?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

https://www.springframework.org/schema/beans/spring-beans.xsd">

public class UserService {

private UserDao userDao; // JavaBean 对象

private AccountDao accountDao // JavaBean 对象

public UserService(UserDao userDao, AccountDao accountDao) {

this.userDao = userDao;

this.accountDao = accountDao;

}

public void test(){

System.out.println(“UserService Test…”);

userDao.test();

accountDao.test();

}XML配置

6.1.2.3. Bean对象和常⽤对象作为参数

Java 代码

}

<?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

https://www.springframework.org/schema/beans/spring-beans.xsd">

public class UserService {

private UserDao userDao; // JavaBean 对象

private AccountDao accountDao; // JavaBean 对象

private String uname; // 字符串类型

public UserService(UserDao userDao, AccountDao accountDao, String uname) {

this.userDao = userDao;

this.accountDao = accountDao;

this.uname = uname;

}

public void test(){

System.out.println(“UserService Test…”);

userDao.test();

accountDao.test();

System.out.println(“uname:” + uname);XML配置

6.1.2.4. 循环依赖问题

循环问题产⽣的原因:

Bean通过构造器注⼊,之间彼此相互依赖对⽅导致bean⽆法实例化。

问题展示:

\1. Java 代码

}

}

<?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

https://www.springframework.org/schema/beans/spring-beans.xsd">

public class AccountService {

private RoleService roleService;

public AccountService(RoleService roleService) {

this.roleService = roleService;

}

public void test() { System.out.println(“AccountService Test…”);

}

}

public class RoleService {

private AccountService accountService;

public RoleService(AccountService accountService) {

this.accountService = accountService;

}

public void test() {

System.out.println(“RoleService Test…”);

}

}

\2. XML配置

如何解决:将构造器注⼊改为set⽅法注⼊

\1. Java代码

public class AccountService {

private RoleService roleService;

/* public AccountService(RoleService roleService) {

this.roleService = roleService;

}*/

public void setRoleService(RoleService roleService) {

this.roleService = roleService;

}2. XML配置

6.1.3. 静态⼯⼚注⼊

\1. 定义静态⼯⼚类

public void test() {

System.out.println(“AccountService Test…”);

}

}

public class RoleService {

private AccountService accountService;

/* public RoleService(AccountService accountService) {

this.accountService = accountService;

}*/

public void setAccountService(AccountService accountService) {

this.accountService = accountService;

}

public void test() {

System.out.println(“RoleService Test…”);

}

}

2. Java代码

\3. XML配置

在配置⽂件中设置bean标签,指定⼯⼚对象并设置对应的⽅法

6.1.4. 实例化⼯⼚注⼊

\1. 定义⼯⼚类

public class StaticFactory {

// 定义静态⽅法

public static TypeDao createTypeDao() {

return new TypeDao();

}

}

public class TypeService {

private TypeDao typeDao;

public void setTypeDao(TypeDao typeDao) {

this.typeDao = typeDao;

}

public void test() {

System.out.println(“TypeService Test…”);

}

}

<bean id=“typeDao” class=“com.xxxx.factory.StaticFactory” factory

method=“createTypeDao”>

public class InstanceFactory {

public TypeDao createTypeDao() {

return new TypeDao();

}

}2. Java代码

\3. XML配置

声明⼯⼚bean标签,声明bean对象,指明⼯⼚对象和⼯⼚⽅法

重点掌握set注⼊和构造器注⼊,⼯⼚⽅式了解即可。实际开发中基本使⽤set⽅式注⼊bean

6.1.5. 注⼊⽅式的选择

开发项⽬中set⽅式注⼊⾸选

使⽤构造注⼊可以在构建对象的同时⼀并完成依赖关系的建⽴,对象⼀建⽴则所有的⼀切也就准备好

了,但如果要建⽴的对象关系很多,使⽤构造器注⼊会在构建函数上留下⼀⻓串的参数,且不易记忆,这

时使⽤Set注⼊会是个不错的选择。

使⽤Set注⼊可以有明确的名称,可以了解注⼊的对象会是什么,像setXXX()这样的名称会⽐记忆

Constructor上某个参数的位置代表某个对象更好。

p名称空间的使⽤

public class TypeService {

private TypeDao typeDao;

public void setTypeDao(TypeDao typeDao) {

this.typeDao = typeDao;

}

public void test() {

System.out.println(“TypeService Test…”);

}

}

<bean id=“typeDao” factory-bean=“instanceFactory” factory

method=“createTypeDao”>spring2.5以后,为了简化setter⽅法属性注⼊,引⽤p名称空间的概念,可以将 ⼦元素,简化为元素

属性配置。

\1. 属性字段提供 set ⽅法

\2. 在配置⽂件 spring.xml 引⼊ p 名称空间

6.2. Spring IOC ⾃动装配(注⼊)

注解⽅式注⼊ Bean

public class UserService {

// 业务对象UserDao set注⼊(提供set⽅法)

private UserDao userDao;

public void setUserDao(UserDao userDao) {

this.userDao = userDao;

}

// 常⽤对象String set注⼊(提供set⽅法)

private String host;

public void setHost(String host) {

this.host = host;

}

}

xmlns:p=“http://www.springframework.org/schema/p”

<?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:p=“http://www.springframework.org/schema/p”

xsi:schemaLocation="http://www.springframework.org/schema/beans

https://www.springframework.org/schema/beans/spring-beans.xsd">

<bean id=“userService” class=“com.xxxx.service.UserService”

p:userDao-ref=“userDao”

p:host=“127.0.0.1” />

对于 bean 的注⼊,除了使⽤ xml 配置以外,可以使⽤注解配置。注解的配置,可以简化配置⽂件,

提⾼开发的速度,使程序看上去更简洁。对于注解的解释,Spring对于注解有专⻔的解释器,对定义的

注解进⾏解析,实现对应bean对象的注⼊。通过反射技术实现。

6.2.1. 准备环境

\1. 修改配置⽂件

\2. 开启⾃动化注⼊

\3. 给注⼊的bean对象添加注解

6.2.2. @Resource注解

@Resource注解实现⾃动注⼊(反射)

默认根据属性字段名称查找对应的bean对象 (属性字段的名称与bean标签的id属性值相等)

如果属性字段名称未找到,则会通过类型(Class类型)查找

属性可以提供set⽅法,也可以不提供set⽅法

注解可以声明在属性级别 或 set⽅法级别

可以设置name属性,name属性值必须与bean标签的id属性值⼀致;如果设置了name属性值,

就只会按照name属性值查找bean对象

当注⼊接⼝时,如果接⼝只有⼀个实现则正常实例化;如果接⼝存在多个实现,则需要使⽤name

属性指定需要被实例化的bean对象

代码示例

\1. 默认根据属性字段名称查找对应的bean对象 (属性字段的名称与bean标签的id属性值相等)

<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

https://www.springframework.org/schema/beans/spring-beans.xsd

http://www.springframework.org/schema/context

http://www.springframework.org/schema/context/spring-context.xsd">

context:annotation-config/

/**

* @Resource注解实现⾃动注⼊(反射)

* 默认根据属性字段名称查找对应的bean对象 (属性字段的名称与bean标签的id属性值相等)

*/

public class UserService { @Resource

private UserDao userDao; // 属性字段的名称与bean标签的id属性值相等

public void setUserDao(UserDao userDao) {

this.userDao = userDao;

}

public void test() {

// 调⽤UserDao的⽅法

userDao.test();

}

}

\2. 如果属性字段名称未找到,则会通过类型(Class类型)查找

/**

* @Resource注解实现⾃动注⼊(反射)

* 如果属性字段名称未找到,则会通过类型(Class类型)查找

*/

public class UserService {

@Resource

private UserDao ud; // 当在配置⽂件中属性字段名(ud)未找到,则会查找对应的

class(UserDao类型)

public void setUd(UserDao ud) {

this.ud = ud;

}

public void test() {

// 调⽤UserDao的⽅法

ud.test();

}

}

\3. 属性可以提供set⽅法,也可以不提供set⽅法

/**

* @Resource注解实现⾃动注⼊(反射)

* 属性可以提供set⽅法,也可以不提供set⽅法

*/

public class UserService {

@Resource

private UserDao userDao; // 不提供set⽅法 public void test() {

// 调⽤UserDao的⽅法

userDao.test();

}

}

\4. 注解可以声明在属性级别 或 set⽅法级别

/**

* @Resource注解实现⾃动注⼊(反射)

* 注解可以声明在属性级别 或 set⽅法级别

*/

public class UserService {

private UserDao userDao;

@Resource // 注解也可设置在set⽅法上

public void setUserDao(UserDao userDao) {

this.userDao = userDao;

}

public void test() {

// 调⽤UserDao的⽅法

userDao.test();

}

}

\5. 可以设置name属性,name属性值必须与bean标签的id属性值⼀致;如果设置了name属性值,

就只会按照name属性值查找bean对象

/**

* @Resource注解实现⾃动注⼊(反射)

* 可以设置name属性,name属性值必须与bean的id属性值⼀致;

* 如果设置了name属性值,就只会按照name属性值查找bean对象

*/

public class UserService {

@Resource(name = “userDao”) // name属性值与配置⽂件中bean标签的id属性值⼀致

private UserDao ud;

public void test() {

// 调⽤UserDao的⽅法

ud.test();

}

}6. 当注⼊接⼝时,如果接⼝只有⼀个实现则正常实例化;如果接⼝存在多个实现,则需要使⽤name

属性指定需要被实例化的bean对象

定义接⼝类 IUserDao.java

package com.xxxx.dao;

/**

* 定义接⼝类

*/

public interface IUserDao {

public void test();

}

定义接⼝实现类 UserDao01.java

package com.xxxx.dao;

/**

* 接⼝实现类

*/

public class UserDao01 implements IUserDao {

@Override

public void test(){

System.out.println(“UserDao01…”);

}

}

定义接⼝实现类 UserDao02.java

package com.xxxx.dao;

/**

* 接⼝实现类

*/

public class UserDao02 implements IUserDao {

@Override

public void test(){

System.out.println(“UserDao02…”);

}

}

XML配置⽂件使⽤注解 UserService.java

6.2.3. @Autowired注解

@Autowired注解实现⾃动化注⼊:

默认通过类型(Class类型)查找bean对象 与属性字段的名称⽆关

属性可以提供set⽅法,也可以不提供set⽅法

注解可以声明在属性级别 或 set⽅法级别

可以添加@Qualififier结合使⽤,通过value属性值查找bean对象(value属性值必须要设置,且值

要与bean标签的id属性值对应)

\1. 默认通过类型(Class类型)查找bean对象 与属性字段的名称⽆关

context:annotation-config/

/**

* @Resource注解实现⾃动注⼊(反射)

* 当注⼊接⼝时,如果接⼝只有⼀个实现则正常实例化;如果接⼝存在多个实现,则需要使⽤

name属性指定需要被实例化的bean对象

*/

public class UserService {

@Resource(name = “userDao01”) // name属性值与其中⼀个实现类的bean标签的id属

性值⼀致

private IUserDao iUserDao; // 注⼊接⼝(接⼝存在多个实现)

public void test() {

iUserDao.test();

}

}

/**

* @Autowired注解实现⾃动化注⼊

* 默认通过类型(Class类型)查找bean对象 与属性字段的名称⽆关

*/

public class UserService {

@Autowired

private UserDao userDao; // 默认通过类型(Class类型)查找bean对象 与属性字段

的名称⽆关 public void setUserDao(UserDao userDao) {

this.userDao = userDao;

}

public void test() {

// 调⽤UserDao的⽅法

userDao.test();

}

}

\2. 属性可以提供set⽅法,也可以不提供set⽅法

/**

* @Autowired注解实现⾃动化注⼊

* 属性可以提供set⽅法,也可以不提供set⽅法

*/

public class UserService {

@Autowired

private UserDao userDao; // 不提供set⽅法

public void test() {

// 调⽤UserDao的⽅法

userDao.test();

}

}

\3. 注解可以声明在属性级别 或 set⽅法级别

/**

* @Autowired注解实现⾃动化注⼊

* 注解可以声明在属性级别 或 set⽅法级别

*/

public class UserService {

private UserDao userDao;

@Autowired// 注解可以声明在set⽅法级别

public void setUserDao(UserDao userDao) {

this.userDao = userDao;

}

public void test() {

// 调⽤UserDao的⽅法

userDao.test();

}

}4. 可以添加@Qualififier结合使⽤,通过value属性值查找bean对象(value属性值必须要设置,且值

要与bean标签的id属性值对应)

推荐使⽤**@Resource** 注解是属于J2EE的,减少了与Spring的耦合。

7. Spring IOC 扫描器

实际的开发中,bean的数量⾮常多,采⽤⼿动配置bean的⽅式已⽆法满⾜⽣产需要,Spring这时候

同样提供了扫描的⽅式,对扫描到的bean对象统⼀进⾏管理,简化开发配置,提⾼开发效率。

7.1. Spring IOC 扫描器的配置

\1. 设置⾃动化扫描范围

/**

* @Autowired注解实现⾃动化注⼊

* 可以添加@Qualifier结合使⽤,通过value属性值查找bean对象

value属性值必须要设置,且值要与bean标签的id属性值对应

*/

public class UserService {

@Autowired

@Qualifier(value=“userDao”) // value属性值必须要设置,且值要与bean标签的id属

性值对应

private UserDao userDao;

public void test() {

userDao.test();

}

}

Spring IOC 扫描器

作⽤:bean对象统⼀进⾏管理,简化开发配置,提⾼开发效率

1、设置⾃动化扫描的范围

如果bean对象未在指定包范围,即使声明了注解,也⽆法实例化

2、使⽤指定的注解(声明在类级别) bean对象的id属性默认是 类的⾸字⺟⼩写

Dao层:

@Repository

Service层:

@Service

Controller层:

@Controller

任意类:

@Component

注:开发过程中建议按照指定规则声明注解<?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

https://www.springframework.org/schema/beans/spring-beans.xsd

http://www.springframework.org/schema/context

http://www.springframework.org/schema/context/spring-context.xsd">

<context:component-scan base-package=“com.xxxx”/>

\2. 使⽤特定的注解

@Repository (Dao层)

@Repository

public class ResourceDao {

public void test() {

System.out.println(“ResourceDao…”);

}

}

@Service(Service层 )

@Service

public class ResourceService {

@Resource

private ResourceDao resourceDao; // service层注⼊dao层的bean对象

public void test() {

System.out.println(“ResourceService…”);

resourceDao.test();

}

}

@Controller (Controller 层 )@Component (任意层)

7.2. Spring 模拟⽤户登录流程

7.2.1. Dao层 (查询⽤户记录)

\1. 定义JavaBean User.java

@Controller

public class ResourceController {

@Autowired

private ResourceService resourceService; // Controller层注⼊service层的

bean对象

public void test() {

System.out.println(“ResourceController…”);

resourceService.test();

}

}

@Component

public class PropertyUtils {

public void test(){

System.out.println(“PropertyUtils…”);

}

}

package com.xxxx.po;

/**

* User ⽤户实体类

*/

public class User {

private String userName; // ⽤户名称

private String userPwd; // ⽤户密码

public String getUserName() {

return userName;

}

public void setUserName(String userName) {

this.userName = userName;

}2. 编写Dao层 UserDao.java

7.2.2. Service层 (业务逻辑处理)

\1. 定义业务处理返回消息模型 MessageModel.java

public String getUserPwd() {

return userPwd;

}

public void setUserPwd(String userPwd) {

this.userPwd = userPwd;

}

}

package com.xxxx.dao;

import com.xxxx.po.User;

import org.springframework.stereotype.Repository;

@Repository

public class UserDao {

private final String USERNAME = “admin”;

private final String USERPWD = “admin”;

/**

* 通过⽤户名称查询⽤户对象

* @param userName

* @return

*/

public User queryUserByUserName(String userName){

User user = null;

// 判断⽤户名称是否正确

if(!USERNAME.equals(userName)){

// 如果不正确,返回null

return null;

}

// 如果正确,将⽤户名称和密码设置到user对象中

user = new User();

user.setUserName(USERNAME);

user.setUserPwd(USERPWD);

return user;

}

}package com.xxxx.po.vo;

/**

* 定义业务处理返回消息模型

* 封装返回结果

*/

public class MessageModel {

private Integer resultCode = 1; // 结果状态码 1=成功,0=失败

private String resultMsg = “操作成功!”; // 结果提示信息

public Integer getResultCode() {

return resultCode;

}

public void setResultCode(Integer resultCode) {

this.resultCode = resultCode;

}

public String getResultMsg() {

return resultMsg;

}

public void setResultMsg(String resultMsg) {

this.resultMsg = resultMsg;

}

}

\2. 编写Service层 UserService.java

package com.xxxx.service;

import com.xxxx.dao.UserDao1;

import com.xxxx.po.User;

import com.xxxx.po.vo.MessageModel;

import org.springframework.stereotype.Service;

import javax.annotation.Resource;

@Service

public class UserService {

@Resource

private UserDao userDao;

/**

* 验证⽤户登录

* @param userName

* @param userPwd7.2.3. Controller层 (接收请求)

\1. 编写Controller层 UserController.java

* @return

*/

public MessageModel userLoginCheck(String userName, String userPwd){

// 定义业务处理返回消息模型

MessageModel messageModel = new MessageModel();

// 判断⽤户名称是否⾮空

if(null == userName || “”.equals(userName.trim())){

messageModel.setResultCode(0);

messageModel.setResultMsg(“⽤户名不能为空!”);

return messageModel;

}

// 判断⽤户密码是否为空

if(null == userPwd || “”.equals(userPwd.trim())){

messageModel.setResultCode(0);

messageModel.setResultMsg(“密码不能为空!”);

return messageModel;

}

// 通过⽤户名称查询⽤户对象

User user = userDao.queryUserByUserName(userName);

// 判断⽤户对象是否为空

if(null == user){

messageModel.setResultCode(0);

messageModel.setResultMsg(“该⽤户不存在!”);

return messageModel;

}

// 如果⽤户对象不为空,判断密码是否正确

if(!user.getUserPwd().equals(userPwd)){

messageModel.setResultCode(0);

messageModel.setResultMsg(“⽤户密码不正确!”);

return messageModel;

}

// 登录成功

messageModel.setResultMsg(“登录成功!”);

return messageModel;

}

}

package com.xxxx.controller;

import com.xxxx.po.vo.MessageModel;

import com.xxxx.service.UserService1;

import org.springframework.stereotype.Controller;7.2.4. 通过 JUnit 进⾏测试

import javax.annotation.Resource;

@Controller

public class UserController {

@Resource

private UserService userService;

/**

* ⽤户登录

* @param userName

* @param userPwd

* @return

*/

public MessageModel login(String userName, String userPwd){

// 调⽤Dao层判断⽤户登录操作,返回结果

MessageModel messageModel = userService.userLoginCheck(userName,

userPwd);

return messageModel;

}

}

package com.xxxx;

import com.xxxx.controller.UserController;

import com.xxxx.po.vo.MessageModel;

import org.junit.Test;

import org.springframework.context.ApplicationContext;

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestLogin {

@Test

public void test() {

// 得到Spring容器上下⽂环境

ApplicationContext ac = new

ClassPathXmlApplicationContext(“spring.xml”);

// 得到UserController实例化对象

UserController userController = (UserController)

ac.getBean(“userController”);

// 传⼊参数调⽤UserController的⽅法,返回封装类

MessageModel messageModel= userController.login(“admin”, “admin”);

System.out.println(“状态码:” + messageModel.getResultCode() + ",提示信

息:" + messageModel.getResultMsg());

}

}8. Bean的作⽤域与⽣命周期

8.1. Bean的作⽤域

默认情况下,我们从Spring容器中拿到的对象均是单例的,对于bean的作⽤域类型如下:

8.1.1. singleton 作⽤域

注意**: lazy-init是懒加载,** 如果等于true时作⽤是指Spring容器启动的时候不会去实例化这个bean,

⽽是在程序调⽤时才去实例化**.** 默认是falseSpring容器启动时实例化**.**

默认情况下,被管理的bean只会IOC容器中存在⼀个实例,对于所有获取该Bean的操作Spring容器

将只返回同⼀个Bean。

容器在启动的情况下就实例化所有singletonbean对象,并缓存与容器中

lazy-init属性(懒加载)

如果为false,则在IOC容器启动时会实例化bean对象,默认false

如果为true,则IOC容器启动时不会实例化Bean对象,在使⽤bean对象时才会实例化

lazy-init设置为false有什么好处?

1)可以提前发现潜在的配置问题

2)Bean 对象存在于缓存中,使⽤时不⽤再去实例化bean,加快程序运⾏效率

什么对象适合作为单例对象?

⼀般来说对于⽆状态或状态不可改变的对象适合使⽤单例模式。(不存在会改变对象状态的成员变

量)

⽐如:controller层、service层、dao层

什么是⽆状态或状态不可改变的对象? 实际上对象状态的变化往往均是由于属性值得变化⽽引起的,⽐如user类 姓名属性会有变化,属性姓

名的变化⼀般会引起user对象状态的变化。对于我们的程序来说,⽆状态对象没有实例变量的存在,保

证了线程的安全性,service 层业务对象即是⽆状态对象。线程安全的。

8.1.2. prototype 作⽤域

通过scope=“prototype” 设置bean的类型 ,每次向Spring容器请求获取Bean都返回⼀个全新的

Bean,相对于"singleton"来说就是不缓存Bean,每次都是⼀个根据Bean定义创建的全新Bean。

8.1.3. Web应⽤中的作⽤域

\1. request作⽤域

表示每个请求需要容器创建⼀个全新Bean。⽐如提交表单的数据必须是对每次请求新建⼀个Bean

来保持这些表单数据,请求结束释放这些数据。

\2. session作⽤域

表示每个会话需要容器创建⼀个全新Bean。⽐如对于每个⽤户⼀般会有⼀个会话,该⽤户的⽤户

信息需要存储到会话中,此时可以将该Bean作⽤域配置为session级别。

\3. globalSession作⽤域

类似于session作⽤域,其⽤于portlet(Portlet是基于Java的Web组件,由Portlet容器管理,并由

容器处理请求,⽣产动态内容)环境的web应⽤。如果在⾮portlet环境将视为session作⽤域。

配置⽅式和基本的作⽤域相同,只是必须要有web环境⽀持,并配置相应的容器监听器或拦截器从⽽

能应⽤这些作⽤域,⽬前先熟悉概念,后续集成web时讲解具体使⽤,⼤家只需要知道有这些作⽤域就

可以了。8.2. Bean的⽣命周期

对⽐已经学过的servlet ⽣命周期(容器启动装载并实例化servlet类,初始化servlet,调⽤service⽅

法,销毁servlet)。

同样对于Spring容器管理的bean也存在⽣命周期的概念

Spring中,Bean的⽣命周期包括Bean的定义、初始化、使⽤和销毁4个阶段

8.2.1. Bean的定义

在Spring中,通常是通过配置⽂档的⽅式来定义Bean的。

在⼀个配置⽂档中,可以定义多个Bean。

8.2.2. Bean 的初始化

默认在IOC容器加载时,实例化对象。

Spring bean 初始化有两种⽅式:

⽅式⼀:在配置⽂档中通过指定 init-method 属性来完成。

⽅式⼆: 实现 org.springframework.beans.factory.InitializingBean 接⼝。

public class RoleService {

// 定义初始化时需要被调⽤的⽅法

public void init() {

System.out.println(“RoleService init…”);

}

}

<bean id=“roleService” class=“com.xxxx.service.RoleService” init

method=“init”>

public class RoleService implements InitializingBean {

@Override

public void afterPropertiesSet() throws Exception {

System.out.println(“RoleService init…”);

}

}

Bean对象实例化过程是在Spring容器初始化时被实例化的,但也不是不可改变的,可以通过 lazy

init=“true” 属性延迟bean对象的初始化操作,此时再调⽤getBean ⽅法时才会进⾏bean的初始化操作

8.2.3. Bean 的使⽤

⽅式⼀:使⽤ BeanFactory

⽅式⼆:使⽤ ApplicationContext

8.2.4. Bean的销毁

实现销毁⽅式(Spring容器会维护bean对象的管理,可以指定bean对象的销毁所要执⾏的⽅法)。

步骤⼀:实现销毁⽅式(Spring容器会维护bean对象的管理,可以指定bean对象的销毁所要执⾏的⽅

法)

步骤⼆:通过 AbstractApplicationContext 对象,调⽤其close⽅法实现bean的销毁过程

// 得到Spring的上下⽂环境

BeanFactory factory = new ClassPathXmlApplicationContext(“spring.xml”);

RoleService roleService = (RoleService) factory.getBean(“roleService”);

// 得到Spring的上下⽂环境

ApplicationContext ac = new ClassPathXmlApplicationContext(“spring.xml”);

RoleService roleService = (RoleService) ac.getBean(“roleService”);

<bean id=“roleService” class=“com.xxxx.service.RoleService” destroy

method=“destroy”>

AbstractApplicationContext ctx=new

ClassPathXmlApplicationContext(“spring.xml”);

ctx.close();

IOC/DI-控制反转和依赖注⼊

将对象实例化的创建过程转交给外部容器(IOC容器 充当⼯⼚⻆⾊)去负责;属性赋值的操作;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值