zoukankan      html  css  js  c++  java
  • java--动态代理设计模式,CGLIB实现的动态代理设计模式

    代理设计模式
    代理设计模式的基本形式
    代理设计模式的核心思路,一个接口两个子类,一个子类完成核心业务操作,另一个完成与核心业务有关的辅助性操作。例如,编写一个简单的设计模式。
    package com.hbsi.test;
    interface Food{
    public void eat();
    }
    class ProxyFood implements Food{
    private Food food;
    public ProxyFood(Food food) {
    this.food = food;
    }
    public void after() {
    System.out.println("饭后");
    }
    public void before() {
    System.out.println("饭前");
    }
    @Override
    public void eat() {
    this.after();
    this.food.eat();//调用RealFood中的eat方法
    this.before();
    }
    }
    class RealFood implements Food{
    @Override
    public void eat() {
    System.out.println("吃饭 ,,,,,RealFood");
    }
    }
    public class ProxyDemo {
    public static void main(String[] args) {
    Food f = new ProxyFood(new RealFood());
    f.eat();
    }
    }

     在什么情况下代理设计模式可能会被使用?最常用的形式就是在系统日志上进行,

     
    动态代理类
    传统的代理模式都是一个接口两个子类,一个是真实主题类,另一个是代理类,这样就导致了,一个代理类只能为一个接口服务,所以在java中提供了动态代理的支持。
    如果要实现动态代理类,必须采用InvocationHandle接口处理。
    此接口中定义了一个invoke方法:
    Object invoke​(Object proxy, Method method, Object[] args) throws Throwable
    处理代理实例上的方法调用并返回结果。
    在这个invoke方法里面接受的参数如下,
    1. proxy:代理的对象,
    2. method:表示真实主题要调用的执行方法;
    3. args:调用方法时所传递的参数
    而在invoke'方法里面会返回一个Object的数据,这个数据就是调用方法时,返回的结果
    但是所哟的真实主体累,都需要返回一个代理类对象,而这个代理类对象都由Proxy类完成,在Proxy类中的一个操作方法:
    返回指定接口的代理实例,该代理实例将方法调用分派给指定的调用处理程序。
    在此方法中有以下参数:
    loader :返回目标对象的类加载器;读取要代理类的代码,重新实例化一个新的
    interfaces:返回一个类实现的所有接口
    h:InvocationHandler 接口对象,完成真正的代理操作。
    代码示例:建立一个动态代理类
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    public class MyProxyd implements InvocationHandler{
    private Object target;//要代理的对象信息
    public Object bind(Object target) {
    this.target = target;//赋值
    //返回与当前传入对象结构相同的代理类对象
    return Proxy.newProxyInstance(target.getClass().getClassLoader(),
    target.getClass().getInterfaces() , this);
    }
    @Override//参数说明:代理的对象。表示真实主体类要执行的方法。方法需要的参数
    public Object invoke(Object proxy, Method method, Object[] arg) throws Throwable {
    this.log();
    Object invoke = method.invoke(this.target, arg);//调用真实类的方法
    this.commit();
    return invoke;
    }
    private void log() {
    System.out.println("执行记录日志方法");
    }
    private void commit() {
    System.out.println("事务提交");
    }
    public static void main(String[] args) {
    Food f = (Food) new MyProxyd().bind(new RealFood());
    f.eat();
    }
    }
    public class RealFood implements Food{
    @Override
    public void eat() {
    System.out.println("吃饭 ,,,,,RealFood");
    }
    }
     
     

     

    CGLIB代理模式、
    从标准的代理设计模式来讲,一定要有借口,而且通过之前的动态代理也可以发现,如果想要去的代理类对象,就必须传入接口。
    return Proxy.newProxyInstance(target.getClass().getClassLoader(),
    target.getClass().getInterfaces() , this);
    使用Proxy必须传入所有接口,否则代理不能使用。为了解决java动态代理的必须需要接口的弊端,CGLIB可以解决此问题。
    cglib包中需要使用以下几个类:
    1. net.sf.cglib.proxy.Enhancer,相当于 Proxy 功能,返回代理对象
    2. net.sf.cglib.proxy.MethodInterceptor接口:处理一个代理操作的接口
    3. net.sf.cglib.proxy.MethodProxy:代替之前的Method类的功能
    代码范例:基于类实现的动态代理设计模式
    import java.lang.reflect.Method;
    import net.sf.cglib.proxy.Enhancer;
    import net.sf.cglib.proxy.MethodInterceptor;
    import net.sf.cglib.proxy.MethodProxy;
    class PrintMes {
    public void print() {
    System.out.println("吃饭 ,,,,,");
    }
    }
    public class CGLIBProxy {
    public static void main(String[] args) {
    PrintMes mes = new PrintMes();//
    Enhancer enhancer = new Enhancer();//代理类对象
    enhancer.setSuperclass(mes.getClass());//为代理类设置一个父类,自我理解就是做关联
    enhancer.setCallback(new MethodInterceptor() {
    @Override
    public Object intercept(Object obj, Method method, Object[] objs, MethodProxy proxy) throws Throwable {
    System.out.println("饭前洗手");
    return method.invoke(mes, args);
    }
    });
    PrintMes create = (PrintMes) enhancer.create();//返回代理对象
    create.print();//调用
    }
    }
  • 相关阅读:
    IEC61850标准化逻辑节点组
    获取类成员函数地址和通过成员函数地址调用对应成员函数
    [转]什么是差动保护
    IEC61850概述
    window下使用mingw编译vlc2.1.0git
    Code::Blocks集成Cygwin的使用
    [STL] 注意erase() 和remove()
    C# 调用C++DLL传递指向指针的指针参数的方法
    Boost的使用相关
    在window下qt开发环境
  • 原文地址:https://www.cnblogs.com/wzqjy/p/7819492.html
Copyright © 2011-2022 走看看