Java Spring 框架详解

  • Spring Bean

  • Spring AOP

  • Spring 事务管理

1 Spring入门

1.1 Spring 简介

1.1.1 Spring的由来

Spring是一个轻量级Java开发框架,最早有Rod Johnson创建,目的是为了解决企业级应用开发的业务逻辑层和其他各层的耦合问题。它是一个分层的JavaSE/JavaEE full-stack(一站式)轻量级开源框架,为开发Java应用程序提供全面的基础架构支持。Spring负责基础架构,因此Java开发者可以专注于应用程序的开发。

1.1.2 Spring的优点

(1)方便解耦,简化开发

Spring就是一个大工厂,可以将所有对象创建和依赖的关系维护,交给Spring管理。

(2)AOP编程的支持

Spring提供面向切面编程,可以方便的实现对程序进行权限拦截、运行监控等功能。

(3)声明式事务的支持

只需要通过配置就可以完成对事务的管理,而无需手动编程。

(4)方便程序的测试

Spring对Junit4支持,可以通过注解方便的测试Spring程序。

(5)方便集成各种优秀框架

Spring不排斥各种优秀的开源框架,其内部提供了对各种优秀框架的直接支持(如:Struts、Hibernate、MyBatis等)。

(6)降低JavaEE API的使用难度

Spring对JavaEE开发中非常难用的一些API(JDBC、JavaMail、远程调用等),都提供了封装,使这些API应用难度大大降低。

1.1.3 Spring的体系结构

Spring框架至今已集成了20多个模块,这些模块分布在核心容器(Core Container)、数据访问/集成(Data Access/Integration)层、Web层、AOP(Aspect Oriented Programming)模块、植入(Instrumentation)模块、消息传输(Messaging)、测试(Test)模块。
Spring体系结构如下图:
在这里插入图片描述

  1. 核心容器

Spring的核心容器是其他模块建立的基础,有Spring-core、Spring-beans、Spring-context、Spring-context-support和Spring-expression(String表达式语言)等模块组成。

Spring-core模块:提供了框架的基本组成部分,包括控制反转(Inversion of Control,IOC)和依赖注入(Dependency Injection,DI)功能。
Spring-beans模块:提供了BeanFactory,是工厂模式的一个经典实现,Spring将管理对象称为Bean。
Spring-context模块:建立在Core和Beans模块的基础之上,提供一个框架式的对象访问方式,是访问定义和配置的任何对象的媒介。ApplicationContext接口是Context模块的焦点。
Spring-context-support模块:支持整合第三方库到Spring应用程序上下文,特别是用于高速缓存(EhCache、JCache)和任务调度(CommonJ、Quartz)的支持。
Spring-expression模块:提供了强大的表达式语言去支持运行时查询和操作对象图。这是对JSP2.1规范中规定的统一表达式语言(Unified EL)的扩展。该语言支持设置和获取属性值、属性分配、方法调用、访问数组、集合和索引器的内容、逻辑和算术运算、变量命名以及从Spring的IOC容器中以名称检索对象。它还支持列表投影、选择以及常用的列表聚合。

  1. AOP和Instrumentation

    Spring-aop模块:提供了一个符合AOP要求的面向切面的编程实现,允许定义方法拦截器和切入点,将代码按照功能进行分离,以便干净地解耦。
    Spring-aspects模块:提供了与AspectJ的集成功能,AspectJ是一个功能强大且成熟的AOP框架。
    Spring-instrument模块:提供了类植入(Instrumentation)支持和类加载器的实现,可以在特定的应用服务器中使用。

  2. 消息

Spring4.0以后新增了消息(Spring-messaging)模块,该模块提供了对消息传递体系结构和协议的支持。

  1. 数据访问/集成

数据访问/集成层由JDBC、ORM、OXM、JMS和事务模块组成。

Spring-jdbc模块:提供了一个JDBC的抽象层,消除了烦琐的JDBC编码和数据库厂商特有的错误代码解析。
Spring-orm模块:为流行的对象关系映射(Object-Relational Mapping)API提供集成层,包括JPA和Hibernate。使用Spring-orm模块可以将这些O/R映射框架与Spring提供的所有其他功能结合使用,例如声明式事务管理功能。
Spring-oxm模块:提供了一个支持对象/XML映射的抽象层实现,例如JAXB、Castor、JiBX和XStream。
Spring-jms模块(Java Messaging Service):指Java消息传递服务,包含用于生产和使用消息的功能。自Spring4.1以后,提供了与Spring-messaging模块的集成。
Spring-tx模块(事务模块):支持用于实现特殊接口和所有POJO(普通Java对象)类的编程和声明式事务管理。

  1. Web

