JDK动态代理和CGLIB动态代理

JDK 动态代理的使用步骤:

复制代码

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

/**

 * 抽象接口

 */

public interface ISubject {

    void operate();

}

/**

 * 委托类, 也叫被代理类

 * 真正的处理逻辑

 */

public class RealSubject implements ISubject{

   @Override

    public void operate() {

        System.out.println("实际操作");

    }

}

/**

 * 代理对象的处理类

 */

public class ProxySubject implements InvocationHandler {

    private ISubject realSubject;

    public ProxySubject(ISubject subject) {

        this.realSubject = subject;

    }

   @Override

    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

        System.out.println("调用方法前---前置操作");

        //动态代理调用RealSubject中的方法

        Object result = method.invoke(realSubject, args);

        System.out.println("调用方法后---后置操作");

        return result;

    }

}

/**

 * 客户端调用类

 */

public class JdkProxyClient {

    public static void main(String[] args) {

        ISubject subject = new RealSubject();

        ISubject result = (ISubject)Proxy.newProxyInstance(subject.getClass().getClassLoader(), subject.getClass().getInterfaces(), new ProxySubject(subject));

        result.operate();

    }

}

CGLIB 动态代理的使用步骤:

复制代码

1

2

3

4

5

<dependency>

  <groupId>cglib</groupId>

  <artifactId>cglib</artifactId>

  <version>3.3.0</version>

</dependency>

第一步: 创建委托类

复制代码

1

2

3

4

5

public class RealSubject {

    public void operate() {

        System.out.println("实际操作的动作");

    }

}

第二步: 创建拦截器类, 实现MethodInterceptor 接口. 在这里面可以对方法进行增强处理

复制代码

1

2

3

4

5

6

7

8

9

10

11

12

13

14

public class ProxyMethodInterceptor implements MethodInterceptor {

    <a href="/profile/992988" data-card-uid="992988" class="js-nc-card" target="_blank" from-niu="default">@Override

    public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {

        System.out.println("调用真实操作之前---操作前处理");

       // 调用真实用户需要处理的业务逻辑

        Object object = methodProxy.invokeSuper(o, args);

        System.out.println("调用真实操作之后---操作后处理");

        return object;

    }

}</a>

第三步: 创建代理对象Proxy:通过 Enhancer.create() 创建委托类对象的代理对象

复制代码

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

public class CglibProxyFactory {

    public static Object getProxy(Class<?> clazz) {

        // 创建cglib动态代理的增强类

        Enhancer enhancer = new Enhancer();

        // 设置类加载器

        enhancer.setClassLoader(clazz.getClassLoader());

        // 设置委托类

        enhancer.setSuperclass(clazz);

        // 设置方法拦截器

        enhancer.setCallback(new ProxyMethodInterceptor());

        // 创建代理类

        return enhancer.create();

    }

}

第四步: 客户端调用

复制代码

1

2

3

4

5

6

public class CglibClient {

    public static void main(String[] args) {

        RealSubject proxy = (RealSubject)CglibProxyFactory.getProxy(RealSubject.class);

        proxy.operate();

    }

}

JDK 动态代理和 CGLIB 动态代理对比

1)JDK 动态代理是基于实现了接口的委托类,通过接口实现代理;而 CGLIB 动态代理是基于继承了委托类的子类,通过子类实现代理。

2)JDK 动态代理只能代理实现了接口的类,且只能增强接口中现有的方法;而 CGLIB 可以代理未实现任何接口的类。

3)就二者的效率来说,大部分情况都是 JDK 动态代理的效率更高,随着 JDK 版本的升级,这个优势更加明显。

4. 什么情况下使用动态代理?

1)我们知道, 设计模式的开闭原则,对修改关闭,对扩展开放,在工作中, 经常会接手前人写的代码,有时里面的代码逻辑很复杂不容易修改,那么这时我们就可以使用代理模式对原来的类进行增强。

2)在使用 RPC 框架的时候,框架本身并不能提前知道各个业务方要调用哪些接口的哪些方法 。那么这个时候,就可用通过动态代理的方式来建立一个中间人给客户端使用,也方便框架进行搭建逻辑,某种程度上也是客户端代码和框架松耦合的一种表现。

3)Spring AOP 采用了动态代理模式

 静态代理和动态代理对比

1)灵活性 :动态代理更加灵活,不需要必须实现接口,可以直接代理实现类,并且可以不需要针对每个目标类都创建一个代理类。另外,静态代理中,接口一旦新增加方法,目标对象和代理对象都要进行修改,这是非常麻烦的

2)JVM 层面 :静态代理在编译时就将接口、实现类、代理类这些都变成了一个个实际的 .class 字节码文件。而动态代理是在运行时动态生成类字节码,并加载到 JVM 中的。

  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值