Spring Aop
# 动态代理
说到Spring AOP就先需要了解动态代理。
代理模式的解释:为其他对象提供一种代理以控制对这个对象的访问,增强一个类中的某个方法,对程序进行扩展。
实现动态代理的方式有2种:
JDK动态代理(只能代理接口类)
CGLIB(基于父子类实现)
# JDK动态代理实现
public interface UserInterface {
public void test();
}
public class UserService implements UserInterface {
@Override
public void test() {
System.out.println("test...");
}
}
public class Test {
public static void main(String[] args) {
UserService target = new UserService();
// UserInterface接口的代理对象
// 所以产生的代理对象的类型是UserInterface,而不是UserService。
Object proxy = Proxy.newProxyInstance(UserService.class.getClassLoader(), new Class[]{UserInterface.class}, (proxy1, method, args1) -> {
System.out.println("before...");
Object result = method.invoke(target, args1);
System.out.println("after...");
return result;
});
UserInterface userService = (UserInterface) proxy;
userService.test();
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# CGLIB动态代理实现
public class UserService {
public void test() {
System.out.println("test...");
}
}
public class Test {
public static void main(String[] args) {
UserService target = new UserService();
// 通过cglib技术
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(UserService.class);
// 定义额外逻辑,也就是代理逻辑
enhancer.setCallbacks(new Callback[]{(MethodInterceptor) (o, method, objects, methodProxy) -> {
System.out.println("before...");
Object result = methodProxy.invoke(target, objects);
System.out.println("after...");
return result;
}});
// 动态代理所创建出来的UserService对象
UserService userService = (UserService) enhancer.create();
// 执行这个userService的test方法时,就会额外会执行一些其他逻辑
userService.test();
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# Spring AOP
spring对于以上的两种代理方式进行了分装,封装出来的类叫做ProxyFactory。
通过ProxyFactory,我们可以不再关心到底是用cglib还是jdk动态代理,ProxyFactory会帮我们自动选择,如果UserService实现了接口,那么ProxyFactory底层就会用jdk动态代理,如果没有实现接口,就会用cglib技术,上面的代码,就是由于UserService实现了UserInterface接口,所以最后产生的代理对象是UserInterface类型。(Spring Boot 2.X默认使用CGLIB,即使实现接口也是使用CGLIB)
# Spring事务基本执行原理
开启Spring事务本质上就是增加了一个Advisor,使用@EnableTransactionManagement注解来开启Spring事务。
在spring初始化后的步骤,判断Bean的类上是否存在@Transactional注解,或者类中的某个方法上是否存在@Transactional注解,如果存在则表示该Bean需要进行动态代理产生一个代理对象作为Bean对象。执行基本流程为:
1. 利用所配置的PlatformTransactionManager事务管理器新建一个数据库连接
2. 修改数据库连接的autocommit为false
3. 执行MethodInvocation.proceed()方法,简单理解就是执行业务方法,其中就会执行sql
4. 如果没有抛异常,则提交
5. 如果抛了异常,则回滚
1
2
3
4
5
2
3
4
5
# Spring事务传播机制
假设有a,b 2个方法,2个方法都在事务中执行,且b方法开启了新事务,a方法调用b方法,那么大致流程如下:
1.通过AOP,利用事务管理器开启事务a连接,
2.设置手动提交(autocommit = false)
3.将事务a连接放入ThreadLocal中
4.执行a方法中的SQL逻辑
5.a方法调用b方法
6.a方法调用b方法时,由于b方法开启了新的事务,则 将a连接挂起放入挂起资源中,并从ThreadLocal移除事务a连接
7.利用事务管理器开启b事务连接
8.设置手动提交(autocommit = false)
9.将事务b连接放入ThreadLocal中
10.执行b方法的sql,并执行完b方法
11.利用ThreadLocal中的b连接提交事务
12.再把挂起资源中的a连接设置到ThreadLocal中.
13.a方法执行完成之后 利用ThreadLocal中的a连接提交事务
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
:::waring
虽然a和b方法属于2个事务,但是如果b方法执行失败,a方法还是会回滚
:::
上次更新: 2026/3/11 21:47:04