Web层由Spring-web、Spring-webmvc、Spring-websocket和Portlet模块组成。

Spring-web模块:提供了基本的Web开发集成功能,例如多文件上传功能、使用Servlet监听器初始化一个IOC容器以及Web应用上下文。
Spring-webmvc模块:也称为Web-Servlet模块,包含用于web应用程序的Spring MVC和REST Web Services实现。Spring MVC框架提供了领域模型代码和Web表单之间的清晰分离,并与Spring Framework的所有其他功能集成。
Spring-websocket模块:Spring4.0以后新增的模块,它提供了WebSocket和SocketJS的实现。
Portlet模块:类似于Servlet模块的功能,提供了Portlet环境下的MVC实现。

  1. 测试

Spring-test模块支持使用JUnit或TestNG对Spring组件进行单元测试和集成测试。

1.2 Spring 开发环境

1.2.1 环境准备

  1. JDK
  2. Tomcat
    这里自行下载安装

1.2.2 创建 Spring 工程

  1. 可以创建maven项目,然后在线导入 Spring 的 jar 包。 在这里插入图片描述
    在这里插入图片描述前提是已安装配置好maven。

  2. 可以使用Idea直接创建Spring项目,这里的jar包自动下载好了。
    在这里插入图片描述
    在这里插入图片描述

1.3 使用IDEA开发 Spring 入门程序

  1. 使用IDEA创建 Spring 工厂
    在这里插入图片描述
  2. 创建接口TestDao
    Spring 解决的是业务逻辑层和其他层的耦合问题,因此它将面向接口的编程思想贯穿整个系统应用。
    在 src 目录下创建demo1包,并创建接口 TestDao,在定义一个方法 sayHello方法,代码如下:
package demo1;

public interface TestDao {
   
    public void sayHello();
}

  1. 创建接口的实现类 TestDaoImpl
    在 demo1 包下创建 实现类 TestDaoImpl,代码如下:
package demo1;

public class TestDaoImpl implements TestDao {
   

    @Override
    public void sayHello() {
   
        System.out.println("Hello,Spring");
    }
}

  1. 创建配置文件 applicationContext.xml
    在 src 目录下创建 Spring 的配置文件 applicationContext.xml,并在该文件使用实现类 TestDaoImpl 创建一个 id 为 testDaoImpl 的Bean,代码如下:
<?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.xsd">

<bean id="testDaoImpl" class="demo1.TestDaoImpl"/>

</beans>

配置文件的名称可以自定义,配置文件信息不需要我们手写,可直接在 Spring 帮助文档复制。

  1. 创建测试类
    在 src 目录下创建一个 Test 的包代码如下:
package demo1;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Test {
   
    public static void main(String[] args) {
   
        ApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        TestDaoImpl testDaoImpl = (TestDaoImpl) classPathXmlApplicationContext.getBean("testDaoImpl");
        testDaoImpl.sayHello();
    }
}

输出结果:
在这里插入图片描述
在上述main方法并没有使用new运算符创建TestDaoImpl实例,而是通过 Spring 容器获取实现类的对象,这就是 SpringIoC 的工作机制。

2 Spring IoC

2.1 Spring IoC 的基本概念

