spring学习
1,spring
Spring中国教育管理中心
Spring认证概述
Spring认证框架是一个开放源代码的J2EE应用程序框架,由Rod Johnson发起,是针对bean的生命周期进行管理的轻量级容器(lightweight container)。 [1] Spring是Java EE编程领域的一个轻量级开源框架,该框架由一个叫Rod Johnson的程序员在 2002 年最早提出并随后创建,是为了解决企业级编程开发中的复杂性,实现敏捷开发的应用型框架 。 [2]
教育中心概述
2021年2月,VMware公司授权北京中科卓望网络科技有限公司正式成为VMware Tunzu Spring中国教育管理中心,负责Spring国际认证体系标准在中国教育行业的推广工作。 [3]
Spring框架是由于[软件开发](https://baike.baidu.com/item/软件开发/3448966)的复杂性而创建的。Spring使用的是基本的JavaBean来完成以前只可能由[EJB](https://baike.baidu.com/item/EJB/144195)完成的事情。然而,Spring的用途不仅仅限于服务器端的开发。从简单性、可测试性和松耦合性角度而言,绝大部分Java应用都可以从Spring中受益。
Spring的形成,最初来自Rod Jahnson所著的一本很有影响力的书籍《Expert One-on-One J2EE Design and Development》,就是在这本书中第一次出现了Spring的一些核心思想,该书出版于2002年。另外一本书《Expert One-on-One J2EE Development without EJB》,更进一步阐述了在不使用EJB开发JAVA EE企业级应用的一些设计思想和具体的做法。
Spring的初衷:
1、JAVA EE开发应该更加简单。
2、使用接口而不是使用类,是更好的编程习惯。Spring将使用接口的复杂度几乎降低到了零。
3、为JavaBean提供了一个更好的应用配置框架。
4、更多地强调[面向对象](https://baike.baidu.com/item/面向对象)的设计,而不是现行的技术如JAVA EE。
5、尽量减少不必要的异常捕捉。
6、使应用程序更加容易测试。
Spring的目标:
1、可以令人方便愉快的使用Spring。
2、应用程序代码并不依赖于Spring APIs。
3、Spring不和现有的解决方案竞争,而是致力于将它们融合在一起。
Spring的基本组成:
1、最完善的轻量级核心框架。
2、通用的事务管理抽象层。
3、JDBC抽象层。
4、集成了Toplink, Hibernate, JDO, and iBATIS SQL Maps。
5、AOP功能。
6、灵活的MVC Web应用框架。
优点
◆JAVA EE应该更加容易使用。
◆面向对象的设计比任何实现技术(比如JAVA EE)都重要。
◆[面向接口编程](https://baike.baidu.com/item/面向接口编程/6025286),而不是针对类编程。Spring将使用接口的复杂度降低到零。(面向接口编程有哪些复杂度?)
◆代码应该易于测试。Spring框架会帮助你,使代码的测试更加简单。
◆JavaBean提供了应用程序配置的最好方法。
◆在Java中,已检查异常(Checked exception)被过度使用。框架不应该迫使你捕获不能恢复的异常。
简介
2002年:首次推出了Spring框架的雏形:interface 21 框架
Spring:
Spring是一个开源框架,它由[Rod Johnson](https://baike.baidu.com/item/Rod Johnson)创建。它是为了解决企业应用开发的复杂性而创建的。Spring使用基本的JavaBean来完成以前只可能由EJB完成的事情。然而,Spring的用途不仅限于服务器端的开发。从简单性、可测试性和松耦合的角度而言,任何Java应用都可以从Spring中受益。
Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架。
轻量——从大小与开销两方面而言Spring都是轻量的。完整的Spring框架可以在一个大小只有1MB多的JAR文件里发布。并且Spring所需的处理开销也是微不足道的。此外,Spring是非侵入式的:典型地,Spring应用中的对象不依赖于Spring的特定类。
控制反转——Spring通过一种称作控制反转(IoC)的技术促进了松耦合。当应用了IoC,一个对象依赖的其它对象会通过被动的方式传递进来,而不是这个对象自己创建或者查找依赖对象。你可以认为IoC与JNDI相反——不是对象从容器中查找依赖,而是容器在对象初始化时不等对象请求就主动将依赖传递给它。
面向切面——Spring提供了[面向切面编程](https://baike.baidu.com/item/面向切面编程)的丰富支持,允许通过分离应用的业务逻辑与系统级服务(例如审计(auditing)和事务(transaction)管理)进行内聚性的开发。应用对象只实现它们应该做的——完成业务逻辑——仅此而已。它们并不负责(甚至是意识)其它的系统级关注点,例如日志或事务支持。
容器——Spring包含并管理应用对象的配置和生命周期,在这个意义上它是一种容器,你可以配置你的每个bean如何被创建——基于一个可配置原型(prototype),你的bean可以创建一个单独的实例或者每次需要时都生成一个新的实例——以及它们是如何相互关联的。然而,Spring不应该被混同于传统的重量级的EJB容器,它们经常是庞大与笨重的,难以使用。
框架——Spring可以将简单的组件配置、组合成为复杂的应用。在Spring中,应用对象被声明式地组合,典型地是在一个XML文件里。Spring也提供了很多基础功能(事务管理、持久化框架集成等等),将应用逻辑的开发留给了你。
所有Spring的这些特征使你能够编写更干净、更可管理、并且更易于测试的代码。它们也为Spring中的各种模块提供了基础支持。
Spring框架由七个定义明确的模块组成(图1.1)。
(Spring框架概览图1.1)
如果作为一个整体,这些模块为你提供了开发企业应用所需的一切。但你不必将应用完全基于Spring框架。你可以自由地挑选适合你的应用的模块而忽略其余的模块。
就像你所看到的,所有的Spring模块都是在核心容器之上构建的。容器定义了Bean是如何创建、配置和管理的——更多的Spring细节。当你配置你的应用时,你会潜在地使用这些类。但是作为一名开发者,你最可能对影响容器所提供的服务的其它模块感兴趣。这些模块将会为你提供用于构建应用服务的框架,例如AOP和持久性。
核心容器
这是Spring框架最基础的部分,它提供了依赖注入(DependencyInjection)特征来实现容器对Bean的管理。这里最基本的概念是BeanFactory,它是任何Spring应用的核心。BeanFactory是工厂模式的一个实现,它使用IoC将应用配置和依赖说明从实际的应用代码中分离出来。
应用上下文(Context)模块
核心模块的BeanFactory使Spring成为一个容器,而上下文模块使它成为一个框架。这个模块扩展了BeanFactory的概念,增加了对国际化(I18N)消息、事件传播以及验证的支持。
另外,这个模块提供了许多企业服务,例如电子邮件、JNDI访问、EJB集成、远程以及时序调度(scheduling)服务。也包括了对模版框架例如Velocity和FreeMarker集成的支持。
Spring的AOP模块
Spring在它的AOP模块中提供了对面向切面编程的丰富支持。这个模块是在Spring应用中实现切面编程的基础。为了确保Spring与其它AOP框架的互用性,Spring的AOP支持基于AOP联盟定义的API。AOP联盟是一个开源项目,它的目标是通过定义一组共同的接口和组件来促进AOP的使用以及不同的AOP实现之间的互用性。通过访问他们的站点,你可以找到关于AOP联盟的更多内容。
Spring的AOP模块也将元数据编程引入了Spring。使用Spring的元数据支持,你可以为你的源代码增加注释,指示Spring在何处以及如何应用切面函数。
JDBC抽象和DAO模块
使用JDBC经常导致大量的重复代码,取得连接、创建语句、处理结果集,然后关闭连接。Spring的JDBC和DAO模块抽取了这些重复代码,因此你可以保持你的数据库访问代码干净简洁,并且可以防止因关闭数据库资源失败而引起的问题。
这个模块还在几种[数据库服务器](https://baike.baidu.com/item/数据库服务器/613818)给出的错误消息之上建立了一个有意义的异常层。使你不用再试图破译神秘的私有的SQL错误消息!
另外,这个模块还使用了Spring的AOP模块为Spring应用中的对象提供了事务管理服务。
对象/关系映射集成模块
对那些更喜欢使用对象/关系映射工具而不是直接使用JDBC的人,Spring提供了ORM模块。Spring并不试图实现它自己的ORM解决方案,而是为几种流行的[ORM框架](https://baike.baidu.com/item/ORM框架/15541111)提供了集成方案,包括Hibernate、JDO和iBATIS SQL映射。Spring的事务管理支持这些ORM框架中的每一个也包括JDBC。
Spring的Web模块
Web上下文模块建立于应用上下文模块之上,提供了一个适合于Web应用的上下文。另外,这个模块还提供了一些面向服务支持。例如:实现文件上传的multipart请求,它也提供了Spring和其它Web框架的集成,比如Struts、WebWork。
Spring的**MVC框架**
Spring为构建Web应用提供了一个功能全面的MVC框架。虽然Spring可以很容易地与其它MVC框架集成,例如Struts,但Spring的MVC框架使用IoC对控制逻辑和业务对象提供了完全的分离。
它也允许你声明性地将请求参数绑定到你的业务对象中,此外,Spring的MVC框架还可以利用Spring的任何其它服务,例如国际化信息与验证。
Spring框架Web页面乱码问题
在做java Web 项目时,乱码问题时常都会出现,解决方法也不尽相同,有简单也有复杂的;如果加入了Spring框架之后就不一样了,可以采用Spring框架自带的过滤器CharacterEncodingFilter,这样可以大大减轻了我们的工作量,即简单方便又容易理解,配置方式如下:在web.xml文件中filter的位置加上如下内容:
encodingFilter
org.springframework.web.filter.CharacterEncodingFilter
encoding
UTF-8
forceEncoding
true
encodingFilter
*
SSH: struct2 + spring + hibernate
SSM: springMVC + spring +Mybatis
官网: https://spring.io/projects/spring-framework
官方下载地址: http://repo.spring.io/release/org/springframework/spring
**GitHub地址:**https://github.com/spring-projects/spring-framework
Maven 依赖
org.springframework
spring-webmvc
5.3.4
org.springframework
spring-jdbc
5.3.4
1.2、优点
- Spring是开源免费的框架(容器)
- Spring是一个轻量级、非入侵式的框架
- 核心是 控制反转(IOC),面向切面编程(AOP)
- 支持事务处理,对框架的整合的支持!
总结:Spring就是一个轻量级的控制反转(IOC),**面向切面编程(AOP)**的框架!
Spring的官网介绍:现代化Java开发
-
Spring Boot
-
一个快速开发的脚手架
-
基于SpringBoot可以快速的开发单个微服务
-
约定大于配置
-
-
Spring Cloud
- SpringCloud 是基于SpringBoot实现的。
大多数公司都在使用Spring Boot进行快速开发
学习SpringBoot的前提,需要为完全掌握Spring及其SpringMVC
唯一弊端缺点:发展太久,配置十分繁琐,人称 “配置地狱”
2,IOC理论推导
传统的设计模式:
-
实体类接口 UserDao 接口
-
实体类接口实现类 UserDaoImpl 类
-
业务层实现接口 UserServive 接口
-
业务层实现类 UserServiceImpl 类
package com.hjf.dao;
public interface UserDao {
void getuser();
}
package com.hjf.dao;
public class UserDaoImpl implements UserDao{
public void getuser() {
System.out.println("默认获取用户数据");
}
}
package com.hjf.service;
public interface UserService {
void getuser();
}
package com.hjf.service;
import com.hjf.dao.UserDao;
import com.hjf.dao.UserDaoImpl;
import com.hjf.dao.UserDaoMysolImpl;
public class UserServiceImpl implements UserService{
private UserDao userDao = new UserDaoMysolImpl();
public void getuser() {
userDao.getuser();
}
}
import com.hjf.dao.UserDaoImpl;
import com.hjf.service.UserServiceImpl;
public class MyTest {
public static void main(String[] args) {
// 用户实际调用的是业务层,dao层他们不需要接触!
UserServiceImpl userService = new UserServiceImpl();
userService.getuser();
}
}
问题提出
- 当实体类接口的实现类增加时
- 用户想要修改调用新的实体类接口时,就不得不修改
UserServiceImpl
实现类的代码。
package com.hjf.dao;
//新增的dao层实体类
public class UserDaoMysolImpl implements UserDao{
public void getuser() {
System.out.println("Mysql获取用户数据!");
}
}
package com.hjf.service;
import com.hjf.dao.UserDao;
import com.hjf.dao.UserDaoImpl;
import com.hjf.dao.UserDaoMysolImpl;
public class UserServiceImpl implements UserService{
//修改需要新实现的接口,如果接口过多,且用户需要过多,会大量增加程序员的负担
private UserDao userDao = new UserDaoMysolImpl();
public void getuser() {
userDao.getuser();
}
}
问题解决
- 在
UserServiceImpl
实现类中使用set
注入来解决,重复修改代码的方法 - 将在
UserServiceImpl
业务层,需要什么接口的实现类,就可以调用什么接口的实现类
package com.hjf.service;
import com.hjf.dao.UserDao;
import com.hjf.dao.UserDaoImpl;
import com.hjf.dao.UserDaoMysolImpl;
public class UserServiceImpl implements UserService{
//修改需要新实现的接口,如果接口过多,且用户需要过多,会大量增加程序员的负担
// 解决方法:新增一个setter方法,将选择权交给客户,让用户选择实现类
//核心思想,将类设计成变量,利用 set 注入,就可以减少程序员的工作量这就是 IOC理论 控制反转
private UserDao userDao;
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
public void getuser() {
userDao.getuser();
}
}
import com.hjf.dao.UserDaoImpl;
import com.hjf.dao.UserDaoMysolImpl;
import com.hjf.service.UserServiceImpl;
public class MyTest {
public static void main(String[] args) {
// 用户实际调用的是业务层,dao层他们不需要接触!
UserServiceImpl userService = new UserServiceImpl();
userService.setUserDao(new UserDaoImpl());
userService.getuser();
}
}
- 之前,程序是主动创建对象,控制权在程序员手上
- 使用
set
注入后,程序不再具有主动性,而是变成了被动接受对象!
IOC
思想,从本质上解决了问题,程序员不用再去管理对象,系统耦合度大大降低。这就是 IOC
原型
控制反转IoC(Inversion of Control),是一种设计思想,DI(依赖注入)是实现IoC的一种方法,
IoC是Spring框架的核心内容,使用多种方式完美的实现了IoC,可以使用XML配置,也可以使用注解,新版本的Spring也可以零配置实现IoC。
Spring容器在初始化时先读取配置文件,根据配置文件或元数据创建与组织对象存入容器中,程序使用时再从Ioc容器中取出需要的对象。
采用XML方式配置Bean的时候,Bean的定义信息是和实现分离的,而采用注解的方式可以把两者合为一体,Bean的定义信息直接以注解的形式定义在实现类中,从而达到了零配置的目的。
控制反转是一种通过描述(XML或注解)并通过第三方去生产或获取特定对象的方式。在Spring中实现控制反转的是IoC容器,其实现方法是依赖注入(Dependency Injection,DI)。
3,第一个Spring
1、Hello Spring
-
导入依赖
-
创建实体类
核心是用
set
注入,实体类必须要有set
方法 -
编写类的配置文件
-
测试
package com.hjf.pojo;
//实体类
public class Hello {
private String str ;
public String getStr() {
return str;
}
public void setStr(String str) {
this.str = str;
}
@Override
public String toString() {
return "Hello{" +
"str='" + str + '\'' +
'}';
}
}
创建beans.xml文件
<?xml version="1.0" encoding="UTF-8"?>
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">
测试类
import com.hjf.pojo.Hello;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MyTest {
public static void main(String[] args) {
// 获取spring的上下文对象
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
// 我们的对象现在都在spring中管理了,我们要使用,直接去里面取出来就可以
Hello hello = (Hello) context.getBean("hello");
System.out.println(hello.toString());
}
}
IOC理论推导用另一个方法xml配置写
编写xml 文件
<?xml version="1.0" encoding="UTF-8"?>
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">
编写测试类MyTest
//import com.hjf.dao.UserDaoImpl;
//
//import com.hjf.service.UserServiceImpl;
import com.hjf.service.UserServiceImpl;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MyTest {
public static void main(String[] args) {
// 第一种获取数据的方法
// 用户实际调用的是业务层,dao层他们不需要接触!
// UserServiceImpl userService = new UserServiceImpl();
// userService.setUserDao(new UserDaoImpl()
// );
// userService.getuser();
// 第二种获取数据的方法
// 获取ApplicationContext;拿到spring的容器
// 获取操作类的 容器(框架)
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
// 容器在手,天下我有,需要什么,直接get什么!
// 获取要操作的类的 变量
UserServiceImpl userServiceImpl = (UserServiceImpl) context.getBean("UserServiceImpl");
// 执行方法
userServiceImpl.getuser();
}
}
到了现在,我们彻底不用再程序中去改动了,要实现不同的操作,只需要在xmI配置文件中进行修改,所谓的IpC,-句话搞定:对象由Spring来创建,管理,装配!
4,IOC创建对象方式
1、Spring 无参构造
Spring
构建时,默认走无参构造.- 当无参构造被有参构造,消除时,有 3 种(有参构造方式)注入方式,进行配置 类的加载文件
beans.xml
2、Spring 有参构造
-
下标构造注入
? 2.类型匹配注入
3.属性名注入(推荐使用)
总结:在配置文件加载的时候,容器bean中管理的对象就已经初始化了
5,spring配置
1、别名
2、Bean 配置
3、import
一般它用于团队开发,他可以将多个配置文件合并为一个 内容相同会自动优化
<?xml version="1.0" encoding="UTF-8"?>
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、构造器注入(上面已经写了)
2、Set注入【重点】
- 依赖注入:Set注入!
- **Dependency **依赖:bean对象的创建依赖于容器
- Injection注入:bean对象中的所有属性,由容器来注入
【环境搭建】
-
复杂类型
public class Address { private String address; public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } }
-
真实测试对象
public class Student { private String name; private Address address; private String[] books; private List
hobbys; private Map card; private Set games; private String wife; private Properties info; }
3.beans.xml
<?xml version="1.0" encoding="UTF-8"?>
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.测试类
public class MyTest {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
Student student = (Student) context.getBean("student");
System.out.println(student.getAddress());
}
}
5.不同对象类型注入方式
红楼梦
三国演义
水浒传
西游记
唱歌
看到电视
听歌
lol
bob
coc
12334
男
大法官
对应的测试及结果
public class MyTest {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
Student student = (Student) context.getBean("student");
System.out.println(student.toString());
}
/* Student{
name='雪女',
address=Address{address='华夏'},
books=[红楼梦, 三国演义, 水浒传, 西游记],
hobbys=[唱歌, 看到电视, 听歌],
card={
身份证=333223323233242343,
银行卡=242454656565656565},
games=[lol, bob, coc],
wife='null',
info={
性别=男,
driver=12334,
姓名=大法官}
}*/
}
3,扩展方式注入
即 p 命名空间和 c 命名空间进行注入
官方解释
实现
注意记得写 xmlns:p="http://www.springframework.org/schema/p"
xmlns:c="http://www.springframework.org/schema/c"
<?xml version="1.0" encoding="UTF-8"?>
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:c="http://www.springframework.org/schema/c"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd">
测试
@Test
public void test2(){
ApplicationContext context = new ClassPathXmlApplicationContext("Userbeans.xml");
User user = (User) context.getBean("user4");
/* User user = context.getBean("user2", User.class);*/
System.out.println(user);
xmlns:p="http://www.springframework.org/schema/p"
xmlns:c="http://www.springframework.org/schema/c"
测试时要导入junit依赖
junit
junit
4.13
4,Bean的作用域
官方文档
1,单列模式The Singleton Scope(Spring 默认机制)初始new 一次,后面都不new 快速 线程不安全 对象一样,是同一个,单线程使用
2,原型模式The Prototype Scope:每次从容器getBean的时候,都会产生一个new对象 ,new浪费资源,但线程安全,多线程使用
3,其余request,application,websocket,session 这些只会在web开发中使用
7,bean的自动装配
-
自动装配是
Spring
满足Bean
依赖的一种方式! -
Spring
会在上下文中寻找,并给Bean
自动装配属性!在
Spring
中的三种装配的方式
- 在
xml
中显示的装配 - 在
Java
中显示装配 - 隐式的自动装配
Bean
【重点】
1,测试
环境搭建:一个人两个宠物
package com.hjf.pojo;
public class Cat {
public void shout(){
System.out.println("miao~");
}
}
package com.hjf.pojo;
public class Dog {
public void shout(){
System.out.println("wang~");
}
}
package com.hjf.pojo;
public class People {
private Cat cat;
private Dog dog;
private String name;
@Override
public String toString() {
return "People{" +
"cat=" + cat +
", dog=" + dog +
", name='" + name + '\'' +
'}';
}
public Cat getCat() {
return cat;
}
public void setCat(Cat cat) {
this.cat = cat;
}
public Dog getDog() {
return dog;
}
public void setDog(Dog dog) {
this.dog = dog;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
<?xml version="1.0" encoding="UTF-8"?>
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">
环境测试
import com.hjf.pojo.People;
import org.junit.jupiter.api.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MyTest {
@Test
public void test1(){
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
People people = context.getBean("people", People.class);
people.getCat().shout();
people.getDog().shout();
}
}
2,byName自动装配
3,byType自动装配
小结:byname的时候,需要保证所有bean的id唯一,并且这个bean的 id 需要和自动注入的属性的set方法的值一致!
bytype的时候,需要保证所有bean的class唯一,并且这个bean需要和自动注入的属性的类型一致!
4,使用注解实现自动装配
jdk1.5支持的注解,spring2.5就支持了!
The introduction of annotation-based configuration raised the question of whether this approach is “better” than XML
使用注解须知:
? 1.导入约束:context约束
? **xmlns:context="http://www.springframework.org/schema/context" **
? 2.配置注解的支持:https://baike.baidu.com/item/面向切面编程/6016335),通过[预编译](https://baike.baidu.com/item/预编译/3191547)方式和运行期间动态代理实现程序功能的统一维护的一种技术。AOP是[OOP](https://baike.baidu.com/item/OOP)的延续,是软件开发中的一个热点,也是[Spring](https://baike.baidu.com/item/Spring)框架中的一个重要内容,是[函数式编程](https://baike.baidu.com/item/函数式编程/4035031)的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的[耦合度](https://baike.baidu.com/item/耦合度/2603938)降低,提高程序的可重用性,同时提高了开发的效率。
11.2 AOP在Spring中的作用
提供声明式事务;允许用户自定义切面
- 横切关注点:跨越应用程序多个模块的方法或功能。即是,与我们业务逻辑无关的,但是我们需要关注的部分,就是横切关注点。如日志,安全,缓存,事务等等…
- 切面(ASPECT):横切关注点被模块化的特殊对象。即,它是一个类。
- 通知(Advice):切面必须要完成的工作。即,它是类中的一个方法。
- 目标(Target):被通知对象。
- 代理(Proxy):向目标对象应用通知之后创建的对象。
- 切入点(PointCut):切面通知执行的“地点”的定义。
- 连接点(JointPoint):与切入点匹配的执行点。
SpringAOP中,通过Advice定义横切逻辑,Spring中支持5种类型的Advice:
即AOP在不改变原有代码的情况下,去增加新的功能。
11.3、使用Spring实现Aop
【重点】使用AOP织入,需要导入依赖包
org.aspectj
aspectjweaver
1.9.7
方式一: 使用Spring的API接口【主要是SpringAPI接口实现】
- 在service包下,定义UserService业务接口和UserServiceImpl实现类
package com.hjf.service;
public interface UserService {
public void add();
public void delete();
public void update();
public void query();
}
package com.hjf.service;
public class UserServiceImpl implements UserService{
@Override
public void add() {
System.out.println("增");
}
@Override
public void delete() {
System.out.println("删");
}
@Override
public void update() {
System.out.println("改");
}
@Override
public void query() {
System.out.println("查");
}
}
- 在log包下,定义我们的增强类,一个Log前置增强和一个AfterLog后置增强类
package com.hjf.log;
import org.springframework.aop.AfterReturningAdvice;
import java.lang.reflect.Method;
public class AfterLog implements AfterReturningAdvice {
@Override
// returnValue:返回值
public void afterReturning(Object returnValue, Method method, Object[] objects, Object o1) throws Throwable {
System.out.println("执行了"+method.getName()+"方法,返回结果为:"+returnValue);
}
}
package com.hjf.log;
import org.springframework.aop.MethodBeforeAdvice;
import java.lang.reflect.Method;
public class Log implements MethodBeforeAdvice {
// method:要执行的目标对象的方法
// args:参数
// target:目标对象
@Override
public void before(Method method, Object[] args, Object target) throws Throwable {
System.out.println(target.getClass().getName()+"的"+method.getName()+"被执行了");
}
}
- 最后去spring的文件中注册 , 并实现aop切入实现 , 注意导入约束,配置applicationContext.xml文件
<?xml version="1.0" encoding="UTF-8"?>
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd">
测试
import com.hjf.service.UserService;
import com.hjf.service.UserServiceImpl;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MyText {
public static void main(String[] args) {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
// 动态代理代理的是接口
UserService userService = context.getBean("userService", UserService.class);
userService.add();
}
}
方式二:使用自定义类来实现【主要是切面定义】
- 在diy包下定义自己的DiyPointCut切入类
package com.hjf.diy;
public class DiyPiontCut {
public void before(){
System.out.println("==方法执行前===");
}
public void after(){
System.out.println("==方法执行后===");
}
}
- 去spring中配置文件
- 测试:和前面一样
方式三:注解实现Aop
- 在diy包下定义注解实现的AnnotationPointCut增强类
//方式三:使用注解方式实现Aop
@Aspect //标注类是切面
public class AnnotationPointCut {
@Before("execution(* com.hjf.service.UserServiceImpl.*(..))")
public void before(){
System.out.println("方法执行前");
}
@After("execution(* com.hjf.service.UserServiceImpl.*(..))")
public void after(){
System.out.println("方法执行后");
}
@Around("execution(* com.hjf.service.UserServiceImpl.*(..))")
public void around(ProceedingJoinPoint jp) throws Throwable {
System.out.println("环绕前");
Object proceed = jp.proceed(); //执行方法
System.out.println("环绕后");
}
}
- 在Spring配置文件中,注册bean,并增加支持注解的配置。
- 测试,和上面一样,不需要改变
12.整合Mybatis
步骤:
- 导入相关jar包
- Junit
- mybatis
- mysql数据库
- spring相关的
- aop织入
- mybatis-spring【new】
junit
junit
4.13
mysql
mysql-connector-java
8.0.26
org.mybatis
mybatis
3.5.7
org.springframework
spring-webmvc
5.3.10
org.springframework
spring-jdbc
5.3.10
org.aspectj
aspectjweaver
1.9.7
org.mybatis
mybatis-spring
2.0.6
编写配置文件
测试
12.1回顾mybatis
- 编写实体类
public class User {
private int id;
private String name;
private String pwd;
- 编写核心配置文件
<?xml version="1.0" encoding="UTF-8" ?>
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
- 编写接口
public interface UserMapper {
public List selectUser();
}
- 编写mapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
- 测试
@Test
public void test() throws Exception {
String resource = "mybatis-config.xml";
InputStream in = Resources.getResourceAsStream(resource);
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(in);
SqlSession sqlSession = sessionFactory.openSession(true);
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
List userList = mapper.selectUser();
for (User user : userList) {
System.out.println(user);
}
}
12.2Mybatis-spring(两种方式)
方式一:
-
编写数据源配置
-
sqlSessionFactory
- sqlSessionTemplate
- 给接口加实现类
public class UserMapperImpl implements UserMapper{
//我们的所有操作,都使用sqlSession来执行,在原来,现在都使用SqlSessionTemplate;
private SqlSessionTemplate sqlSession;
public void setSqlSession(SqlSessionTemplate sqlSession) {
this.sqlSession = sqlSession;
}
@Override
public List selectUser() {
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
return mapper.selectUser();
}
}
- 将写的实现类,注入到spring中
- 测试
@Test
public void test(){
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
UserMapper userMapper = context.getBean("userMapper", UserMapper.class);
for (User user : userMapper.selectUser()) {
System.out.println(user);
}
}
方式二:
SqlSessionDaoSupport
package com.hjf.mapper;
import com.hjf.pojo.User;
import org.apache.ibatis.session.SqlSession;
import org.mybatis.spring.support.SqlSessionDaoSupport;
import java.util.List;
public class UserMapperImpl2 extends SqlSessionDaoSupport implements UserMapper{
@Override
public List selectUser() {
/* SqlSession sqlSession = getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
return mapper.selectUser();*/
return getSqlSession().getMapper(UserMapper.class).selectUser();
}
}
sqlSessionFactory
测试
@Test
public void test2(){
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
UserMapper userMapper = context.getBean("userMapper2", UserMapper.class);
for (User user : userMapper.selectUser()) {
System.out.println(user);
}
}
13、声明式事务
1、回顾事务
- 把一组业务当作一个业务来做;要么都成功,要么都失败
- 开发中涉及到数据一致性问题
- 确保完整性和一致性
事务ACID原则:
- 原子性([Atom](https://so.csdn.net/so/search?from=pc_blog_highlight&q=Atom)icity)
- 一致性(Consistency)
- 隔离性(Isolation)
- 多个业务可能操作同一个资源,防止数据破坏
- 持久性(Durability)
- 事务一旦提交,无论系统出现什么问题,之前操作后的数据不会被影响,被持久化的吓到存储器中
2、spring中的事务管理
- 声明式事务:AOP
- 编程式事务:需要在代码中,进行事务的管理
为什么需要事务?
- 如果不配置事务,可能存在数据提交不一致的情况下;
- 如果我们不在spring中去配置声明式事务,就需要在代码中手动配置事务
- 事务在项目的开发中十分重要,涉及到数据的一致性和完整性问题,不容马虎!