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实现,接口不是必须的

  • 相关阅读:
    grab jpegs from v4l2 devices
    c helloworld on zynq
    minicom installation and configuration on ubuntu
    DBA的做法
    sqlserver锁表、解锁、查看销表
    linux内核分析(网课期末&地面课期中)
    Linux内核分析实验八------理解进程调度时机跟踪分析进程调度与
    LINUX内核分析第七周——可执行程序的装载
    Linux内核分析实验六
    Linux内核分析实验五
  • 原文地址:https://www.cnblogs.com/candies123/p/10046058.html
Copyright © 2011-2022 走看看