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的位置加上如下内容:
<filter>
<filter-name>encodingFilter</filter-name >
<filter-class>
org.springframework.web.filter.CharacterEncodingFilter
</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>*</url-pattern>
</filter-mapping>
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 依赖
<!--spring-webmvc 依赖-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.4</version>
</dependency>
<!-- spring-jdbc 依赖-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.3.4</version>
</dependency>
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"?>
<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">
<!-- 使用spring来创建对象,在spring中这些都称为Bean-->
<!-- 类型 变量名 = new 类型
Hello hello = new Hello()
id = 变量名
class = new 的对象
property 相当于给对象中的属性设置一个值-->
<bean id="hello" class="com.hjf.pojo.Hello">
<property name="str" value="Spring"/>
</bean>
</beans>
测试类
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"?>
<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="daoImpl" class="com.hjf.dao.UserDaoImpl"/>
<bean id="daoMysqlImpl" class="com.hjf.dao.UserDaoMysolImpl"/>
<bean id="daoOracalImpl" class="com.hjf.dao.UserDaoOrcalImpl"/>
<bean id="UserServiceImpl" class="com.hjf.service.UserServiceImpl">
<property name="userDao" ref="daoOracalImpl"/>
</bean>
<!-- ref: 应用spring容器中创建号的对象
value:具体的值,基本数据类型
UserDaoMysolImpl
UserDaoImpl
就相当于MyTest里边的
UserServiceImpl userService = new UserServiceImpl();
userService.setUserDao(new UserDaoImpl());
userService.getuser();
new UserDaoImpl()
需要用那个获取数据直接改
ref = "" 即可-->
</beans>
编写测试类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 有参构造
-
下标构造注入
<!--第一种,下标赋值--> <bean id="user" class="com.hjf.pojo.User"> <constructor-arg index="0" value="嘿嘿"/> </bean>
2.类型匹配注入
<!--第二种,通过类型创建,不建议使用。原因:多个同类型的情况 如多个String类型-->
<bean id="user" class="com.hjf.pojo.User">
<constructor-arg type="java.lang.String" value="哈哈"/>
</bean>
3.属性名注入(推荐使用)
<!--第三种,直接通过参数名来设置-->
<bean id="user" class="com.hjf.pojo.User">
<constructor-arg name="name" value="呵呵"/>
</bean>
总结:在配置文件加载的时候,容器bean中管理的对象就已经初始化了
5,spring配置
1、别名
<!-- 别名 :顾名思义,给对象名另起一个名字,一对一个-->
<alias name="user" alias="user2"/>
2、Bean 配置
<!-- id : bean 的唯一标识符,也就是我们学的对象名,ApplicationContext中得到的getBean("dd")的名字
class : bean对象所对应的全限定名:包名+类名
name : 也是别名,而且可以同时有多个-->
<bean id="user" class="com.hjf.pojo.User" name="user3,df dd;wef">
<property name="name" value="晓梦"/>
</bean>
3、import
一般它用于团队开发,他可以将多个配置文件合并为一个 内容相同会自动优化
<!--
一般项目时的所有人写的beans.xml都需要导入一个名叫 applicationContext.xml 的配置文件,
import 就是将其他人写的配置文件导入进来
-->
<?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">
<import resource="beans.xml"/>
<import resource="beans2.xml"/>
<import resource="beans3.xml"/>
</beans>
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<String> hobbys; private Map<String,String> card; private Set<String> games; private String wife; private Properties info; }
3.beans.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="student" class="com.hjf.pojo.Student">
<!-- 第一种,普通值注入,value-->
<property name="name" value="雪女"/>
</bean>
</beans>
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.不同对象类型注入方式
<bean id="address" class="com.hjf.pojo.Address">
<property name="address" value="华夏"/>
</bean>
<bean id="student" class="com.hjf.pojo.Student">
<!-- 第一种,普通值注入,value-->
<property name="name" value="雪女"/>
<!-- 第二种,Bean注入,ref-->
<property name="address" ref="address"/>
<!-- 数组-->
<property name="books">
<array>
<value>红楼梦</value>
<value>三国演义</value>
<value>水浒传</value>
<value>西游记</value>
</array>
</property>
<!-- list-->
<property name="hobbys">
<list>
<value>唱歌</value>
<value>看到电视</value>
<value>听歌</value>
</list>
</property>
<!-- map-->
<property name="card">
<map>
<entry key="身份证" value="333223323233242343"/>
<entry key="银行卡" value="242454656565656565"/>
</map>
</property>
<!-- set-->
<property name="games">
<set>
<value>lol</value>
<value>bob</value>
<value>coc</value>
</set>
</property>
<!-- null-->
<property name="wife">
<null/>
</property>
<!-- Properties-->
<property name="info">
<props>
<prop key="driver">12334</prop>
<prop key="性别">男</prop>
<prop key="姓名">大法官</prop>
</props>
</property>
</bean>
对应的测试及结果
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"?>
<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"
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">
<!--p命名空间注入,可以直接注入属性的值:property-->
<bean id="user" class="com.hjf.pojo.User" p:name="天明" p:age="15"/>
<!--c命名空间注入,通过构造器注入:constructor-arg 注:必须写其有参构造方法-->
<bean id="user4" class="com.hjf.pojo.User" c:name="高月" c:age="15"/>
</beans>
测试
@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依赖
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13</version>
</dependency>
4,Bean的作用域
官方文档

