代理模式。静态代理,动态代理,CGLib代理

参考:https://www.cnblogs.com/puyangsky/p/6218925.html

 

代理模式

3个组成部分:1、接口   2、接口实现类   3、代理类

 

 

静态代理

接口类

1
2
3
interface Person {
    void speak();
}

 

接口实现类:

1
2
3
4
5
6
7
8
9
10
11
class Actor implements Person {
    private String content;
    public Actor(String content) {
        this.content = content;
    }
 
    @Override
    public void speak() {
        System.out.println(this.content);
    }
}

 

代理类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Agent implements Person {
    private Actor actor;
    private String before;
    private String after;
    public Agent(Actor actor, String before, String after) {
        this.actor = actor;
        this.before = before;
        this.after = after;
    }
    @Override
    public void speak() {
        //before speak
        System.out.println("Before actor speak, Agent say: " + before);
        //real speak
        this.actor.speak();
        //after speak
        System.out.println("After actor speak, Agent say: " + after);
    }
}<br>

  测试类:

1
2
3
4
5
6
7
public class StaticProxy {
    public static void main(String[] args) {
        Actor actor = new Actor("I am a famous actor!");
        Agent agent = new Agent(actor, "Hello I am an agent.", "That's all!");
        agent.speak();
    }
}

  结果:

 

静态代理的核心思想:代理类中包含接口实现类,在代理类中调用接口。

 

动态代理

首先介绍一下最核心的一个接口和一个方法:

首先是java.lang.reflect包里的InvocationHandler接口:

1
2
3
4
public interface InvocationHandler {
    public Object invoke(Object proxy, Method method, Object[] args)
        throws Throwable;
}

  

我们对于被代理的类的操作都会由该接口中的invoke方法实现,其中的参数的含义分别是:

  • proxy:被代理的类的实例
  • method:调用被代理的类的方法
  • args:该方法需要的参数

代理类实现InvocationHandler接口,通过 invoke方法调用实际的接口实现类方法

 

另外一个很重要的静态方法是java.lang.reflect包中的Proxy类的newProxyInstance方法:

 

1
2
3
4
public static Object newProxyInstance(ClassLoader loader,
                                      Class<?>[] interfaces,
                                      InvocationHandler h)
    throws IllegalArgumentException

 

其中的参数含义如下:

  • loader:被代理的类的类加载器 。interfaceClazz.getClassLoader(),即接口类的类加载器
  • interfaces:被代理类的接口数组。new Class[]{interfaceClazz},即接口类
  • invocationHandler:就是刚刚介绍的调用处理器类的对象实例。就是代理类实例

 

接口:

1
2
3
public interface Fruit {
    public void show();
}

 接口实现类:

1
2
3
4
5
6
public class Apple implements Fruit{
    @Override
    public void show() {
        System.out.println("<<<<show method is invoked");
    }
}

 代理类

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
public class DynamicAgent {
 
    //实现InvocationHandler接口,并且可以初始化被代理类的对象
    static class MyHandler implements InvocationHandler {
        private Object proxy;
        public MyHandler(Object proxy) {
            this.proxy = proxy;
        }
             
        //自定义invoke方法
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            System.out.println(">>>>before invoking");
            //真正调用方法的地方
            Object ret = method.invoke(this.proxy, args);
            System.out.println(">>>>after invoking");
            return ret;
        }
    }
 
    //返回一个被修改过的对象
    public static Object agent(Class interfaceClazz, Object proxy) {
        return Proxy.newProxyInstance(interfaceClazz.getClassLoader(), new Class[]{interfaceClazz},
                new MyHandler(proxy));
    }   
}

  测试:

1
2
3
4
5
6
7
public class ReflectTest {
    public static void main(String[] args) throws InvocationTargetException, IllegalAccessException {
        //注意一定要返回接口,不能返回实现类否则会报错
        Fruit fruit = (Fruit) DynamicAgent.agent(Fruit.class, new Apple());
        fruit.show();
    }
}

 结果:

缺点:必须实现接口

 

 

CGLIB库的方法     核心:动态生成一个被代理类的子类,子类重写被代理的类的所有不是final的方法。在子类中采用方法拦截的技术拦截所有父类方法的调用,顺势织入横切逻辑。

CGlib是一个字节码增强库,为AOP等提供了底层支持

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
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
 
public class CGlibAgent implements MethodInterceptor {
 
    private Object proxy;
 
    public Object getInstance(Object proxy) {
        this.proxy = proxy;
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(this.proxy.getClass());
        // 回调方法
        enhancer.setCallback(this);
        // 创建代理对象
        return enhancer.create();
    }
    //回调方法
    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println(">>>>before invoking");
        //真正调用
        Object ret = methodProxy.invokeSuper(o, objects);
        System.out.println(">>>>after invoking");
        return ret;
    }
 
    public static void main(String[] args) {
        CGlibAgent cGlibAgent = new CGlibAgent();
        Apple apple = (Apple) cGlibAgent.getInstance(new Apple());
        apple.show();
    }
}

  

 

参考:https://www.jianshu.com/p/829e93528d56

被代理类:

1
2
3
4
5
6
7
8
9
public class HelloServiceImpl {
    public void sayHello(){
        System.out.println("Hello Zhanghao");
    }
 
    public void sayBey(){
        System.out.println("Bye Zhanghao");
    }
}

 

代理类,实现

1
2
3
4
5
6
7
8
9
public class HelloMethodInterceptor  implements MethodInterceptor{
    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("Before: "  + method.getName());
        Object object = methodProxy.invokeSuper(o, objects);
        System.out.println("After: " + method.getName());
        return object;
    }
}

 测试:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class Client {
    public static void main(String[] args) {
        System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "/Users/zhanghao/Documents/toy/spring-framework-source-study/");
        Enhancer enhancer = new Enhancer();
        //继承被代理类
        enhancer.setSuperclass(HelloServiceImpl.class);
        //设置回调
        enhancer.setCallback(new HelloMethodInterceptor());
        //设置代理类对象
        HelloServiceImpl helloService = (HelloServiceImpl) enhancer.create();
        //在调用代理类中方法时会被我们实现的方法拦截器进行拦截
        helloService.sayBey();
    }
}
result:
Before: sayBey
Bye Zhanghao
After: sayBey

 核心思想:代理类实现MethodInterceptor结果。通过Enhancer将被代理类设置成超类,代理类设置为回调,通过create()创建实例,通过实例调用方法,即完成调用

posted on   潮流教父孙笑川  阅读(105)  评论(0编辑  收藏  举报

(评论功能已被禁用)
编辑推荐:
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· winform 绘制太阳,地球,月球 运作规律
· 上周热点回顾(3.3-3.9)

导航

< 2025年3月 >
23 24 25 26 27 28 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 1 2 3 4 5
点击右上角即可分享
微信分享提示