Java 动态代理
本文最后更新于 756 天前,其中的信息可能已经有所发展或是发生改变。

动态代理实现:

1、JDK 动态代理

​ 用 Java 反射包中的类和接口实现动态代理

2、CGLIB 动态代理

​ 通过第三方库 CGLIB ,以继承类的方式实现动态代理

JDK 代理

由于底层机制的缘故,被代理的目标类必须实现至少一个接口

  • 创建被代理的目标类以及其实现的接口
  • 创建 InvocationHandler 接口的实现类,在 invoke() 中完成要代理的功能
  • Proxy.newInstance()动态地构造出代理对象

Hello (被代理的目标类实现的接口)

public interface Hello {
    void sayHello();

    int plus(int a, int b);
}

HelloImpl (被代理的目标类)

public class HelloImpl implements Hello {

    @Override
    public void sayHello() {
        System.out.println("sayHello方法被调用");
    }

    @Override
    public int plus(int a, int b) {
        int c = a + b;
        System.out.println("plus方法被调用");
        System.out.println("返回值为" + c);
        return c;
    }
}

MyProxyHandler (InvocationHandler的实现类)

public class MyProxyHandler implements InvocationHandler {

    private Object target = null;

    /**
     * 构造方法中传入被代理的对象
     *
     * @param target
     */
    public MyProxyHandler(Object target) {
        this.target = target;
    }

    /**
     * 需要代理的功能
     *
     * @param proxy  JDK自动创建的代理的对象
     * @param method 被代理的对象的方法(哪个方法被调用,这里的 method 就是那个方法)
     * @param args   被代理的方法的参数
     * @return
     * @throws Throwable
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

        //在执行目标方法前,做一系列增强操作
        before();

        System.out.println(method);

        //执行目标方法,获取返回值
        Object res = null;
        res = method.invoke(target, args);

        //在执行目标方法后,做一系列增强操作
        after();

        return res;
    }

    public void before() {
        System.out.println("before");
    }

    public void after() {
        System.out.println("after");
    }
}

Main (主方法)

public class Main {
    public static void main(String[] args) {

        //通过 被代理的目标类 和 InvocationHandler的实现类
        //构造出代理对象
        HelloImpl helloImpl = new HelloImpl();
        MyProxyHandler myProxyHandler = new MyProxyHandler(helloImpl);
        Hello helloProxy = (Hello) Proxy.newProxyInstance(helloImpl.getClass().getClassLoader(),
                helloImpl.getClass().getInterfaces(),
                myProxyHandler);

        helloProxy.sayHello();
        System.out.println("==========");
        helloProxy.plus(1, 1);
    }
}

//输出
//before
//public abstract void Hello.sayHello()
//sayHello方法被调用
//after
//==========
//before
//public abstract int Hello.plus(int,int)
//plus方法被调用
//返回值为2
//after

JDK 代理生成的代理对象实际上是在原对象的基础上,给每个方法都用 invoke() 进行了加强

相较于静态代理,使用少量的代码就可以完成增强效果

CGLIB 代理

需要导入jar包:核心包和依赖包(spring_core.jar已经集成了这两个包,因此,导入此包即可)

子类是在调用的时候才生成的

使用目标对象的子类的方式实现的代理,它是在内存中构建一个子类对象从而实现对目标对象功能的扩展,能够在运行时动态生成字节码,可以解决目标对象没有实现接口的问题

缺点:被final或static修饰的类不能用cglib代理,因为它们不会被拦截,不会执行目标对象的额外业务方法

Java 动态代理详解 – whirlys – 博客园 (cnblogs.com)

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