0
点赞
收藏
分享

微信扫一扫

【关于Spring那些事】——带你了解Spring AOP的代理模式



Spring AOP 之代理模式

  • ​​一、静态代理​​
  • ​​二、动态代理​​
  • ​​2.1 JDK动态代理​​
  • ​​2.2 CGLib代理​​

一、静态代理


静态代理,代理类和被代理的类实现了同样的接口,只能代理特定的类。


  1. 定义一个接口
public interface Service {
public void delete();
public void update();
public void insert();
}
  1. 被代理类
public class StudentServiceImpl implements Service {
@Override
public void delete() {
System.out.println("删除学生信息!!!");
}

@Override
public void update() {
System.out.println("修改学生信息!!!");
}

@Override
public void insert() {
System.out.println("添加学生信息!!!");
}
}
  1. 代理类
public class StaticProxy implements Service {

private Service service;

public StaticProxy(Service service) {
this.service = service;
}

public void delete() {
open();
service.delete();
commit();
}

public void update() {
open();
service.update();
commit();
}

public void insert() {
open();
service.insert();
commit();
}

public void open(){
System.out.println("开启事务!!!");
}
public void commit(){
System.out.println("提交事务!!!");
}

}

4.测试类

public class Test {
public static void main(String[] args) {
//被代理类
StudentServiceImpl student = new StudentServiceImpl();
//被代理类的代理对象
StaticProxy proxy = new StaticProxy(student);
//通过代理对象调用被代理类的方法
proxy.delete();
}
}

运行结果:

【关于Spring那些事】——带你了解Spring AOP的代理模式_动态代理


被代理类只需负责自己特定的业务,而代理类则负责业务的扩展,比如执行被代理类的方法前要开启事务,执行之后要提交事务,我们就不需要给每个方法都添加开启事务和提交事务。
代理类就会负责完成这些工作。


静态代理的优缺点:

  1. 优点:
  • 被代理类只需负责核心业务
  • 业务逻辑的扩展更加方便
  • 通用代码放到代理类中,提高了代码的复用性
  1. 缺点:
  • 被代理类太多,就会导致工作量变大,开发效率降低

二、动态代理


动态代理,由AOP框架动态生成的一的对象,对象可以作为目标对象使用。
动态代理有两种方式:

  • JDK动态代理
  • CGLIB代理


2.1 JDK动态代理

基于接口的动态代理,只能为实现了接口的类动态代理对象

  • 创建一个接口并创建一个它的实现类并重写它的方法。
  • 创建一个类实现InvocationHandler接口,并重写invoke方法
public class JdkDynamicProxy implements InvocationHandler {
//被代理的对象
private Object object;

public JdkDynamicProxy(Object object) {
this.object = object;
}
//产生代理对象,返回代理对象
public Object getProxy(){
//1.获取被代理对象的类加载器
ClassLoader classLoader = object.getClass().getClassLoader();
//2.获取被代理对象实现的所有接口
Class<?>[] interfaces = object.getClass().getInterfaces();
//3.创建代理对象
//classloader:类加载器来定义代理类
//interfaces:代理类实现的接口列表
//this:调度方法调用的调用处理函数
Object o = Proxy.newProxyInstance(classLoader, interfaces,this);
return o;
}
//处理代理实例,返回结果
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
log(method.getName());
Object invoke = method.invoke(object,args);
return invoke;
}
//定义一个打印日志的方法
public void log(String msg){
System.out.println("执行了"+ msg +"方法!");
}
}
  • 测试
public class DynamicProxyTest {
public static void main(String[] args) {
//创建被代理类对象
StudentServiceImpl studentService = new StudentServiceImpl();
//创建代理对象,产生的代理对象可以强转成被代理对象实现的接口类型
JdkDynamicProxy jdkDynamicProxy = new JdkDynamicProxy(studentService);
Service proxy = (Service) jdkDynamicProxy.getProxy();
//使用代理对象调方法,不会执行调用的方法,而是进入到创建代理对象时指定的invoke方法
//调用的方法作为一个参数,传给invoke方法
proxy.delete();
}
}

运行结果:

【关于Spring那些事】——带你了解Spring AOP的代理模式_代理类_02

2.2 CGLib代理


使用JDK动态代理的对象必须是实现了一个或多个接口的,如果要对没有实现接口的类创建代理对象,就要使用CGLIB代理。
基于类的动态代理—CGlib


  • CGLib是一个高性能开源的代码生成包,因在Spring的核心包中已包含CGLib所需要的包,所以不再需要添加依赖。
  • 创建一个StudentServiceImpl 类,并添加增删改方法。
  • 创建一个类,实现MethodInterceptor接口,并重写intercept方法。
/**
* CGLIB代理
*/
public class CGLibDynamicProxy implements MethodInterceptor {

private Object object;

public CGLibDynamicProxy(Object object) {
this.object = object;
}
//创建并返回代理对象
//该代理对象是通过被代理类的子类来创建的
public Object getProxy(){
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(object.getClass());
enhancer.setCallback(this);
return enhancer.create();
}

@Override
public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
log(method.getName());
Object invoke = method.invoke(object, args);
return invoke;
}

//定义一个打印日志的方法
public void log(String msg){
System.out.println("执行了"+ msg +"方法!");
}
}
  • 测试
public class DynamicProxyTest {
public static void main(String[] args) {
//创建被代理类对象
StudentServiceImpl studentService = new StudentServiceImpl();
//创建代理对象,产生的代理对象可以强转成被代理类类型
CGLibDynamicProxy cgLibDynamicProxy = new CGLibDynamicProxy(studentService);
StudentServiceImpl proxy = (StudentServiceImpl) cgLibDynamicProxy.getProxy();
//使用代理对象调方法,不会执行调用的方法,而是进入到创建代理对象时指定的intercept方法
//将调用的方法以及方法中的参数传给intercept方法
proxy.insert();
}
}

运行结果:

【关于Spring那些事】——带你了解Spring AOP的代理模式_spring_03

动态代理的优点:

  • 被代理类只需负责核心业务;
  • 业务逻辑的扩展更加方便;
  • 通用代码放到代理类中,提高了代码的复用性;
  • 一个动态代理 , 一般代理某一类业务;
  • 一个动态代理可以代理多个类,代理的是接口。


举报

相关推荐

0 条评论