AOP、AspectJ、Spring AOP、JDK动态代理、CGLib动态代理

释放双眼,带上耳机,听听看~!

Table of Contents

  1. AOP介绍

2.AOP的实现

3.Spring AOP的两种实现方式

4.AspectJ实现示例

5.JDK动态代理、CGLib动态代理 实现示例

6.小结


1. AOP介绍

AOP称为面向切面编程,它是一种
编程思想,是对OOP的补充,可以进一步提高编程效率,在程序开发中主要用来解决一些系统层面上的问题,比如日志,事务,权限等待,Struts2的拦截器设计就是基于AOP的思想,是个比较经典的例子。

 AOP的基本概念:

(1)Aspect(切面):通常是一个类,里面可以定义切入点和通知

(2)JointPoint(连接点):程序执行过程中明确的点,一般是方法的调用

(3)Advice(通知):AOP在特定的切入点上执行的增强处理,有before,after,afterReturning,afterThrowing,around

(4)Pointcut(切入点):就是带有通知的连接点,在程序中主要体现为书写切入点表达式

(5)Target(目标对象):就是被增强的目标类,也称之为委托类。

(6)AOP代理:AOP框架创建的对象,代理就是目标对象的加强。Spring AOP代理可以使JDK动态代理,也可以是CGLIB代理,前者基于接口,后者基于子类。

AOP、AspectJ、Spring AOP、JDK动态代理、CGLib动态代理


2.AOP的实现

AOP前面说过是编程思想,所以需要具体的实现方法来实现。

AOP的实现主要分为静态代理和动态代理,静态代理的实现方式是AspectJ;而动态代理则以Spring AOP为代表。

  • AspectJ(静态)

  • AspectJ是语言级的实现,它扩展了Java语言,定义了AOP语法。

    • AspectJ在编译期织入代码,它有一个专门的编译器,用来生成遵守Java字节码规范的class文件。
  • Spring AOP(动态)

  • Spring AOP使用纯Java实现,它不需要专门的编译过程,也不需要特殊的类装载器。

    • Spring AOP在运行时通过代理的方式织入代码,只支持方法类型的连接点。
    • Spring支持对AspectJ的集成。

3.Spring AOP的两种实现方式

  • JDK动态代理(依赖接口)

  • Java提供的动态代理技术,可以在运行时创建接口的代理实例。

    • Spring AOP默认采用此种方式,在接口的代理实例中织入代码。
  • CGLib动态代理(不依赖接口)

  • 采用底层的字节码技术,在运行时创建子类代理实例。

    • 当目标对象不存在接口时,Spring AOP会采用此种方式,在子类实例中织入代码。

 

4.AspectJ实现示例

AspectJ是静态代理的增强,所谓的静态代理就是AOP框架会在编译阶段生成AOP代理类,因此也称为编译时增强。

静态代理模式:静态代理说白了就是在程序运行前就已经存在代理类的字节码文件,代理类和原始类的关系在运行前就已经确定。废话不多说,我们看一下代码,为了方便阅读,博主把单独的class文件合并到接口中,读者可以直接复制代码运行:


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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
1
2package test.staticProxy;
3
4// 接口
5
6public interface IUserDao {
7
8void save();
9
10void find();
11
12}
13
14//目标对象
15
16class UserDao implements IUserDao{
17
18@Override
19
20public void save() {
21
22System.out.println("模拟:保存用户!");
23
24}
25
26@Override
27
28public void find() {
29
30System.out.println("模拟:查询用户");
31
32}
33
34}
35
36/**
37
38静态代理
39
40特点:
41
421. 目标对象必须要实现接口
43
442. 代理对象,要实现与目标对象一样的接口
45
46*/
47
48class UserDaoProxy implements IUserDao{
49
50// 代理对象,需要维护一个目标对象
51
52private IUserDao target = new UserDao();
53
54@Override
55
56public void save() {
57
58System.out.println("代理操作: 开启事务...");
59
60target.save(); // 执行目标对象的方法
61
62System.out.println("代理操作:提交事务...");
63
64}
65
66@Override
67
68public void find() {
69
70target.find();
71
72}
73
74}
75

测试结果:

       

静态代理虽然保证了业务类只需关注逻辑本身,代理对象的一个接口只服务于一种类型的对象,如果要代理的方法很多,势必要为每一种方法都进行代理。再者,如果增加一个方法,除了实现类需要实现这个方法外,所有的代理类也要实现此方法。增加了代码的维护成本。那么要如何解决呢?答案是使用动态代理。

 

5.JDK动态代理、CGLib动态代理 实现示例

5.1 JDK动态代理

JDK动态代理通过反射来接收被代理的类,并且要求被代理的类必须实现一个接口。JDK动态代理的核心是InvocationHandler接口和Proxy类。

5.2 CGLIB动态代理

如果目标类没有实现接口,那么Spring AOP会选择使用CGLIB来动态代理目标类。CGLIB(Code Generation Library),是一个代码生成的类库,可以在运行时动态的生成某个类的子类。注意:CGLIB是通过继承的方式做的动态代理,因此如果某个类被标记为final,那么它是无法使用CGLIB做动态代理的。

5.3 JDK Proxy VS Cglib

JDK Proxy 的优势:

  • 最小化依赖关系,减少依赖意味着简化开发和维护,JDK 本身的支持,更加可靠;

  • 平滑进行 JDK 版本升级,而字节码类库通常需要进行更新以保证在新版上能够使用;

Cglib 框架的优势:

  • 可调用普通类,不需要实现接口;

  • 高性能;

6.小结

AspectJ在编译时就增强了目标对象,Spring AOP的动态代理则是在每次运行时动态的增强,生成AOP代理对象。区别在于生成AOP代理对象的时机不同,相对来说AspectJ的静态代理方式具有更好的性能,但是AspectJ需要特定的编译器进行处理,而Spring AOP则无需特定的编译器处理。

给TA打赏
共{{data.count}}人
人已打赏
安全技术

C++ 中 struct和class 的区别

2022-1-11 12:36:11

气候事件

武警浙江省总队提前部署抢险兵力

2011-8-5 8:16:33

个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索