控制反转(Inversion of Control,IoC)是一个比较抽象的概念,是Spring框架的核心,用来消除计算机程序的耦合问题。依赖注入(Dependency Injection,DI)是 IoC 的另外一个说法,只是从不同的角度描述相同的概念。下面通过实际生活中的一个例子来解释 IoC 和 DI 。
当人们需要一件东西时,第一反应就是找东西,例如吃面包。在没有面包店和有面包店两种情况下,您会怎么做?在没有面包店时,最直观的做法可能是您按照自己的口味制作面包,也就是一个面包需要主动制作。然而时至今日,各种网点、实体店盛行,已经没有必要自己制作面包。想吃面包了,去网店或实体店把自己的口味告诉店家,一会就可以吃到面包了。注意,您并没有制作面包,而是由店家制作,但是完全符合您的胃口。
上面只是列举一个非常简单的例子,但包含了控制反转的思想,即把制作面包的主动权交给店家。下面通过面向对象编程思想继续探讨这两个概念。
当某个Java对象(调用者,例如您)需要调用另一个Java对象(被调用者,即被依赖对象,例如面包)时,在传统编程模式下,调用者通常会采用“new被调用者”的代码方式来创建对象(例如您自己制作面包)。这种方式会增加调用者与被调用者之间的耦合性,不利于后期代码的升级与维护。
当Spring框架出现后,对象的实例不再由调用者来创建,而是由Spring容器(例如面包店)来创建。Spring容器会负责控制程序之间的关系(例如面包店负责控制您与面包的关系),而不是由调用者的程序代码直接控制。这样,控制权由调用者转移到Spring 容器,控制权发生了反转,这就是Spring的控制反转。
从Spring容器角度来看,Spring 容器负责将被依赖对象赋值给调用者的成员变量,相当于为调用者注入它所依赖的实例,这就是Spring的依赖注入。
综上所述,控制反转是一种通过描述(在Spring中可以是XML或注解)并通过第三方去产生或获取特定对象的方式。在Spring 中实现控制反转的是IoC容器,其实现方法是依赖注入。

2.2 Spring IoC 容器

实现控制反转的时 Spring IoC 容器。Spring IoC 容器的设计主要基于BeanFactory 和 ApplicationContext 两个接口。

2.2.1 BeanFactory

BeanFactory由org.springframework. beans.factory.BeanFactory接口定义,它提供了完整的IoC服务支持,是一个管理Bean的工厂,主要负责初始化各种Bean。BeanFactory 接口有多个实现类,其中比较常用的是org.springframework .beans factory.xml.XmlBeanFactory,该类会根据XML配置文件中的定义来装配Bean(有关Bean的知识将在第3章讲解)。
在创建BeanFactory实例时需要提供XML文件的绝对路径。例如可以将第1章chl应用中main 方法的代码修改如下:

package demo1;

import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.core.io.FileSystemResource;

public class Test {
   
    public static void main(String[] args) {
   
//        ApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
//        TestDaoImpl testDaoImpl = (TestDaoImpl) classPathXmlApplicationContext.getBean("testDaoImpl");
//        testDaoImpl.sayHello();
        BeanFactory beanFactory = new XmlBeanFactory(new FileSystemResource("applicationContext.xml的绝对路径"));
        TestDaoImpl testDaoImpl = (TestDaoImpl) beanFactory.getBean("testDaoImpl");
        testDaoImpl.sayHello();
    }
}

使用BeanFactory实例加载配置文件在实际开发并不多见,我们只需要了解即可。

2.2.2 ApplicationContext

ApplicationContext是 BeanFactory 的子接口,也称应用上下文,由org.springframework.context.ApplicationContext接口定义。ApplicationContext接口包含 BeanFactory 的所有功能外,还添加了对国际化、资源访问、事件传播等内容的支持。
创建ApplicationContext接口实例通常有以下三种方法:

  1. 通过ClassPathXmlApplicationContext 创建

ClassPathXmlApplicationContext 将从类路径目录(src根目录)中寻找指定的XML配置文件。
在这里插入图片描述
测试代码:

package demo1;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Test {
   
    public static void main(String[] args) {
   
        ApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        TestDaoImpl testDaoImpl = (TestDaoImpl) classPathXmlApplicationContext.getBean("testDaoImpl");
        testDaoImpl.sayHello();
    }
}

这里用的是第一章的配置文件和TestDao,TestDaoImpl。

  1. 通过FileSystemXmlApplicationContext创建

FileSystemXmlApplicationContext将从配置文件的绝对路径中寻找XML配置文件,找到并装载完成 ApplicationContext 的实例化工作。

package demo1;
import org.springframework.context.support.FileSystemXmlApplicationContext;


public class Test {
   
    public static void main(String[] args) {
   
        FileSystemXmlApplicationContext fileSystemXmlApplicationContext = new FileSystemXmlApplicationContext("ApplicationContext.xml文件的绝对路径");
        TestDaoImpl testDaoImpl = (TestDaoImpl) fileSystemXmlApplicationContext.getBean("testDaoImpl");
        testDaoImpl.sayHello();
    }
}

