每一秒钟的时间都值得铭记

0%

Spring AOP的两种实现方式

什么是AOP?

AOP(Aspect Oriented Programming),面向切面编程,AOP不是单独指某一种技术,而是一种编程思想,AOP是OOP的一种补充,用于处理各个业务逻辑中的横切关注点,比如日志记录,事务处理,性能统计,异常处理等等。
AOP的主要功能是将大量的通用行为从业务逻辑中抽取出来,将这些行为封装成独立的非业务方法,用于横向切入,这些行为不会对已有的业务逻辑产生任何影响。

AOP是一种设计思想,而Spring AOP则是符合AOP思想的一种框架实现。

Spring AOP

Spring AOP主要有两种实现,分别的JDK动态代理和Cglib动态代理。

JDK动态代理
JDK动态代理是JDK内置的一种动态代理模式,使用反射来接受被代理的类,但是被代理的类必须实现一个接口。

Cglib动态代理
Cglib是一个代码生成的类库,可以在运行时动态生成某个类的子类,所以如果需要被Cglib动态代理,那么就需要被代理类不能被final修饰。

  • 在Spring AOP中,如果一个类实现了接口,那么就使用JDK动态代理的方式进行AOP实现,而如果这个类没有实现接口,则使用Cglib动态代理的方式进行AOP实现。如果一个类既没有接口,同时又被final修饰,那么这个类不能进行AOP动态代理。

JDK动态代理

JDK动态代理,由于是JDK内置的代理模式,所以我们不需要引入任何依赖,可以直接使用。

1、编写JDK动态代理代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class JDKProxy implements InvocationHandler {

private Object target;

public JDKProxy(Object target){
this.target = target;
}

public Object createProxy() {
Object proxy = Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(), this);
return proxy;
}

@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("JDK动态代理前置通知......");
Object object = method.invoke(target, args);
System.out.println("JDK动态代理后置通知......");
return object;
}
}

2、编写一个接口

1
2
3
4
5
6
public interface UserDao {
void save();
void update();
void find();
void delete();
}

3、编写被代理类实现该接口。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class UserDaoImpl implements UserDao {
@Override
public void save() {
System.out.println("保存用户......");
}
@Override
public void update() {
System.out.println("修改用户......");
}
@Override
public void find() {
System.out.println("查找用户......");
}
@Override
public void delete() {
System.out.println("删除用户......");
}
}

4、测试

1
2
3
4
5
6
7
8
9
10
public class JDKProxyTest {
public static void main(String[] args) {
UserDao userDao = new UserDaoImpl();
UserDao proxy = (UserDao) new JDKProxy(userDao).createProxy();
proxy.save();
proxy.update();
proxy.find();
proxy.delete();
}
}

5、测试结果

1
2
3
4
5
6
7
8
9
10
11
12
JDK动态代理前置通知......
保存用户......
JDK动态代理后置通知......
JDK动态代理前置通知......
修改用户......
JDK动态代理后置通知......
JDK动态代理前置通知......
查找用户......
JDK动态代理后置通知......
JDK动态代理前置通知......
删除用户......
JDK动态代理后置通知......

Cglib动态代理

Cglib动态代理,需要引入外部依赖,我们可以直接引入Spring的核心依赖即可,Spring中有Cglib的类库。

1、引入依赖

1
2
3
4
5
6
7
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.0.8.RELEASE</version>
</dependency>
</dependencies>

2、编写Cglib动态代理代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class CglibProxy implements MethodInterceptor {

private Object target;

public CglibProxy(Object target){
this.target = target;
}

public Object createProxy() {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(target.getClass());
enhancer.setCallback(this);
Object proxy = enhancer.create();
return proxy;
}

@Override
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
System.out.println("Cglib动态代理前置通知......");
Object object = method.invoke(target, args);
System.out.println("Cglib动态代理后置通知......");
return object;
}
}

3、编写被代理类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class CustomerDao {
public void save() {
System.out.println("保存客户......");
}
public void update() {
System.out.println("修改客户......");
}
public void find() {
System.out.println("查找客户......");
}
public void delete() {
System.out.println("删除客户......");
}
}

4、测试

1
2
3
4
5
6
7
8
9
10
public class CglibProxyTest {
public static void main(String[] args) {
CustomerDao customerDao = new CustomerDao();
CustomerDao proxy = (CustomerDao) new CglibProxy(customerDao).createProxy();
proxy.save();
proxy.update();
proxy.find();
proxy.delete();
}
}

5、测试结果

1
2
3
4
5
6
7
8
9
10
11
12
Cglib动态代理前置通知......
保存客户......
Cglib动态代理后置通知......
Cglib动态代理前置通知......
修改客户......
Cglib动态代理后置通知......
Cglib动态代理前置通知......
查找客户......
Cglib动态代理后置通知......
Cglib动态代理前置通知......
删除客户......
Cglib动态代理后置通知......
坚持原创技术分享,您的支持将鼓励我继续创作!
-------------这是我的底线^_^-------------