SpringFamework的学习,是小编正在经历的,作为刚刚接触这玩意的新人,也算是摸爬滚打一路奔跑
与君共勉!!!
本文的学习学自狂神说,大家可以在B站找到!赞!狂神说!!
AOP(Aspect Oriented Programming)意为:面向切面编程,通过预编译方式和运行期动态代理实现
程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的
一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使
得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
本图借自狂神的笔记

| 通知类型 | 连接点 | 实现接口 |
|---|---|---|
| 前置通知 | 方法方法前 | org.springframework.aop.MethodBeforeAdvice |
| 方法后 | 后置通知 | org.springframework.aop.AfterReturningAdvice |
| 环绕通知 | 方法前后 | org.aopalliance.intercept.MethodInterceptor |
| 方法抛出异常 | 异常抛出通知 | org.springframework.aop.ThrowsAdvice |
| 引介通知 | 类中增加新的方法属性 | orgspringframework.aop.Introductionlnterceptor |
即 Aop 在 不改变原有代码的情况下 , 去增加新的功能 .
<dependencies>
<dependency>
<groupId>org.aspectjgroupId>
<artifactId>aspectjweaverartifactId>
<version>1.9.9.1version>
dependency>
dependencies>
package com.yang.service;
/**
* @author 缘友一世
* @date 2022/7/27-20:40
*/
public interface UserService {
public void add();
public void delete();
public void update();
public void query();
}
package com.yang.service;
/**
* @author 缘友一世
* @date 2022/7/27-20:42
*/
public class UserServiceImpl implements UserService {
public void add() {
System.out.println("add a user");
}
public void delete() {
System.out.println("delete a user");
}
public void update() {
System.out.println("update a user");
}
public void query() {
System.out.println("query a user ");
}
}
package com.yang.log;
import org.springframework.aop.AfterReturningAdvice;
import java.lang.reflect.Method;
/**
* @author 缘友一世
* @date 2022/7/27-20:53
*/
public class AfterLog implements AfterReturningAdvice {
//method : 要执行的目标对象的方法
//objects : 被调用的方法的参数
//Object : 目标对象
public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
System.out.println("执行了"+method.getName()+"方法,返回结果:"+returnValue);
}
}
package com.yang.log;
import org.springframework.aop.MethodBeforeAdvice;
import java.lang.reflect.Method;
/**
* @author 缘友一世
* @date 2022/7/27-20:47
*/
public class BeforeLog implements MethodBeforeAdvice {
//method:要执行的目标对象的方法
//args:被调用的方法的对象的参数
//target:目标读写;被调用的目标对象
//returnValue 返回值
public void before(Method method, Object[] args, Object target) throws Throwable {
System.out.println(target.getClass().getName()+"的"+method.getName()+"被执行了");
}
}
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
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/aop
https://www.springframework.org/schema/aop/spring-aop.xsd">
<bean id="userService" class="com.yang.service.UserServiceImpl"/>
<bean id="log" class="com.yang.log.BeforeLog"/>
<bean id="after" class="com.yang.log.AfterLog"/>
<aop:config>
<aop:pointcut id="pointCut" expression="execution(* com.yang.service.UserServiceImpl.*(..))"/>
<aop:advisor advice-ref="log" pointcut-ref="pointCut"/>
<aop:advisor advice-ref="after" pointcut-ref="pointCut"/>
aop:config>
beans>
狂神的话:
- Aop的重要性 : 很重要 . 一定要理解其中的思路 , 主要是思想的理解这一块 .
- Spring的Aop就是将公共的业务 (日志 , 安全等) 和领域业务结合起来 , 当执行领域业务时 , 将会把公共业务加进来 . 实现公共业务的重复利用 . 领域业务更纯粹 , 程序猿专注领域业务 , 其本质还是动态代理
package com.yang.diy;
/**
* @author 缘友一世
* @date 2022/7/28-14:41
*/
public class DIyPointCut {
public void before() {
System.out.println("====执行方法前====");
}
public void after() {
System.out.println("====执行方法后====");
}
}
<bean id="diy" class="com.yang.diy.DIyPointCut"/>
<aop:config>
<aop:aspect ref="diy">
<aop:pointcut id="point" expression="execution(* com.yang.service.UserServiceImpl.*(..))"/>
<aop:before method="before" pointcut-ref="point"/>
<aop:after method="after" pointcut-ref="point"/>
aop:aspect>
aop:config>
import com.yang.service.UserService;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* @author 缘友一世
* @date 2022/7/27-21:15
*/
public class MyTest09 {
public static void main(String[] args) {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("ApplicationContext.xml");
//动态代理代理的是接口:注意点
UserService userService = (UserService) context.getBean("userService");
userService.query();
}
}
package com.yang.diy;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
/**
* @author 缘友一世
* @date 2022/7/28-14:58
*/
//方式三:使用注解方式实现AOP
@Aspect//标注此类是一个切面
public class AnnotationPointCut {
@Before("execution(* com.yang.service.UserServiceImpl.*(..))")
public void before() {
System.out.println("==方法执行前==");
}
@After("execution(* com.yang.service.UserServiceImpl.*(..))")
public void after() {
System.out.println("==方法执行后==");
}
//在环绕增强中,可以定义一个参数,代表要获取处理的切入点
@Around("execution(* com.yang.service.UserServiceImpl.*(..))")
public void around(ProceedingJoinPoint jp) throws Throwable {
Signature signature = jp.getSignature();//获取签名
System.out.println("signature"+signature);
System.out.println("环绕前");
Object proceed = jp.proceed();//执行方法
System.out.println("环绕后");
System.out.println(proceed);
}
/*
* signaturevoid com.yang.service.UserService.query()
环绕前
==方法执行前==
query a user
==方法执行后==
环绕后
null*/
}
<bean id="annotationPointCut" class="com.yang.diy.AnnotationPointCut"/>
<aop:aspectj-autoproxy/>
通过aop命名空间的<aop:aspectj-autoproxy />声明自动为spring容器中那些配置@aspectJ切面
的bean创建代理,织入切面。当然,spring 在内部依旧采用
AnnotationAwareAspectJAutoProxyCreator进行自动代理的创建工作,但具体实现的细节已经被
<aop:aspectj-autoproxy />隐藏起来了
<aop:aspectj-autoproxy />有一个proxy-target-class属性,默认为false,表示使用jdk动态
代理织入增强,当配为<aop:aspectj-autoproxy poxy-target-class="true"/>时,表示使用
CGLib动态代理技术织入增强。不过即使proxy-target-class设置为false,如果目标类没有声明接
口,则spring将自动使用CGLib动态代理。
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
<version>4.11version>
dependency>
<dependency>
<groupId>org.mybatisgroupId>
<artifactId>mybatisartifactId>
<version>3.5.6version>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>8.0.29version>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-webmvcartifactId>
<version>5.3.18version>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-jdbcartifactId>
<version>5.3.20version>
dependency>
<dependency>
<groupId>org.aspectjgroupId>
<artifactId>aspectjweaverartifactId>
<version>1.9.9.1version>
dependency>
<dependency>
<groupId>org.mybatisgroupId>
<artifactId>mybatis-springartifactId>
<version>2.0.7version>
dependency>
<build>
<resources>
<resource>
<directory>src/main/javadirectory>
<includes>
<include>**/*.propertiesinclude>
<include>**/*.xmlinclude>
includes>
<filtering>truefiltering>
resource>
<resource>
<directory>src/main/resourcesdirectory>
<includes>
<include>**/*.propertiesinclude>
<include>**/*.xmlinclude>
includes>
<filtering>truefiltering>
resource>
resources>
build>
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
<version>1.18.24version>
dependency>
DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<properties resource="db.properties"/>
<settings>
<setting name="logImpl" value="STDOUT_LOGGING"/>
<setting name="mapUnderscoreToCamelCase" value="true"/>
settings>
<typeAliases>
<package name="com.yang.pojo"/>
typeAliases>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
dataSource>
environment>
environments>
<mappers>
<package name="com.yang.dao"/>
mappers>
configuration>
package com.yang.pojo;
import lombok.Data;
/**
* @author 缘友一世
* @date 2022/7/28-15:44
*/
@Data
public class User {
private int id;
private String name;
private String pwd;
}
public interface UserMapper {
List<User> selectUser1();
}
DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.yang.mapper.UserMapper">
<select id="selectUser1" resultType="com.yang.pojo.User">
select *
from mybatis.user;
select>
mapper>
import com.yang.mapper.UserMapper;
import com.yang.pojo.User;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* @author 缘友一世
* @date 2022/7/28-15:57
*/
public class MyTest10 {
@Test
public void test1() {
ApplicationContext context = new ClassPathXmlApplicationContext("ApplicationText.xml");
UserMapper userMapper = context.getBean("userMapper2", UserMapper.class);
for(User user:userMapper.selectUser1())
{
System.out.println(user);
}
}
}