采用绝对路径的加载方式将导致程序的灵活性变差,一般不推荐使用。因此,通常在 Spring 的 java 应用中采取通过 ClassPathXmlApplicationContext 类来实例化 ApplicationContext 容器的实例化工作将交给Web服务器完成。

  1. 通过Web服务器实例化ApplicationContext 容器

在Web服务器实例化ApplicationContext 容器时,一般使用基于org.springframework.web.context.ContextLoaderListener 的实现方式(需要将spring-web-5.0.2.RELEASE.jar复制到WEB-INF/lib目录中),此方法只需要在web.xml中添加以下代码:

<context-param>
	<!-- 加载src目录下的 applicationContext.xml文件-->
	<param-name>contextConfigLocation</param-name>
	<param-value>
		classpath:applicationContext.xml
	</param-value>
</context-param>

<!-- 指定以 ContextLoaderListener 方式启动 Spring 容器 -->
<listener>
	<listener-class>
		org.springframework.web.context.ContextLoaderListener
	</listener-class>
</listener>

2.3 依赖注入的类型

在 Spring 中实现 IoC 容器的方法是依赖注入,依赖注入的作用是在使用 Spring 框架创建对象时动态地将其所依赖的对象(例如属性值)注入 Bean 组件中。Spring 框架的依赖注入通常有两种实现方法,一种是使用构造方法注入,另一种是使用属性的 setter 方法注入。

2.3.1 使用构造方法注入

Spring 框架可以采用java的反射机制,通过构造方法完成依赖注入。下面开始代码演示:
在这里插入图片描述我们在demo2中演示。

目的:在service 中使用构造方法依赖注入 TestDIDao 接口对象。

  1. 创建 dao 包
    TestDIDao 接口代码如下:
package demo2.dao;

public interface TestDIDao {
   
    public void sayHello();
}

TestDIDaoImpl 实现类的代码如下:

package demo2.dao;

public class TestDIDaoImpl  implements TestDIDao{
   
    @Override
    public void sayHello() {
   
        System.out.println("TestDIDao say: hello,Spring!!");
    }
}

  1. 创建 service 包
    TestDIService 接口代码如下:
package demo2.service;

public interface TestDIService {
   
    public void sayHello();
}

TestDIServiceImpl 实现类的代码如下:

package demo2.service;

import demo2.dao.TestDIDao;

public class TestDIServiceImpl implements TestDIService {
   
    private TestDIDao testDIDao;
	
	// 构造方法,用于实现依赖注入接口testDIDao
    public TestDIServiceImpl(TestDIDao testDIDao){
   
        super();
        this.testDIDao = testDIDao;
    }

    @Override
    public void sayHello() {
   
        testDIDao.sayHello();
        System.out.println("TestDIService 构造方法注入say:,hello Spring");
    }
}

  1. 编写配置文件
    在demo2包下创建applicationContext.xml文件。在配置文件中首先将TestDIDaoImpl 类托管给 Spring,让Spring 创建其对象,然后service.TestDIServiceImpl 类托管给 Spring,让 Spring 创建其对象,同时给构造方法传递实参。配置文件具体代码如下:
<?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.xsd">

    <bean id="testDIDaoImpl" class="demo2.dao.TestDIDaoImpl"/>

    <bean id="testServiceImpl" class="demo2.service.TestDIServiceImpl">
    	// index = 0 表示 第一个参数为 引用的 testDIDaoImpl
        <constructor-arg index="0" ref="testDIDaoImpl"/>
    </bean>

</beans>

在配置文件中,constructor-arg 元素用于定义构造方法的参数,index 用于定义参数的位置,ref 指定某个实例的引用,如果参数时常量值,ref由value代替。

  1. 创建 Test 类
package demo2;

import demo2.service.TestDIService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Test {
   
    public static void main(String[] args) {
   
        ApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("demo2/applicationContext.xml");
        TestDIService testServiceImpl = (TestDIService) classPathXmlApplicationContext.getBean("testServiceImpl");
        testServiceImpl.sayHello();
    }
}

  • 8
    点赞
  • 60
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值