ok了家人们,这周学习spring框架,我们一起去看看吧
Spring
一.Spring概述
1.1 Spring介绍
官网: https://spring.io/
广义的 Spring : Spring 技术栈 (全家桶)
广义上的 Spring 泛指以 Spring Framework 为基础的 Spring
技术栈。
经过十多年的发展, Spring 已经不再是一个单纯的应用框
架,而是逐渐发展成为一个由多个不同子项目(模块)组成的
成熟技术,例如 Spring Framework 、 Spring MVC 、
SpringBoot 、 Spring Cloud 、 Spring Data 、 Spring Security
等,其中 Spring Framework 是其他子项目的基础。
狭义的 Spring : Spring Framework (基础框架)
狭义的 Spring 特指 Spring Framework ,通常我们将它称为
Spring 框架。
Spring 是分层的 Java SE/EE 应用 full-stack 轻量级开源框
架,以 IoC ( Inverse Of Control :反转控制)和 AOP
( Aspect Oriented Programming :面向切面编程)为内
核,提供了展现层 Spring MVC 和持久层 Spring JDBC 以及业
务层事务管理等众多的企业级应用技术,还能整合开源世界众
多著名的第三方框架和类库,逐渐成为使用最多的 Java EE 企
业应用开源框架。
1.2 spring 的优势
- 方便解耦,简化开发
通过 Spring 提供的 IoC 容器,可以将对象间的依赖关系交由
Spring 进行控制,避免硬编码所造成的过度程序耦合。用户
也不必再为单例模式类、属性文件解析等这些很底层的需求编
写代码,可以更专注于上层的应用。
- AOP 编程的支持
通过 Spring 的 AOP 功能,方便进行面向切面的编程,许多不容易用传统 OOP 实现的功能可以通过 AOP 轻松应付。
- 声明式事务的支持
可以将我们从单调烦闷的事务管理代码中解脱出来,通过声明
式方式灵活的进行事务的管理,提高开发效率和质量。
- 方便程序的测试
可以用非容器依赖的编程方式进行几乎所有的测试工作,测试
不再是昂贵的操作,而是随手可做的事情。
- 方便集成各种优秀框架
Spring 可以降低各种框架的使用难度,提供了对各种优秀框
架( Struts 、 Hibernate 、 Hessian 、 Quartz 等)的直接支
持。
- 降低 JavaEE API 的使用难度
Spring 对 JavaEE API (如 JDBC 、 JavaMail 、远程调用等)进
行了薄薄的封装层,使这些 API 的使用难度大为降低。
1.3 spring 的体系结构
二.优质程序代码的书写原则
2.1 耦合与内聚
耦合( Coupling ):代码书写过程中所使用技术的结合紧
密度 ( 程序之间的依赖程度 ) ,用于衡量软件中各个模块之间
的互联程度;
内聚( Cohesion ):代码书写过程中单个模块内部各组成
部分间的联系,用于衡量软件中各个功能模块内部的功能
联系;
程序书写的目标:高内聚,低耦合。就是同一个模块内的
各个元素之间要高度紧密,但是各个模块之间的相互依存
度却不要那么紧密
2.2 耦合和内聚代码示例
//内聚:一个方法只做一件事情(一个类只聚合一个业务属性
集)
//反例: 此方法不符合高内聚思想
public int compute(int i,int j,String label){
if("+".equals(label)){
return i+j;
}else if("-".equals(label)){
return i-j;
}else{
//do something....
}
}
//例子:
public int add(int i,int j){
return i+j;
}
public int sub(int i,int j){
return i-j;
}
//耦合:程序代码之间的依赖关系
public class UserService(){
public List<User> getAllUser(){
/**
* getAllUser方法的执行需要依赖UserDao类,
* 我们称,getAllUser方法与UserDao类之间有
耦合
**/
UserDao userDao=new UserDao();
return userDao.findAll();
}
}
public class UserDao(){
public List<User> findAll(){
//do something and return list
}
}
耦合 : 程序代码之间的依赖关系。
低耦合 : 降低程序代码之间的依赖关系 , 从而方便维护扩展和重
用 。
解耦合 : 在 java 程序代码中 , 耦合是不可能完全解开的 , 我们所说
的 " 解耦合 " 指的是解开程序编译期的耦合。
2.3 实现解耦
2.3.1 原始方案
public class UserServlet {
public static void main(String[] args) {
//要实现解耦:1.需要接口 需要多态 2.不能new实
现类对象
//UserServiceImpl01
userServiceImpl01=new UserServiceImpl01();
UserService userService=new
UserServiceImpl01();
userService.add();
}
}
public interface UserService {public void add();
}
public class UserServiceImpl01 implements
UserService{
@Override
public void add() {
System.out.println("impl01...add...");
}
}
public class UserServiceImpl02 implements
UserService{
@Override
public void add() {
System.out.println("impl02...add...");
}
}
2.3.2 使用工厂类+反射进行解耦
public class BeanFactory {
public static UserService getUserServcie(){
return new UserServiceImpl01();
}
}
public class UserServlet {
public static void main(String[] args) {
//要实现解耦:1.需要接口 需要多态 2.不能new实
现类对象
//UserServiceImpl01
userServiceImpl01=new UserServiceImpl01();
//UserService userService=new
UserServiceImpl01();
//虽然解决了之前的耦合,但是引入的新的耦合:工厂
类和业务层存在耦合
UserService userService=
BeanFactory.getUserServcie();
userService.add();
}
}
public class BeanFactory {
// public static UserService getUserServcie()
{
// return new UserServiceImpl01();
// }
//负责创建实现类对象,不能使用new
//使用反射方式创建对象,方法接受实现类对象的全限定名
public static Object getBean(String
className){
try {
Class<?> clazz =
Class.forName(className);
return clazz.newInstance();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
public class UserServlet {
public static void main(String[] args) {
//要实现解耦:1.需要接口 需要多态 2.不能new实
现类对象
//UserServiceImpl01
userServiceImpl01=new UserServiceImpl01();
//UserService userService=new
UserServiceImpl01();
//虽然解决了之前的耦合,但是引入的新的耦合:工厂
类和业务层存在耦合
//UserService userService=
BeanFactory.getUserServcie();
UserService userService= (UserService)
BeanFactory.getBean("com.lzw.service.UserService
Impl01");
userService.add();
}
}
2.3.3 使用工厂类+反射+配置文件解耦
- 导入依赖
<dependencies>
<!--DOM4j-->
<dependency>
<groupId>dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>1.6.1</version>
</dependency>
</dependencies>
- 编写beans.xml配置文件
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
<bean id="userService"
class="com.lzw.service.UserServiceImpl01">
</bean>
</beans>
- 编写工厂类
public class BeanFactory {
//定义Map集合 用于存储id和实现类对象
private static Map<String,Object> map=new
HashMap<>();
//加载并解析beans.xml文件 只需要加载一次
static {
try {
//加载beans.xml配置文件
SAXReader saxReader=new SAXReader();
InputStream in =
BeanFactory.class.getClassLoader().getResourceA
sStream("beans.xml");
Document document =
saxReader.read(in);
//解析beans.xml配置文件
Element beans =
document.getRootElement();//获取根标签beans
List<Element> beanList =
beans.elements();//获取子标签bean的集合
//遍历获取每一个bean标签
for (Element bean : beanList) {
//获取id 和 class 的属性的值
String idValue =
bean.attributeValue("id");
String classValue =
bean.attributeValue("class");
//通过反射创建对象 并存储到集合中
Object obj =
Class.forName(classValue).newInstance();
map.put(idValue,obj);
}
} catch (Exception e) {
e.printStackTrace();
}
}
//提供一个方法, 用于从Map集合中, 获取指定id( 接口
字符串) 所对应的value( 接口实现类对象 )
public static Object getBean(String id){
return map.get(id);
}
}
public class UserServlet {
public static void main(String[] args) {
//要实现解耦:1.需要接口 需要多态 2.不能new实
现类对象
//UserServiceImpl01
userServiceImpl01=new UserServiceImpl01();
//UserService userService=new
UserServiceImpl01();
//虽然解决了之前的耦合,但是引入的新的耦合:工厂
类和业务层存在耦合
//UserService userService=
BeanFactory.getUserServcie();
//存在硬编码问题
//UserService userService= (UserService)
BeanFactory.getBean("com.lzw.service.UserService
Impl01");
UserService userService= (UserService)
BeanFactory.getBean("userService");
userService.add();
}
}
三.Spring IOC 相关概念
3.1 IOC 控制反转
IoC ( Inversion Of Control )控制反转, Spring 反向控制应用
程序所需要使用的外部资源;
简单说,就是把创建创建对象的权力交给 Spring 去管理。
传统方式创建对象 : new 对象 (); ( 主动创建 ) 。当前类可以选
择主动出击( new 的方式)创建对象,但是此时耦合度
高。
IOC 方式创建对象 : 找容器 ( 被动接收 ), 本质上就是一个 Map
集合。把主动式改成被动接收,由工厂对象为当前类生产
所必须的关联对象,此时降低了两个类的依赖关系。
3.2 SpringIOC容器介绍
Spring 控制的资源全部放置在 Spring 容器中,该容器称为 IOC
容器; Spring 容器中存储的对象称为 bean 对象;
降低了组件之间的耦合性: Spring IoC 容器通过依赖注入
机制,将组件之间的依赖关系削弱,减少了程序组件之间
的耦合性,使得组件更加松散地耦合。
提高了代码的可重用性和可维护性:将组件的实例化过
程、依赖关系的管理等功能交给 Spring IoC 容器处理,使
得组件代码更加模块化、可重用、更易于维护。
方便了配置和管理: Spring IoC 容器通过 XML 文件或者注
解,轻松的对组件进行配置和管理,使得组件的切换、替
换等操作更加的方便和快捷。
交给 Spring 管理的对象(组件),方可享受 Spring 框架的
其他功能( AOP, 声明式事务管理)等
3.3 SpringIOC容器接口和实现
BeanFactory 接口提供了一种高级配置机制,能够管理任
何类型的对象,它是 SpringIoC 容器标准化超接口!
ApplicationContext 是 BeanFactory 的子接口。添加了更多
特定于企业的功能。例如更容易与 Spring 的 AOP 功能集
成
ApplicationContext 容器实现类:
3.4 SpringIoC容器管理配置方式
Spring框架提供了多种配置方式:XML配置方式、注解方式和 Java配置类方式
SSM 期间,我们使用 XML+ 注解方式为主 。 SpringBoot 期间,
我们使用 配置类 + 注解方式为主 !
四.基于XML的IOC环境搭建
1. 创建 Maven 工程 , 添加坐标
2. 准备好接口和实现类
3. 创建 spring 的配置文件 (applicationContext.xml), 配置bean标签
4. 创建工厂对象 获得 bean 调用
- 创建Maven工程, 添加坐标
<dependencies>
<!--导入spring的坐标spring-context,对应版
本是5.2.10.RELEASE-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>springcontext</artifactId>
<version>5.2.10.RELEASE</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
- 准备好接口和实现类
public interface UserService {
public void save();
}
public class UserServiceImpl implements
UserService{
@Override
public void save() {
System.out.println("service...save...");
}
}
- 创建spring的配置文件 (applicationContext.xml), 配置bean标签
<?xml version="1.0" encoding="UTF-8"?>
<beans
xmlns="http://www.springframework.org/schema/bea
ns"
xmlns:xsi="http://www.w3.org/2001/XMLSchemainstance"
xsi:schemaLocation="http://www.springframework.o
rg/schema/beans
http://www.springframework.org/schema/beans/spri
ng-beans.xsd">
<!--
bean标签:通过配置bean标签告诉IOC容器需要创建
的对象id属性:bean的唯一标识,方便后期获取Bean
class属性:类的全类名!
-->
<bean id="userService"
class="com.lzw.service.UserServiceImpl"></bean>
</beans>
public class DemoTest {
@Test
public void test01(){
//创建IoC容器,并读取配置文件
ApplicationContext ioc =
new
ClassPathXmlApplicationContext("applicationConte
xt.xml");
//方式1:根据id获取 没有指定类型,返回为
Object,需要类型转化!
UserService userService01 =
(UserService) ioc.getBean("userService");
userService01.save();
//方式2:根据类型获取,但是要求,同类型只能有一个
对象交给IoC容器管理
UserService userService02 =
ioc.getBean(UserService.class);
userService02.save();singleton(默认值):
含义:在 IOC 容器中,这个 bean 的对象始终为单实例
创建对象的时机:IOC 容器初始化时
prototype:
含义:这个 bean 在 IOC 容器中有多个实例
//方式3: 根据id和类型获取
UserService userService03 =
ioc.getBean("userService", UserService.class);
userService03.save();
}
}
五.Bean的相关配置
5.1 Bean的基础配置
<!--
bean标签:通过配置bean标签告诉IOC容器需要创建
的对象
id属性:bean的唯一标识,方便后期获取Bean
class属性:类的全类名!
-->
<bean id="userService"
class="com.lzw.service.UserServiceImpl"></bean>
5.2 Bean的作用域
- singleton(默认值):
- 含义:在 IOC 容器中,这个 bean 的对象始终为单实例
- 创建对象的时机:IOC 容器初始化时
- prototype :
- 含义:这个 bean 在 IOC 容器中有多个实例创建对象的时机:获取 bean 时如果是在 WebApplicationContext 环境下还会有另外两个作用域(但不常用):
-
- request:
- 含义:请求范围内有效的实例创建对象的时机:每次请求
-
- session :含义:会话范围内有效的实例创建对象的时机:每次会话
默认情况:我们全局只需要实例化一个 Bean 对象,绝大情况
我们也仅需创建一个对象!
<bean id="userService"
class="com.lzw.service.UserServiceImpl"
scope="singleton"></bean>
------------------------------------------------
-----------------------------------------------
public class UserServiceImpl implements
UserService{
public UserServiceImpl(){
System.out.println("无参构造方法执行
了...");
}
@Override
public void save() {
System.out.println("service...save...");
}
}
------------------------------------------------
-----------------------------------------------
public class DemoTest {
@Test
public void test01(){
//创建IoC容器,并读取配置文件;单例模式下,IOC容
器初始化后,会立即创建对象
ApplicationContext ioc =
new
ClassPathXmlApplicationContext("applicationConte
xt.xml");
UserService userService01 =
ioc.getBean("userService", UserService.class);
UserService userService02 =
ioc.getBean("userService", UserService.class);
System.out.println(userService01);
System.out.println(userService02);
}
}
<bean id="userService"
class="com.lzw.service.UserServiceImpl"
scope="prototype"></bean>
------------------------------------------------
-----------------------------------------------
public class UserServiceImpl implements
UserService{
public UserServiceImpl(){
System.out.println("无参构造方法执行
了...");
}
@Override
public void save() {
System.out.println("service...save...");
}
}
------------------------------------------------
-----------------------------------------------
@Test
public void test01(){
//创建IoC容器,并读取配置文件,
ApplicationContext ioc =
new
ClassPathXmlApplicationContext("applicationConte
xt.xml");
UserService userService01 =
ioc.getBean("userService", UserService.class);
UserService userService02 =
ioc.getBean("userService", UserService.class);
System.out.println(userService01);
System.out.println(userService02);
}
ok了家人们,明天见