今天是我在乐字节教育学习的第11天,今天主要学习的内容是Spring IOC
Spring IOC 主要内容 Spring 框架 Spring 框架概念 Spring 是众多开源java项目中的一员,基于分层的javaEE应用一站式轻量级开源框架,主要核心是 IOC(控制反转/依赖注入)与 AOP(面向切面)两大技术,实现项目在开发过程中的轻松解耦,提高项目的开发效率。 在项目中引入 Spring 立即可以带来下面的好处 降低组件之间的耦合度,实现软件各层之间的解耦。可以使用容器提供的众多服务,如:事务管理服务、消息服务等等。当我们使用容器管理事务时,开发人员就不再需要手工控制事务.也不需处理复杂的事务传播。 容器提供单例模式支持,开发人员不再需要自己编写实现代码。 容器提供了AOP技术,利用它很容易实现如权限拦截、运行期监控等功能。 Spring 源码架构 Spring 总共大约有20个模块,由1300多个不同的文件构成。而这些组件被分别整合在核心容器(Core Container)、Aop(Aspect Oriented Programming)和设备支持(Instrmentation)、数据访问及集成(Data Access/Integeration)、Web、报文发送(Messaging)、测试6个模块集合中。
核心容器: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 模块是统一表达式语言(unified EL)的扩展模块,可以查询、管理运行中的对象,同时也方便的可以调用对象方法、操作数组、集合等。它的语法类似于传统EL,但提供了额外的功能,最出色的要数函数调用和简单字符串的模板函数。
Spring-AOP:Spring-aop是Spring的另一个核心模块, 在Spring中,他是以JVM的动态代理技术为基础,然后设计出了一系列的Aop横切实现,比如前置通知、返回通知、异常通知等。通过其配置管理特性,Spring AOP 模块直接将面向切面的编程功能集成到了 Spring 框架中。所以,可以很容易地使 Spring 框架管理的任何对象支持 AOP。
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 等。
Web 模块:由Spring-web、Spring-webmvc、Spring-websocket和Spring-webmvc-portlet 4个模块组成,Web 上下文模块建立在应用程序上下文模块之上,为基于 Web 的应用程序提供了上下文。Web 模块还简化了处理多部分请求以及将请求参数绑定到域对象的工作。
报文发送:即Spring-messaging模块。 Spring-messaging是Spring4 新加入的一个模块,主要职责是为Spring 框架集成一些基础的报文传送应用。
单元测试:即Spring-test模块。Spring-test模块主要为测试提供支持
Spring 框架环境搭建环境要求 JDK 版本: JDK 1.7 及以上版本 Spring版本: Spring 5.x版本 新建 Maven 项目 创建 Maven 的普通 Java 项目 设置项目的坐标 设置项目的 Maven 环境 设置项目的名称和存放的工作空间 调整项目环境
修改 JDK 版本 <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 junit 4.12 test
build标签中的pluginManagement标签
添加 Spring 框架的依赖坐标 Maven仓库:mvnrepository.com/
org.springframework spring-context 5.2.4.RELEASE编写 Bean 对象package com.xxxx.service;public class UserService { public void test(){ System.out.println("Hello Spring!"); }}添加Spring 配置文件 在项目的src下创建文件夹 resources(Alt+insert)
将 resources 标记为资源目录
在 src\main\resources 目录下新建 spring.xml 文件,并拷贝官网文档提供的模板内容到 xml 中。 配置 bean 到 xml 中,把对应 bean 纳入到 Spring 容器来管理 spring.xml
在 spring.xml 中配置 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(); }}Spring IOC 容器 Bean 对象实例化模拟 思路:
定义Bean 工厂接口,提供获取bean方法
定义Bean工厂接口实现类,解析配置文件,实例化Bean对象
实现获取Bean方法
定义 Bean 属性对象package com.xxxx.spring;/** * 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; }}添加 dom4j 坐标依赖 dom4j dom4j 1.6.1 jaxen jaxen 1.1.6准备自定义配置文件 spring.xml
定义 Bean 工厂接口package com.xxxx.spring;/** * Bean 工厂接口定义 */public interface MyFactory { // 通过id值获取对象 public Object getBean(String id);}定义 Bean 接口的实现类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创建与配置文件中对应的Bean对象 UserService.java package com.xxxx.service; public class UserService { public void test(){ System.out.println(“UserService Test…”); }} AccountService.java package com.xxxx.service;public class AccountService { public void test(){ System.out.println(“AccountService Test…”); }}
测试是否可以获取实例化的Bean对象 package com.xxxx;import com.xxxx.spring.MyFactory;import com.xxxx.spring.MyClassPathXmlApplicationContext;import com.xxxx.service.AccountService;import com.xxxx.service.UserService;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(); }} Spring 容器在启动的时候 读取xml配置信息,并对配置的 bean 进行实例化(这里模拟的比较简单,仅用于帮助大家理解),同时通过上下文对象提供的 getBean() 方法拿到我们配置的 bean 对象,从而实现外部容器自动化维护并创建 bean 的效果。
Spring IOC 配置文件加载Spring 配置文件加载 spring.xml
根据相对路径加载资源ApplicationContext ac = new ClassPathXmlApplicationContext("spring.xml");根据绝对路径加载资源(了解)ApplicationContext ac = new FileSystemXmlApplicationContext("C:/IdeaWorkspace/spring01/src/main/resources/spring.xml"); Spring 多配置文件加载Spring 框架启动时可以加载多个配置文件到环境中。对于比较复杂的项目,可能对应的配置文件有多个,项目在启动部署时会将多个配置文件同时加载进来。 service.xml
dao.xml
可变参数,传入多个文件名// 同时加载多个资源文件ApplicationContext ac = new ClassPathXmlApplicationContext("spring.xml","dao.xml");通过总的配置文件import其他配置文件spring.xml
加载时只需加载总的配置文件即可 // 加载总的资源文件ApplicationContext ac = new ClassPathXmlApplicationContext(“spring.xml”);Spring IOC 容器 Bean 对象实例化构造器实例化 注:通过默认构造器创建 空构造方法必须存在 否则创建失败
设置配置文件 spring.xml
获取实例化对象 ApplicationContext ac = new ClassPathXmlApplicationContext(“spring.xml”);UserService userService = (UserService) ac.getBean(“userService”); userService.test();
静态工厂实例化(了解) 注: 要有该工厂类及工厂方法 工厂方法为静态的
定义静态工厂类 package com.xxxx.factory;import com.xxxx.service.UserService;/** * 定义静态工厂类 /public class StaticFactory { /* * 定义对应的静态方法,返回实例化对象 * @return */ public static UserService createUserService() { return new UserService(); }}
设置配置文件 spring.xml
获取实例化对象 ApplicationContext ac = new ClassPathXmlApplicationContext(“spring.xml”);UserService userService = (UserService) ac.getBean(“userService”); userService.test(); 当我们指定Spring使用静态工厂方法来创建Bean实例时,Spring将先解析配置文件,并根据配置文件指定的信息,通过反射调用静态工厂类的静态工厂方法,并将该静态工厂方法的返回值作为Bean实例,在这个过程中,Spring不再负责创建Bean实例,Bean实例是由用户提供的静态工厂方法提供的。
实例化工厂实例化(了解) 注: 工厂方法为非静态方法 需要配置工厂bean,并在业务bean中配置factory-bean,factory-method属性
定义工厂类 package com.xxxx.factory;import com.xxxx.service.UserService;/** * 定义工厂类 /public class InstanceFactory { /* * 定义方法,返回实例化对象 * @return */ public UserService createUserService() { return new UserService(); }}
设置配置文件 spring.xml
获取实例化对象 ApplicationContext ac = new ClassPathXmlApplicationContext(“spring.xml”);UserService userService = (UserService) ac.getBean(“userService”); userService.test();
Spring三种实例化Bean的方式比较
方式一:通过bean的缺省构造函数创建,当各个bean的业务逻辑相互比较独立的时候或者和外界关联较少的时候可以使用。
方式二:利用静态factory方法创建,可以统一管理各个bean的创建,如各个bean在创建之前需要相同的初始化处理,则可用这个factory方法险进行统一的处理等等。
方式三:利用实例化factory方法创建,即将factory方法也作为了业务bean来控制,1可用于集成其他框架的bean创建管理方法,2能够使bean和factory的角色互换。 开发中项目一般使用一种方式实例化bean,项目开发基本采用第一种方式,交给Spring托管,使用时直接拿来使用即可。另外两种了解
Spring IOC 注入 手动实例化与外部引入 图一: 图二: 对比发现:图二中对于 UserDao 对象的创建并没有像图一那样主动的去实例化,而是通过带参方法形式将UserDao 传入过来,从而实现 UserService 对UserDao类 的依赖。 而实际创建对象的幕后对象即是交给了外部来创建。 Spring IOC 手动装配(注入) Spring 支持的注入方式共有四种:set 注入、构造器注入、静态工厂注入、实例化工厂注入。 set方法注入 注: 属性字段需要提供set方法 四种方式,推荐使用set方法注入 业务对象 JavaBean
属性字段提供set方法