zoukankan      html  css  js  c++  java
  • Java设计模式之代理模式的动态代理下篇

    前言

    上篇我们演示了使用JDK的InvocationHandler实现动态代理,本文我们采用cglib来实现动态代理。

    动态代理示例

    运用JDK的InvocationHandler是根据抽象接口来实现的,然而基于cglib来实现动态代理,被代理角色可以是一个普通的类,也可以是一个接口的实现类,总之,是基于类来实现的。

    首先我们在pom文件中增加cglib依赖:

    1 <dependency>
    2     <groupId>cglib</groupId>
    3     <artifactId>cglib</artifactId>
    4     <version>3.2.9</version>
    5 </dependency>

    我们增加一个没有接口的真实角色:

     1 public class RealConsumer {
     2 
     3     private String name = null;
     4 
     5     public RealConsumer(String name){
     6         this.name = name;
     7     }
     8 
     9     public RealConsumer() {
    10     }
    11 
    12     public void login(String name, String password) {
    13 
    14         System.out.println("登录用户["+name+"]登陆成功");
    15     }
    16 
    17     public void order() {
    18 
    19 
    20         System.out.println("登录账号:"+ this.name +"生成订单成功");
    21 
    22     }
    23 
    24     public void pay() {
    25 
    26         System.out.println("登录账号:"+ this.name +"订单支付成功");
    27 
    28     }
    29 
    30 }

    我们再来新增一个实现代理的拦截类,这个拦截类需要实现MethodInterceptor接口。

     1 package com.example.pattern.proxy.dynamic.cglib;
     2 
     3 
     4 
     5 
     6 
     7 import net.sf.cglib.proxy.Enhancer;
     8 import net.sf.cglib.proxy.MethodInterceptor;
     9 import net.sf.cglib.proxy.MethodProxy;
    10 
    11 import java.lang.reflect.Method;
    12 
    13 public class ConsumerIntercepor implements MethodInterceptor {
    14 
    15 
    16     private Object proxiedInstance;
    17 
    18     public Object getInstance (Object proxiedInstance) {
    19         this.proxiedInstance = proxiedInstance;
    20 
    21         Enhancer enhancer = new Enhancer();
    22         enhancer.setSuperclass(this.proxiedInstance.getClass());
    23 
    24         enhancer.setCallback(this);
    25         return enhancer.create();
    26     }
    27 
    28     @Override
    29     public Object intercept(Object object, Method method, Object[] args, MethodProxy proxy) throws Throwable {
    30 
    31         System.out.println("前置操作");
    32 
    33         proxy.invokeSuper(object, args);
    34 
    35         System.out.println("后置操作");
    36 
    37         return null;
    38     }
    39 }

    第13行,这个拦截类实现了MethodInterceper接口。

    第16行,声明被代理对象。

    第18行,获取到代理对象。

    第21行,创建加强器,用于创建动态代理类。

    第22行,指定代理类的父类,也就是被代理类。

    第24行,设置回调,这个回调就是调用上面的interceper方法。

    第25行,创建动态代理类对象并且返回。

    我们再来创建一个场景类。

     1 public class Client {
     2 
     3     public static void main(String[] args) {
     4         RealConsumer realConsumer = new RealConsumer("抒尽");
     5 
     6         ConsumerIntercepor intercepor = new ConsumerIntercepor();
     7         RealConsumer proxy = (RealConsumer)intercepor.getInstance(realConsumer);
     8 
     9         proxy.login("shujin", "123456");
    10         proxy.order();
    11         proxy.pay();
    12 
    13 
    14     }
    15 }

    我们先来看一下执行结果。

     1 ---------前置操作---------
     2 登录用户[shujin]登陆成功
     3 ---------后置操作---------
     4 
     5 ---------前置操作---------
     6 登录账号:null生成订单成功
     7 ---------后置操作---------
     8 
     9 ---------前置操作---------
    10 登录账号:null订单支付成功
    11 ---------后置操作---------

    出现了一个问题,我们最先赋值的[抒尽]为什么是空值呢??

    因为name是成员属性,是跟随着对象而存在,原始对象和代理对象不是同一个对象,因此代理对象proxy中的name当然为空。除非proxy.setName("xxx");之后,name在代理对象中才不会为空。

    这个现象也从侧面说明了jdk实现和cglib实现的不同。cglib实现的动态代理是继承了被代理对象,因此代理和被代理的关系等价于子类和父类之间的关系。另外因为是使用继承关系实现动态代理,那么被final修饰的类不可以被代理。

    最后,要实现动态代理,如果是jdk实现,必须要有一个接口,而cglib实现,接口不是必须的

  • 相关阅读:
    flash中网页跳转总结
    as3自定义事件
    mouseChildren启示
    flash拖动条移出flash无法拖动
    需要一个策略文件,但在加载此媒体时未设置checkPolicyFile标志
    Teach Yourself SQL in 10 Minutes
    电子书本地转换软件 Calibre
    Teach Yourself SQL in 10 Minutes
    Teach Yourself SQL in 10 Minutes
    Teach Yourself SQL in 10 Minutes – Page 31 练习
  • 原文地址:https://www.cnblogs.com/candies123/p/10046058.html
Copyright © 2011-2022 走看看