1,单列模式The Singleton Scope(Spring 默认机制)初始new 一次,后面都不new 快速 线程不安全 对象一样,是同一个,单线程使用
<bean id="user4" class="com.hjf.pojo.User" c:name="高月" c:age="15" scope="singleton"/>
2,原型模式The Prototype Scope:每次从容器getBean的时候,都会产生一个new对象 ,new浪费资源,但线程安全,多线程使用
<bean id="accountService" class="com.something.DefaultAccountService" scope="prototype"/>
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"?>
<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="cat" class="com.hjf.pojo.Cat"/>
<bean id="dog" class="com.hjf.pojo.Dog"/>
<bean id="people" class="com.hjf.pojo.People">
<property name="cat" ref="cat"/>
<property name="dog" ref="dog"/>
<property name="name" value="卫庄"/>
</bean>
</beans>
环境测试
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自动装配
<bean id="cat" class="com.hjf.pojo.Cat"/>
<bean id="dog" class="com.hjf.pojo.Dog"/>
<!--byName:会自动在容器上下文中查找,和自己对象set方法后面的值对应的beanid! 也就是需要写对应的setter方法,
且需要注册beanid 并且id需要相对应-->
<bean id="people" class="com.hjf.pojo.People" autowire="byName">
<property name="name" value="卫庄"/>
</bean>
3,byType自动装配
<bean class="com.hjf.pojo.Cat"/>
<bean class="com.hjf.pojo.Dog"/>
<!--byName:会自动在容器上下文中查找,和自己对象set方法后面的值对应的beanid! 也就是需要写对应的setter方法,
且需要注册beanid 并且id需要相对应
byType:会自动在容器上下文中查找,和自己对象属性类型相同的bean! 注:若写dog 和dog111时 会冲突,同一类型只能有一个
也可以不写id ,直接class即可-->
<bean id="people" class="com.hjf.pojo.People" autowire="byType">
<property name="name" value="卫庄"/>
</bean>
小结: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.配置注解的支持:context:annotation-config/ 【重要】
<?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
https://www.springframework.org/schema/context/spring-context.xsd">
<context:annotation-config/>
</beans>
@Autowired
直接在属性上使用即可,也可以在set方式上使用
使用 Autowired 就可以不用写Set方法了,前提是你自动装配的属性在IOC(Spring)容器中存在,且符合名字byname
@Nullable 字段标记了这个注解,说明这个字段可以null
boolean required() default true;
public class People {
//如果显示的定义Autowired的required 属性为 false,说明这个对象可以为null,否则不允许为空
@Autowired(required = false)
private Cat cat;
如果@Autowired自动装配的环境比较复杂,自动装配无法通过一个注解【@Autowired】完成的时候,可以使用@Qualifier(value = "xxxx")去配置@Autowired的使用,指定一个唯一的bean对象注入
<bean id="cat111" class="com.hjf.pojo.Cat"/>
<bean id="cat222" class="com.hjf.pojo.Cat"/>
<bean id="dog222" class="com.hjf.pojo.Dog"/>
<bean id="people" class="com.hjf.pojo.People"/>
public class People {
// @Resource(name = "cat111")也行,不指定时默认查找cat,没有就查找name里的,否则报错
@Qualifier(value = "cat111")
@Autowired
private Cat cat;
小结:
@Resource 和 @Autowired 的区别
- 都是用来自动装配的,都可以放在属性字段上
- @Autowired通过bytype的方式实现,而且必须要求这个对象存在【常用】
- @Resource默认通过byname的方式实现,如果找不到名字,则通过Bytype实现!若都找不到,则报错【常用】
- 执行顺序不同:@Autowired通过bytype的方式实现,@Resource默认通过byname的方式实现
8.使用注解开发
在Spring4之后,要使用注解开发,必须要保证aop的包导入了
<bean id="user" class="com.hjf.pojo.User">
<property name="name" value="嬴政"/>
</bean>
相当于
//等价于<bean id="user" class="com.hjf.pojo.User"/>
//@Component 组件
@Component
public class User {
// 相当于 <property name="name" value="嬴政"/>
@Value("嬴政")
public String name;
}
也可以注入在set方法上
@Component
public class User {
public String name;
// 相当于 <property name="name" value="嬴政"/>
@Value("嬴政")
public void setName(String name) {
this.name = name;
}
}
建议:复杂的走配置文件
- 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"
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">
<!--指定要扫描的包,这个包下的注解就会生效-->
<context:component-scan base-package="com.hjf.pojo"/>
<context:annotation-config/>
</beans>
- 属性如何注入
@Component
public class User {
public String name;
// 相当于 <property name="name" value="嬴政"/>
@Value("嬴政")
public void setName(String name) {
this.name = name;
}
}
- 衍生的注解
@Component有几个衍生注解,我们在web开发中,会按照mvc三层架构分层
- dao【@Repository】
- service 【@Service】
- controller 【@Controller】
这四个注解功能都是一样的,都是代表将某个类注册到spring容器中(即装配bean)
- 自动装配
@Autowired
@Resource
@Qualifier
@Nullable
- 作用域
@Scope("singleton/prototype.....")
-
小结:
xml与注解
- xml 更加万能,适用于任何场合!维护简单方便
- 注解 不是自己的类使用不了,维护相对复杂
xml与注解最佳搭配
- xml用来管理bean;
- 注解只负责完成属性的注入;
- 我们在使用的过程中,只需要注意一个问题:必须让注解生效,就需要开启注解的支持
<!--指定要扫描的包,这个包下的注解就会生效--> <context:component-scan base-package="com.hjf"/> <context:annotation-config/>
9.使用Java的方式配置spring
完全不使用spring的xml配置,全权交给Java来做!
官方文档
@Configuration
public class AppConfig {
@Bean
public MyService myService() {
return new MyServiceImpl();
}
}
The preceding AppConfig class is equivalent to the following Spring <beans/> XML:
<beans>
<bean id="myService" class="com.acme.services.MyServiceImpl"/>
</beans>
上面的Java类完全等价与下面的xml配置
Javaconfig在spring4之后,成为了核心功能【推荐使用】

实体类
package com.hjf.pojo;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component
public class User {
private String name;
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
'}';
}
public String getName() {
return name;
}
@Value("李斯")
public void setName(String name) {
this.name = name;
}
}
配置类
package com.hjf.config;
import com.hjf.pojo.User;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
//会被spring容器托管,注册到容器中,因为它本就是一个@Component
// @Configuration代表他是一个配置类,和之前的bean.xml一样
@Configuration
@ComponentScan("com.hjf.pojo")
@Import(MyConfig2.class)
public class MyConfig {
// <bean id="cat" class="com.hjf.pojo.Cat"/>
//getUser相当于id="getUser"
//User相当于class="com.hjf.pojo.User"
@Bean
public User getUser(){
return new User();
}
}
测试类
import com.hjf.config.MyConfig;
import com.hjf.pojo.User;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class MyTest {
public static void main(String[] args) {
// 如果完全使用了配置类方式,就只能通过AnnotationConfig上下文来获取容器,然后对配置类的 class 对象进行加载
ApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class);
User getUser = context.getBean("getUser", User.class);
System.out.println(getUser.getName());
}
}
这种纯Java的配置方式,在springboot随处可见
10.代理模式
SpringAOP的底层
代理模式分类:
- 静态代理
- 动态代理


