zoukankan      html  css  js  c++  java
  • 代理模式-细细道来

    概述

      代理(Proxy) 是一种设计模式,提供了对目标对象的另外一种访问方式,即通过代理访问目标对象,这样的好处是,可以在目标对象的基础上,增强额外的功能操作,扩展目标对象的功能。

    举例:明星(邓紫棋)<-----经纪人<------用户

         目标对象              代理对象

    静态代理(一般不用)

    • 代理对象要实现与目标对象一样的接口
    • 可以做到在不修改目标对象的功能前提下,对目标对象功能进行扩展
    • 缺点
      • 因为代理对象,需要与目标对象实现一样的接口,所有会有很多代理类,
      • 一旦接口增加方法,目标对象与代理对象都要维护
     1 package cn.fuyi.a_static;
     2 
     3 public interface IUserDao {
     4     void save();
     5 }
     6 
     7 package cn.fuyi.a_static;
     8 
     9 public class UserDao implements IUserDao{
    10 
    11     public void save() {
    12         System.out.println("=====已经保存数据====-");
    13     }
    14 }
    15 
    16 package cn.fuyi.a_static;
    17 
    18 public class UserProxy implements IUserDao{
    19 
    20     private IUserDao target;
    21     public UserProxy(IUserDao target) {
    22         this.target = target;
    23     }
    24     
    25     @Override
    26     public void save() {
    27         System.out.println("开始事务");
    28         target.save();
    29         System.out.println("提交事务");
    30     }
    31 
    32 }
    33 
    34 
    35 package cn.fuyi.a_static;
    36 
    37 import static org.junit.Assert.*;
    38 
    39 import org.junit.Test;
    40 
    41 public class App {
    42 
    43     @Test
    44     public void testStaticProxy() throws Exception {
    45         //目标对象
    46         IUserDao userDao = new UserDao();
    47         
    48         //代理对象
    49         IUserDao userDaoProxy = new UserProxy(userDao);
    50         
    51         userDaoProxy.save();
    52     }
    53 }
    54 
    55 
    56 /**Output
    57    开启事务
    58    =====已经保存数据====-
    59    关闭事务
    60  
    61     
    62 */
    View Code

     

    动态代理

    • 代理对象不需要实现接口
    • 目标对象一定要实现接口
    • 代理对象的生成是利用JDKAPI,动态的在内存中构建代理对象(需要我们指定目标对象实现的接口)
    • 也称JDK代理,接口代理
    • JDK中生成代理对象的API 

    static Object newProxyInstance(

      ClassLoader loader,             指定当前目标对象使用的类加载器

       Class<?>[] interfaces,        目标对象实现的接口的类型

      InvocationHandler h)           事件处理器

     1 package cn.fuyi.b_dynamic;
     2 
     3 public interface IUserDao {
     4     void save();
     5 }
     6 
     7 package cn.fuyi.b_dynamic;
     8 
     9 public class UserDao implements IUserDao{
    10 
    11     public void save() {
    12         System.out.println("=====已经保存数据====-");
    13     }
    14 }
    15 
    16 package cn.fuyi.b_dynamic;
    17 
    18 import java.lang.reflect.InvocationHandler;
    19 import java.lang.reflect.Method;
    20 import java.lang.reflect.Proxy;
    21 
    22 public class ProxyFactory {
    23 
    24     private Object target;
    25     public ProxyFactory(Object target) {
    26         this.target = target;
    27     }
    28     
    29     public Object getProxyInstance() {
    30         return Proxy.newProxyInstance(target.getClass().getClassLoader(), 
    31                 target.getClass().getInterfaces(), 
    32                 new InvocationHandler() {
    33                     
    34                     @Override
    35                     public Object invoke(Object proxy, Method method, Object[] args)
    36                             throws Throwable {
    37                         System.out.println("开启事务");
    38                         
    39                         //执行目标对象的方法
    40                         Object returnValue = method.invoke(target, args);
    41                             
    42                         System.out.println("关闭事务");
    43                         return returnValue;
    44                     }
    45                 });
    46     }
    47 }
    48 
    49 package cn.fuyi.b_dynamic;
    50 
    51 import static org.junit.Assert.*;
    52 
    53 import org.junit.Test;
    54 
    55 public class App {
    56 
    57     @Test
    58     public void testDynamicProxy() throws Exception {
    59         //目标对象
    60         IUserDao target = new UserDao();
    61         
    62         //代理对象
    63         IUserDao proxy = (IUserDao) new ProxyFactory(target).getProxyInstance();
    64         
    65         proxy.save();
    66     }
    67 }
    68 
    69 /***
    70    开启事务
    71    =====已经保存数据====-
    72    关闭事务
    73  
    74 */
    View Code

     

    Cglib代理

    • Cglib代理,也叫作子类代理,在内存中构建一个子类对象从而实现对目标对象功能的扩展
    • JDK的动态代理有一个限制,就是使用动态代理的对象必须实现一个或多个接口,如果想代理没有实现接口的类,就可以用cglib实现
    • Cglib是一个强大的高性能的代码生成包,它可以在运行期间扩展Java类与实现Java接口,它广泛的被许多AOP的框架使用,如:spring AOP,为他们提供方法的interception(拦截);
    • Cglib包的底层通过使用一个小而快的字节码处理框架ASM,来装换字节码并生成新的类,不鼓励直接使用ASM,因为它要求你必须对JVM内部结构包括class文件的格式和指令集都很熟悉
    • spring-Core中包含了cglibg功能
    • 目标对象不能为final
    • 目标对象的方法如果为final/static,那么就不会别拦截,即不会执行目标对象额外的业务方法
    • 在spring的AOP编程中
      • 如果加入容器的目标对象有实现接口,就用JDK代理
      • 如果目标对象没有实现接口,就用Cglib代理
         1 package cn.fuyi.c_cglib;
         2 
         3 public class UserDao {
         4 
         5     public void save() {
         6         System.out.println("=====已经保存数据====-");
         7     }
         8 }
         9 
        10 package cn.fuyi.c_cglib;
        11 
        12 import java.lang.reflect.InvocationHandler;
        13 import java.lang.reflect.Method;
        14 import java.lang.reflect.Proxy;
        15 
        16 import org.springframework.cglib.proxy.Enhancer;
        17 import org.springframework.cglib.proxy.MethodInterceptor;
        18 import org.springframework.cglib.proxy.MethodProxy;
        19 
        20 public class ProxyFactory implements MethodInterceptor{
        21 
        22     private Object target;
        23     public ProxyFactory(Object target) {
        24         this.target = target;
        25     }
        26     
        27     public Object getProxyInstance() {
        28         //1.工具类
        29         Enhancer enhancer = new Enhancer();
        30         
        31         //2.设置父类,即目标对象
        32         enhancer.setSuperclass(target.getClass());
        33         
        34         //3.设置回调对象,即实现MethodInterceptor的类的对象
        35         enhancer.setCallback(this);
        36         
        37         //4.创建子类
        38         return enhancer.create();
        39     }
        40 
        41     @Override
        42     public Object intercept(Object obj, Method method, Object[] args,
        43             MethodProxy proxy) throws Throwable {
        44 
        45         System.out.println("开启事务");
        46         
        47         //执行目标对象的方法
        48         Object returnValue = method.invoke(target, args);
        49         
        50         System.out.println("提交事务");
        51         return returnValue;
        52     }
        53 }
        54 
        55 package cn.fuyi.c_cglib;
        56 
        57 import static org.junit.Assert.*;
        58 
        59 import org.junit.Test;
        60 
        61 public class App {
        62 
        63     @Test
        64     public void testDynamicProxy() throws Exception {
        65         //目标对象
        66         UserDao target = new UserDao();
        67         System.out.println(target.getClass());
        68         
        69         //代理对象
        70         UserDao proxy = (UserDao) new ProxyFactory(target).getProxyInstance();
        71         System.out.println(proxy.getClass());
        72         
        73         proxy.save();
        74     }
        75 }
        76 
        77 /***Output
        78 class cn.fuyi.c_cglib.UserDao
        79 class cn.fuyi.c_cglib.UserDao$$EnhancerByCGLIB$$b9ff5e0
        80 开启事务
        81 =====已经保存数据====-
        82 提交事务
        83 
        84 */
        View Code
  • 相关阅读:
    C语言I博客作业09
    请看这里
    C++ 面向对象学习笔记[1]
    graphviz的使用
    KDE安装后的一些随笔
    近期内容整理
    链表
    理解C++ lvalue与rvalue
    再看“笕实智慧校园”——作品的复盘[1]
    无题
  • 原文地址:https://www.cnblogs.com/fuyiming/p/5828717.html
Copyright © 2011-2022 走看看