| MyBatis-Spring | MyBatis Spring 框架 | Spring Batch | Java |
|---|---|---|---|
| 2.0 | 3.5+ | 5.0+ | 4.0+ |
| 1.3 | 3.4+ | 3.2.2+ | 2.1+ |
dependency>
<dependency>
<groupId>org.mybatisgroupId>
<artifactId>mybatis-springartifactId>
<version>2.0.7version>
dependency>
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="datasource" />
bean>
注意: SqlSessionFactory 需要一个 DataSource (数据源)。 这可以是任意的DataSource ,只需要和配置其它 Spring 数据库连接一样配置它就可以了。
在基础的 MyBatis 用法中,是通过 SqlSessionFactoryBuilder 来创建 SqlSessionFactory的。 而在 MyBatis-Spring 中,则使用== SqlSessionFactoryBean== 来创建。
在 MyBatis 中,你可以使用 SqlSessionFactory 来创建 SqlSession 。一旦你获得一个session 之后,你可以使用它来执行映射了的语句,提交或回滚连接,最后,当不再需要它的时候,你可以关闭 session。
SqlSessionFactory 有一个唯一的必要属性:用于 JDBC 的 DataSource 。这可以是任意的DataSource 对象,它的配置方法和其它 Spring 数据库连接是一样的。
一个常用的属性是== configLocation ==,它用来指定 MyBatis 的 XML 配置文件路径。它在需要修改MyBatis 的基础配置非常有用。通常,基础配置指的是 或 元素。
需要注意的是,这个配置文件并不需要是一个完整的 MyBatis 配置。确切地说,任何环境配置( ,数据源( )和 MyBatis 的事务管理器( )都会被忽略。 SqlSessionFactoryBean 会创建它自有的 MyBatis环境配置( Environment ),并按要求设置自定义环境的值。SqlSessionTemplate 是 MyBatis-Spring 的核心。作为 SqlSession 的一个实现,这意味着可以使用它无缝代替你代码中已经在使用的== SqlSession ==。
可以使用 ==SqlSessionFactory ==作为构造方法的参数来创建 SqlSessionTemplate 对象。可以使用 SqlSessionFactory 作为构造方法的参数来创建 SqlSessionTemplate 对象。
<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
<constructor-arg name="sqlSessionFactory" ref="sqlSessionFactory"/>
bean>
package com.yang.mapper;
import com.yang.pojo.User;
import org.mybatis.spring.SqlSessionTemplate;
import java.util.List;
/**
* @author 缘友一世
* @date 2022/7/28-17:03
*/
public class UserMapperImpl implements UserMapper{
//我们所有的操作,在原来都使用sqlSession来执行,现在,都使用sqlSessionTemplate;
private SqlSessionTemplate sqlSession;
public void setSqlSession(SqlSessionTemplate sqlSession) {
this.sqlSession = sqlSession;
}
public List<User> selectUser1() {
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
return mapper.selectUser1();
}
}
<bean id="userMapper" class="com.yang.mapper.UserMapperImpl">
<property name="sqlSession" ref="sqlSession"/>
bean>
<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="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&serverTimezone=UTC"/>
<property name="username" value="root"/>
<property name="password" value="xxxxxxxx"/>
bean>
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="datasource" />
<property name="configLocation" value="classpath:mybatis-config.xml"/>
<property name="mapperLocations" value="classpath:com/yang/mapper/*.xml"/>
bean>
<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
<constructor-arg name="sqlSessionFactory" ref="sqlSessionFactory"/>
bean>
package com.yang.mapper;
import com.yang.pojo.User;
import org.mybatis.spring.SqlSessionTemplate;
import java.util.List;
/**
* @author 缘友一世
* @date 2022/7/28-17:03
*/
public class UserMapperImpl implements UserMapper{
//我们所有的操作,在原来都使用sqlSession来执行,现在,都使用sqlSessionTemplate;
//私有化sqlSessionTemplate
//sqlSession不用我们自己创建了,Spring来管理
private SqlSessionTemplate sqlSession;
public void setSqlSession(SqlSessionTemplate sqlSession) {
this.sqlSession = sqlSession;
}
public List<User> selectUser1() {
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
return mapper.selectUser1();
}
}
<bean id="userMapper" class="com.yang.mapper.UserMapperImpl">
<property name="sqlSession" ref="sqlSession"/>
bean>
public class MyTest10 {
@Test
public void test1() {
ApplicationContext context = new ClassPathXmlApplicationContext("ApplicationText.xml");
UserMapper userMapper = context.getBean("userMapper2", UserMapper.class);
for(User user:userMapper.selectUser1())
{
System.out.println(user);
}
}
}
结果成功输出!现在我们的Mybatis配置文件的状态!发现都可以被Spring整合!


package com.yang.mapper;
import com.yang.pojo.User;
import org.mybatis.spring.support.SqlSessionDaoSupport;
import java.util.List;
/**
* @author 缘友一世
* @date 2022/7/28-18:25
*/
public class UserMapperImpl2 extends SqlSessionDaoSupport implements UserMapper{
public List<User> selectUser1() {
return getSqlSession().getMapper(UserMapper.class).selectUser1();
}
}
<bean id="userMapper2" class="com.yang.mapper.UserMapperImpl2">
<property name="sqlSessionFactory" ref="sqlSessionFactory"/>
bean>
@Test
public void test2() {
ApplicationContext context = new ClassPathXmlApplicationContext("ApplicationText.xml");
UserMapper userMapper = context.getBean("userMapper2", UserMapper.class);
for(User user:userMapper.selectUser1())
{
System.out.println(user);
}
}

- 事务在项目开发过程非常重要,涉及到数据的一致性的问题,不容马虎!
- 事务管理是企业级应用程序开发中必备技术,用来确保数据的完整性和一致性。
- 事务的原子性:事务就是把一系列的动作当成一个独立的工作单元,这些动作要么全部完成,要么全部不起作用。
| 事务特性ACID | 详解 |
|---|---|
| 1. 原子性(atomicity) | 事务是原子性操作,由一系列动作组成,事务的原子性确保动作要么全部完成,要么完全不起作用 |
| 2. 一致性(consistency) | 一旦所有事务动作完成,事务就要被提交。数据和资源处于一种满足业务规则的一致性状态中 |
| 3. 隔离性(isolation) | 可能多个事务会同时处理相同的数据,因此每个事务都应该与其他事务隔离开来,防止数据损坏 |
| 4. 持久性(durability) | 事务一旦完成,无论系统发生什么错误,结果都不会受到影响。通常情况下,事务的结果被写到持久化存储器中 |
//add a user
int addUser(User user);
//delete a user
int deleteUser(int id);
<insert id="addUser" parameterType="com.kuang.pojo.User">
insert into user (id,name,pwd) values (#{id},#{name},#{pwd})
insert>
<delete id="deleteUser" parameterType="int">
deletes from user where id = #{id}
delete>
package com.yang.mapper;
import com.yang.pojo.User;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.support.SqlSessionDaoSupport;
import java.util.List;
/**
* @author 缘友一世
* @date 2022/7/28-17:03
*/
public class UserMapperImpl extends SqlSessionDaoSupport implements UserMapper{
public List<User> selectUser1() {
User user1 = new User(5, "西瓜姑娘", "852963741");
UserMapper mapper = getSqlSession().getMapper(UserMapper.class);
mapper.addUser(user1);
mapper.deleteUser(5);
return mapper.selectUser1();
}
public int addUser(User user) {
return getSqlSession().getMapper(UserMapper.class).addUser(user);
}
public int deleteUser(int id) {
return getSqlSession().getMapper(UserMapper.class).deleteUser(id);
}
}
public class MyTest11 {
//本次实验为引出事务管理器
//delete语句有错误,但是add事务执行了,提交到了数据库,成功了一般,违反事务的原子性
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("ApplicationContext11.xml");
UserMapper userMapper = context.getBean("UserMapper", UserMapper.class);
List<User> users = userMapper.selectUser1();
for(User user:users) {
System.out.println(user);
}
}
}

xmlns:tx="http://www.springframework.org/schema/tx"
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="datasource"/>
bean>
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<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>
| 传播行为分类 | 详解 |
|---|---|
| propagation_requierd | 如果当前没有事务,就新建一个事务,如果已存在一个事务中,加入到这个事务中,这是最常见的选择。 |
| propagation_supports | 支持当前事务,如果没有当前事务,就以非事务方法执行。 |
| propagation_mandatory | 使用当前事务,如果没有当前事务,就抛出异常。 |
| propagation_required_new | 新建事务,如果当前存在事务,把当前事务挂起。 |
| propagation_not_supported | 以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。 |
| propagation_never | 以非事务方式执行操作,如果当前事务存在则抛出异常。 |
| propagation_nested | 如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与propagation_required类似的操作 |
- Spring 默认的事务传播行为是 PROPAGATION_REQUIRED,它适合于绝大多数的情况。
- 假设 ServiveX#methodX() 都工作在事务环境下(即都被 Spring 事务增强了),假设程序中存在如下的调用链:
Service1#method1()->Service2#method2()->Service3#method3(),
那么这 3 个服务类的 3个方法通过 Spring 的事务传播机制都工作在同一个事务中。- 就好比,我们刚才的几个方法存在调用,所以会被放在一组事务当中!
<aop:config>
<aop:pointcut id="txPointCut" expression="execution(* com.yang.mapper.*.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"/>
aop:config>
public class MyTest11 {
//本次实验为引出事务管理器
//delete语句有错误,但是add事务执行了,提交到了数据库,成功了一般,违反事务的原子性
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("ApplicationContext11.xml");
UserMapper userMapper = context.getBean("UserMapper", UserMapper.class);
List<User> users = userMapper.selectUser1();
for(User user:users) {
System.out.println(user);
}
}
}