10.1、静态代理
角色分析:
- 抽象角色:一般会使用接口或者抽象类来解决
- 真实角色:被代理的角色
- 代理角色:代理真实角色,代理后会做一些附属操作
- 客户:访问代理对象的人
代码步骤:
- 接口
package com.hjf.demo01;
//租房
public interface Rent {
public void rent();
}
- 真实角色
package com.hjf.demo01;
public class Host implements Rent{
@Override
public void rent() {
System.out.println("房东要出租房子");
}
}
- 代理角色
package com.hjf.demo01;
public class Proxy implements Rent{
private Host host;
public Proxy(Host host) {
this.host = host;
}
public Proxy() {
}
@Override
public void rent() {
host.rent();
seeHouse();
hetong();
}
//看房
public void seeHouse(){
System.out.println("中介代理看房");
}
//签合同
public void hetong(){
System.out.println("签合同");
}
}
- 客户端访问代理角色
package com.hjf.demo01;
public class Client {
public static void main(String[] args) {
Host host = new Host();
//代理
Proxy proxy = new Proxy(host);
proxy.rent();
}
}
代理模式的好处:
- 可以使真实角色的操作更加纯粹不用去关注一些公共的业务
- 公共业务交给了代理角色,实现了业务的分工
- 公共业务扩展的时候,方便管理
缺点:
- 一个真实角色就会产生一个代理角色;代码量会翻倍,开发效率会变低
10.2、加深理解
代码:spring-08-proxy。demo02
aop

10.3动态代理
- 动态代理和静态代理角色一样
- 动态代理的代理类是动态生成的,不是我们直接写好的
- 动态代理分为两大类:基于接口的动态代理,基于类的动态代理
- 基于接口: JDK动态代理【我们使用这个】
- 基于类: cglib
- Java字节码实现: javasist
需要了解两个类:proxy: 代理 INvocationHandler: 调用处理程序
动态代理的好处:
- 可以使真实角色的操作更加纯粹不用去关注一些公共的业务
- 公共业务交给了代理角色,实现了业务的分工
- 公共业务扩展的时候,方便管理
- 一个动态代理类代理的是一个接口,一般就是对应的一类业务
- 一个动态代理类可以代理多个类,只要实现了同一个接口即可
11、AOP
AOP为Aspect Oriented Programming的缩写,意为:[面向切面编程](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织入,需要导入依赖包
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.7</version>
</dependency>
方式一: 使用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"?>
<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"
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">
<bean id="userService" class="com.hjf.service.UserServiceImpl"/>
<bean id="log" class="com.hjf.log.Log"/>
<bean id="afterLog" class="com.hjf.log.AfterLog"/>
<!-- 方式一:使用原生态Spring API接口-->
<!-- 配置Aop:上方需要导入aop的约束-->
<aop:config>
<!-- 切入点 : expression:表达式,execution(要执行的位置!* * * * *)-->
<aop:pointcut id="pointcut" expression="execution(* com.hjf.service.UserServiceImpl.*(..))"/>
<!-- 执行环绕-->
<aop:advisor advice-ref="log" pointcut-ref="pointcut"/>
<aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/>
</aop:config>
</beans>
测试
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中配置文件
<!--方式二:自定义类-->
<bean id="diy" class="com.hjf.diy.DiyPiontCut"/>
<aop:config>
<!-- 自定义切面,ref :要引用的类-->
<aop:aspect ref="diy">
<!--切入点-->
<aop:pointcut id="point" expression="execution(* com.hjf.service.UserServiceImpl.*(..))"/>
<!-- 通知-->
<aop:before method="before" pointcut-ref="point"/>
<aop:after method="after" pointcut-ref="point"/>
</aop:aspect>
</aop:config>
- 测试:和前面一样
方式三:注解实现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,并增加支持注解的配置。
<!-- 方式三-->
<bean id="annotationPointCut" class="com.hjf.diy.AnnotationPointCut"/>
<!-- 开启注解支持 JDK(默认 proxy-target-class="false") cglib(proxy-target-class="true")-->
<aop:aspectj-autoproxy/>
- 测试,和上面一样,不需要改变
12.整合Mybatis
步骤:
- 导入相关jar包
- Junit
- mybatis
- mysql数据库
- spring相关的
- aop织入
- mybatis-spring【new】
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.26</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.7</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.10</version>
</dependency>
<!-- Spring操作数据库的话,还需要一个Spring-jdbc-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.3.10</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.7</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis-spring -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.6</version>
</dependency>
</dependencies>
编写配置文件
测试
12.1回顾mybatis
- 编写实体类
public class User {
private int id;
private String name;
private String pwd;
- 编写核心配置文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<typeAliases>
<package name="com.hjf.pojo"/>
</typeAliases>
<!-- spring-dao.xml配置后就不要mabatis这段配置了-->
<!-- <environments default="development">-->
<!-- <environment id="development">-->
<!-- <transactionManager type="JDBC"/>-->
<!-- <dataSource type="POOLED">-->
<!-- <property name="driver" value="com.mysql.cj.jdbc.Driver"/>-->
<!-- <property name="url" value="jdbc:mysql://localhost:3306/mybatis? -->
<!-- useSSL=true&useUnicode=true&characterEncoding=UTF-8"/>-->
<!-- <property name="username" value="root"/>-->
<!-- <property name="password" value="hjf"/>-->
<!-- </dataSource>-->
<!-- </environment>-->
<!-- </environments>-->
<!-- <mappers>-->
<!-- <mapper class="com.hjf.mapper.UserMapper"/>-->
<!-- </mappers>-->
</configuration>
- 编写接口
public interface UserMapper {
public List<User> selectUser();
}
- 编写mapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.hjf.mapper.UserMapper">
<select id="selectUser" resultType="user">
select * from mybatis.user ;
</select>
</mapper>
- 测试
@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<User> userList = mapper.selectUser();
for (User user : userList) {
System.out.println(user);
}
}
12.2Mybatis-spring(两种方式)
方式一:
-
编写数据源配置
<!--DataSource:使用Spring的数据源替换Mybatis的配置 c3p0 dbcp druid 这里使用Spring提供的JDBC:org.springframework.jdbc.datasource--> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=true&useUnicode=true&characterEncoding=UTF-8"/> <property name="username" value="root"/> <property name="password" value="hjf"/> </bean> -
sqlSessionFactory
<!--sqlSessionFactory-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<!-- 绑定Mybatis配置文件-->
<property name="configLocation" value="classpath:mybatis-config.xml"/>
<property name="mapperLocations" value="classpath:com/hjf/mapper/*.xml"/>
</bean>
- sqlSessionTemplate
<!-- SqlSessionTemplate:就是我们使用的 sqlSession-->
<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
<!-- 只能使用构造器注入sqlSessionFactory,因为它没有set方法-->
<constructor-arg index="0" ref="sqlSessionFactory"/>
</bean>
- 给接口加实现类
public class UserMapperImpl implements UserMapper{
//我们的所有操作,都使用sqlSession来执行,在原来,现在都使用SqlSessionTemplate;
private SqlSessionTemplate sqlSession;
public void setSqlSession(SqlSessionTemplate sqlSession) {
this.sqlSession = sqlSession;
}
@Override
public List<User> selectUser() {
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
return mapper.selectUser();
}
}
- 将写的实现类,注入到spring中
<bean id="userMapper" class="com.hjf.mapper.UserMapperImpl">
<property name="sqlSession" ref="sqlSession"/>
</bean>
- 测试
@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<User> selectUser() {
/* SqlSession sqlSession = getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
return mapper.selectUser();*/
return getSqlSession().getMapper(UserMapper.class).selectUser();
}
}
sqlSessionFactory
<bean id="userMapper2" class="com.hjf.mapper.UserMapperImpl2">
<property name="sqlSessionFactory" ref="sqlSessionFactory"/>
</bean>
测试
@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中去配置声明式事务,就需要在代码中手动配置事务
- 事务在项目的开发中十分重要,涉及到数据的一致性和完整性问题,不容马虎!
<!-- 配置声明式事务-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<constructor-arg ref="dataSource" />
<!-- 也可以这样写-->
<!-- <property name="dataSource" ref="dataSource"/>-->
</bean>
<!-- 结合AOP实现事务的织入-->
<!--配置事务通知-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<!-- 给哪些方法配置事务-->
<!-- 配置事务的传播特性: propagation= -->
<tx:attributes>
<tx:method name="add" propagation="REQUIRED"/>
<tx:method name="delete" propagation="REQUIRED"/>
<tx:method name="update" propagation="REQUIRED"/>
<tx:method name="query" read-only="true"/>
<tx:method name="*" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
<!-- 配置事务切入-->
<aop:config>
<aop:pointcut id="txPointCut" expression="execution(* com.hjf.mapper.*.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"/>
</aop:config>

浙公网安备 33010602011771号