设计模式 - 代理模式

一、代理模式模式

1、代理模式模式的定义

代理模式(Proxy Pattern)定义:指为其他对象提供一种代理,以控制对这个对象的访问,属于结构型设计模式。

在某些情况下,访问对象不适合或者不能直接引用目标对象,这时,可以通过代理对象来间接控制对该对象的访问,而代理对象可以在访问对象和目标对象之间起到中介的作用。

使用代理模式的主要目的:

  • 保护目标对象
  • 增强目标对象

2、代理模式模式的结构

(1)模式的结构

代理模式的主要角色如下。

  • 抽象主题(Subject)类:主要职责是声明真实主题与代理的共同接口方法,该类可以是接口,也可以是类。
  • 真实主题(RealSubject)类:该类也被称为被代理类,实现了抽象主题中的具体业务,是代理对象所代表的真实对象,是最终要引用的对象。
  • 代理主题(Proxy)类:该类也被称为代理类,提供了与真实主题相同的接口,其内部含有对真实主题的引用,它可以访问、控制或扩展真实主题的功能。
  •  

在代码中,一般代理会被理解为代码增强,实际上就是在原代码逻辑前后增加一些代码逻辑,而使调用者无感知。

根据代理的创建时期,代理模式分为静态代理和动态代理。

  • 静态代理:由程序员创建代理类或特定工具自动生成源代码再对其编译,在程序运行前代理类的 .class 文件就已经存在了。
  • 动态代理:在程序运行时,运用反射机制动态创建而成

(2)结构图如下:(图来自网络)

3、优缺点

代理模式的主要优点有:

  • 代理模式在客户端与目标对象之间起到一个中介作用和保护目标对象的作用;
  • 代理对象可以扩展目标对象的功能;
  • 代理模式能将客户端与目标对象分离,在一定程度上降低了系统的耦合度,增加了程序的可扩展性

其主要缺点是:

  • 代理模式会造成系统设计中类的数量增加
  • 在客户端和目标对象之间增加一个代理对象,会造成请求处理速度变慢;
  • 增加了系统的复杂度;

那么如何解决以上提到的缺点呢?答案是可以使用动态代理方式

4、使用场景

  • 远程代理,这种方式通常是为了隐藏目标对象存在于不同地址空间的事实,方便客户端访问。例如,用户申请某些网盘空间时,会在用户的文件系统中建立一个虚拟的硬盘,用户访问虚拟硬盘时实际访问的是网盘空间。
  • 虚拟代理,这种方式通常用于要创建的目标对象开销很大时。例如,下载一幅很大的图像需要很长时间,因某种计算比较复杂而短时间无法完成,这时可以先用小比例的虚拟代理替换真实的对象,消除用户对服务器慢的感觉。
  • 安全代理,这种方式通常用于控制不同种类客户对真实对象的访问权限。
  • 智能指引,主要用于调用目标对象时,代理附加一些额外的处理功能。例如,增加计算真实对象的引用次数的功能,这样当该对象没有被引用时,就可以自动释放它。
  • 延迟加载,指为了提高系统的性能,延迟对目标的加载。例如,Hibernate 中就存在属性的延迟加载和关联表的延时加载。

5、模式的通用实现

代码如下:

public class ProxyPattern {
    public static void main(String[] args) {
        Proxy proxy = new Proxy();
        proxy.Request();
    }
}
//抽象主题
interface Subject {
    void Request();
}
//真实主题
class RealSubject implements Subject {
    @Override
    public void Request() {
        System.out.println("访问真实主题方法...");
    }
}
//代理
class Proxy implements Subject {
    private RealSubject realSubject;
    @Override
    public void Request() {
        if (realSubject == null) {
            realSubject = new RealSubject();
        }
        preRequest();
        realSubject.Request();
        postRequest();
    }
    public void preRequest() {
        System.out.println("访问真实主题之前的预处理。");
    }
    public void postRequest() {
        System.out.println("访问真实主题之后的后续处理。");
    }
}

 

下面代码主要是对真实类的方法做事务增强,方法没有做具体的业务实现。

一、静态代理

      静态代理:由程序员创建或特定工具自动生成源代码并对其编译。在程序运行之前,就已经存在代理类的字节码文件(代理类.class),代理对象和真实对象的关系也已经确定了。

      静态代理在使用时,需要定义接口或者父类,被代理对象与代理对象一起实现相同的接口或者是继承相同的父类。

1、正常创建model、dao 和 service 

UserDao类

public class UserDao implements IUserDao {
    @Override
    public void save(User user) {
        System.out.println("保存用户");
    }

    @Override
    public void update(User user) {
        System.out.println("修改用户");
    }

    @Override
    public List<User> listAll() {
        System.out.println("查询所有");
        return new ArrayList<>();
    }
}

UserServiceImpl类

public class UserServiceImpl implements IUserService {
    private UserDao userDao;

    public UserServiceImpl() {
    }

    public UserServiceImpl(UserDao userDao) {
        this.userDao = userDao;
    }

    @Override
    public void save(User user) {
        userDao.save(user);
        System.out.println("保存成功");
    }

    @Override
    public void update(User user) {
        userDao.update(user);
        throw new RuntimeException("修改失败");
    }

    @Override
    public List<User> listAll() {
        System.out.println("查询成功");
        return userDao.listAll();
    }
}

2、创建事务的处理类和代理类

MyTransctionManager类

//模拟事务管理器
public class MyTransctionManager {
    public void begin() {
        System.out.println("开启事务");
    }

    public void commit() {
        System.out.println("提交事务");
    }

    public void cloce() {
        System.out.println("关闭事务");
    }

    public void rollback() {
        System.out.println("回滚事务");
    }
}

UserServiceProxy类

public class UserServiceProxy implements IUserService{
    private IUserService target; //真实对象
    private MyTransctionManager txManager; //事务管理器

    public UserServiceProxy(IUserService target, MyTransctionManager txManager) {
        this.target = target;
        this.txManager = txManager;
    }

    @Override
    public void save(User user) {
        txManager.begin();
        try {
            target.save(user);
            txManager.commit();
        } catch (Exception e) {
            e.printStackTrace();
            txManager.rollback();
        } finally {
            txManager.cloce();
        }
    }

    @Override
    public void update(User user) {
        txManager.begin();
        try {
            target.update(user);
            txManager.commit();
        } catch (Exception e) {
            e.printStackTrace();
            txManager.rollback();
        } finally {
            txManager.cloce();
        }
    }

    @Override
    public List<User> listAll() {
        return target.listAll();
    }
}

3、测试

public class App {
    public static void main(String[] args) {
        testNoProxy();
        testProxy();
    }

    // 使用静态代理
    private static void testProxy() {
        User user = new User();
        //属性注入,多态
        IUserService userService = new UserServiceProxy(new UserServiceImpl(new UserDao()), new MyTransctionManager());

        userService.save(user);
        System.out.println("==========");
        userService.update(user);
        System.out.println("==========");
        userService.listAll();
    }

    // 未使用代理
    private static void testNoProxy() {
        User user = new User();
        IUserService userService = new UserServiceImpl(new UserDao());

        userService.save(user);
        System.out.println("==========");
        userService.update(user);
        System.out.println("==========");
        userService.listAll();
    }
}

4、静态代理总结

     优点:可以做到在符合开闭原则(软件组成实体应该是可扩展的, 但是不可修改)的情况下对目标对象进行功能扩展。

     缺点:我们得为每一个服务都得创建代理类,工作量太大,不易管理。同时接口一旦发生改变,代理类也得相应修改。

二、动态代理

      动态代理:动态代理类是在程序运行期间由JVM通过反射等机制动态创建生成的,所以不存在代理类的字节码文件,代理对象和真实对象的关系是在程序运行时期才确定的。

动态代理的实现方式:

    1)针对有接口的类:使用JDK动态代理,也叫接口动态代理

    2)针对没有接口的类:使用CGLIB动态代理或者Javassist组件

如何动态的加载一份字节码:

     由于JVM通过字节码的二进制信息加载类的,如果我们在运行期系统中,遵循Java编译系统组织的 .class文件的格式和结构,生成相应的二进制数据,然后再把这个二进制数据加载转换为对应的类,所以,就可完成在代码中动态创建一个类的能力。

1、JDK动态代理

      要实现基于JDK动态代理,必须要求真实对象要有实现的接口,同时需要理解JDK中的 java.lang.reflect.Proxy类java.lang.reflect.InvocationHandler接口。

Proxy 类提供了创建动态代理类及其对象的静态方法,它也是由这些方法创建的所有动态代理类的父类。

参数
    loader - 类加载器来定义代理类,一般传递真实对象的类加载器
    interfaces - 代理类需要实现的接口列表
    handler - 代理对象调用的增强处理方法

 

InvocationHandler 接口是通用处理器接口,是由代理实例的调用处理程序实现的接口

参数
    proxy - 生成的代理对象
    method - 当前调用的真实方法对象
    args - 当前调用真实方法的实参

 

JDK动态代理使用步骤

1)新建一个接口,并为该接口创建一个实现类

2)创建自己需要增强的代码处理器,实现 InvocationHandler接口,并提供一个创建动态代理对象的方法

3)获取动态代理对象,测试

实例:

1)model、dao、service 和事务的处理类同上,然后创建增强的代码处理器类

JDKTransctionManagerAdvice类

import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class JDKTransctionManagerAdvice implements java.lang.reflect.InvocationHandler {
    private Object target; //真实对象(对谁做增强)
    private MyTransctionManager txManager; //事务管理器(模拟)

    public void setTarget(Object target) {
        this.target = target;
    }

    public void setTxManager(MyTransctionManager txManager) {
        this.txManager = txManager;
    }

    //为真实对象的方法做增强的具体操作
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("==" + proxy.getClass()); //class com.sun.proxy.$Proxy0

        if (method.getName().startsWith("get") || method.getName().startsWith("list")) {
            return method.invoke(target, args); //放行
        }

        Object ret = null;
        txManager.begin();
        try {
            ret = method.invoke(target, args); //调用真实对象的方法
            txManager.commit();
        } catch (Exception e) {
            e.printStackTrace();
            txManager.rollback();
        } finally {
            txManager.cloce();
        }
        return ret;
    }

    //创建一个代理对象
    public <T> T getProxyObject() {
        return (T) Proxy.newProxyInstance(target.getClass().getClassLoader(), //类加载器,一般跟上真实对象的类加载器
                target.getClass().getInterfaces(), //真实对象所实现的接口(JDK动态代理必须要求真实对象有接口)
                this);//做事务增强的对象,InvocationHandler子类,多态
    }
}

2)测试

public class App {
    public static void main(String[] args) {
        JDKProxy();
    }

    //JDK代理对象:class com.sun.proxy.$Proxy0
    private static void JDKProxy() {
        User user = new User();
        IUserService userService = new UserServiceImpl(new UserDao());
        JDKTransctionManagerAdvice advice = new JDKTransctionManagerAdvice();
        advice.setTarget(userService);
        advice.setTxManager(new MyTransctionManager());

        IUserService proxyObject = advice.getProxyObject();
        System.out.println(proxyObject.getClass()); //
//        proxyObject.save(user);
        System.out.println("==========");
        proxyObject.update(user);
        System.out.println("==========");
//        proxyObject.listAll();
    }

JDK动态代理原理

    通过 DynamicProxyClassGenerator类生产动态代理的字节码文件,在通过反编译工具生成java文件查看

DynamicProxyClassGenerator类

import sun.misc.ProxyGenerator;

public class DynamicProxyClassGenerator {
	public static void main(String[] args) throws Exception {
		generateClassFile(UserServiceImpl.class, "UserServiceProxy");
	}

	//生成代理类的字节码文件-->Java反编译工具-->Java文件
	public static void generateClassFile(Class targetClass, String proxyName) throws Exception {
		//根据类信息和提供的代理类名称,生成字节码  
		byte[] classFile = ProxyGenerator.generateProxyClass(proxyName, targetClass.getInterfaces());
		String path = targetClass.getResource(".").getPath();
		System.out.println(path);
		FileOutputStream out = null;
		//保留到硬盘中  
		out = new FileOutputStream(path + proxyName + ".class");
		out.write(classFile);
		out.close();
	}
}

反编译生成的UserServiceProxy类

import cn.jq.springdemo.model.User;
import cn.jq.springdemo.service.IUserService;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;
import java.util.List;

public final class UserServiceProxy extends Proxy implements IUserService {
    private static Method m1;
    private static Method m2;
    private static Method m3;
    private static Method m4;
    private static Method m5;
    private static Method m0;

    public UserServiceProxy(InvocationHandler var1) throws  {
        super(var1);
    }

    public final boolean equals(Object var1) throws  {
        try {
            return (Boolean)super.h.invoke(this, m1, new Object[]{var1});
        } catch (RuntimeException | Error var3) {
            throw var3;
        } catch (Throwable var4) {
            throw new UndeclaredThrowableException(var4);
        }
    }

    public final String toString() throws  {
        try {
            return (String)super.h.invoke(this, m2, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    public final void update(User var1) throws  {
        try {
            super.h.invoke(this, m3, new Object[]{var1});
        } catch (RuntimeException | Error var3) {
            throw var3;
        } catch (Throwable var4) {
            throw new UndeclaredThrowableException(var4);
        }
    }

    public final void save(User var1) throws  {
        try {
            super.h.invoke(this, m4, new Object[]{var1});
        } catch (RuntimeException | Error var3) {
            throw var3;
        } catch (Throwable var4) {
            throw new UndeclaredThrowableException(var4);
        }
    }

    public final List listAll() throws  {
        try {
            return (List)super.h.invoke(this, m5, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    public final int hashCode() throws  {
        try {
            return (Integer)super.h.invoke(this, m0, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    static {
        try {
            m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
            m2 = Class.forName("java.lang.Object").getMethod("toString");
            m3 = Class.forName("cn.jq.springdemo.service.IUserService").getMethod("update", Class.forName("cn.jq.springdemo.model.User"));
            m4 = Class.forName("cn.jq.springdemo.service.IUserService").getMethod("save", Class.forName("cn.jq.springdemo.model.User"));
            m5 = Class.forName("cn.jq.springdemo.service.IUserService").getMethod("listAll");
            m0 = Class.forName("java.lang.Object").getMethod("hashCode");
        } catch (NoSuchMethodException var2) {
            throw new NoSuchMethodError(var2.getMessage());
        } catch (ClassNotFoundException var3) {
            throw new NoClassDefFoundError(var3.getMessage());
        }
    }
}

可看到

1)代理类继承了 Proxy类并且实现了要代理的接口,由于java不支持多继承,所以JDK动态代理不能代理类

2)重写了equals、hashCode、toString

3)有一个静态代码块,通过反射或者代理类的所有方法

4)通过invoke执行代理类中的目标方法doSomething

 

2、CGLib动态代理

     JDK动态代理需要实现类通过接口定义业务方法,对于没有接口的类,就可以使用CGLib动态代理

实例:

1)创建无接口的service 类和事务的处理类同上,然后创建增强的代码处理器类

 UserServiceImpl2类 无接口

public class UserServiceImpl2 {
    private UserDao userDao;

    public UserServiceImpl2() {
    }

    public UserServiceImpl2(UserDao userDao) {
        this.userDao = userDao;
    }

    public void save(User user) {
        userDao.save(user);
        System.out.println("保存成功");
    }

    public void update(User user) {
        userDao.update(user);
        throw new RuntimeException("修改失败");
    }

    public List<User> listAll() {
        System.out.println("查询成功");
        return userDao.listAll();
    }
}

 CGLIBTransctionManagerAdvice类

import org.springframework.cglib.proxy.Enhancer;
import java.lang.reflect.Method;

public class CGLIBTransctionManagerAdvice implements org.springframework.cglib.proxy.InvocationHandler {
    private Object target; //真实对象(对谁做增强)
    private MyTransctionManager txManager; //事务管理器(模拟)

    public void setTarget(Object target) {
        this.target = target;
    }

    public void setTxManager(MyTransctionManager txManager) {
        this.txManager = txManager;
    }

    //如何为真实对象的方法做增强的具体操作
    @Override
    public Object invoke(Object o, Method method, Object[] args) throws Throwable {
        if (method.getName().startsWith("get") || method.getName().startsWith("list")) {
            return method.invoke(target, args); //放行
        }

        Object ret = null;
        txManager.begin();
        try {
            ret = method.invoke(target, args); //调用真实对象的方法
            txManager.commit();
        } catch (Exception e) {
            e.printStackTrace();
            txManager.rollback();
        } finally {
            txManager.cloce();
        }
        return ret;
    }

    //创建一个代理对象
    public <T> T getProxyObject() {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(target.getClass());//将继承于哪一个类,去做增强
        enhancer.setCallback(this);//设置增强的对象
        return (T) enhancer.create();//创建代理对象
    }
}

2)测试

public class App {
    public static void main(String[] args) {
        CGLIBProxy();
    }

    //CGLIB代理对象:class cn.jq.springdemo.service.impl.UserServiceImpl2$$EnhancerByCGLIB$$45b44dc4
    private static void CGLIBProxy() {
//        生成字节码文件    
//        System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY,"E:/Lei");
        User user = new User();
        CGLIBTransctionManagerAdvice advice = new CGLIBTransctionManagerAdvice();
        advice.setTarget(new UserServiceImpl2(new UserDao()));
        advice.setTxManager(new MyTransctionManager());

        UserServiceImpl2 proxyObject = advice.getProxyObject();
        System.out.println(proxyObject.getClass()); //
        proxyObject.save(user);
        System.out.println("==========");
        proxyObject.update(user);
        System.out.println("==========");
        proxyObject.listAll();
    }
}

CGLib动态代理原理

    动态代理的字节码文件反编译之后的 java文件

package cn.jq.springdemo.service.impl;

import cn.jq.springdemo.dao.impl.UserDao;
import cn.jq.springdemo.model.User;
import java.lang.reflect.Method;
import java.util.List;
import org.springframework.cglib.proxy.Callback;
import org.springframework.cglib.proxy.Factory;
import org.springframework.cglib.proxy.InvocationHandler;
import org.springframework.cglib.proxy.UndeclaredThrowableException;

public class UserServiceImpl2$$EnhancerByCGLIB$$45b44dc4 extends UserServiceImpl2 implements Factory {
    private boolean CGLIB$BOUND;
    public static Object CGLIB$FACTORY_DATA;
    private static final ThreadLocal CGLIB$THREAD_CALLBACKS;
    private static final Callback[] CGLIB$STATIC_CALLBACKS;
    private InvocationHandler CGLIB$CALLBACK_0;
    private static Object CGLIB$CALLBACK_FILTER;
    private static final Method CGLIB$update$0;
    private static final Method CGLIB$save$1;
    private static final Method CGLIB$listAll$2;
    private static final Method CGLIB$equals$3;
    private static final Method CGLIB$toString$4;
    private static final Method CGLIB$hashCode$5;
    private static final Method CGLIB$clone$6;

    static void CGLIB$STATICHOOK1() {
        CGLIB$THREAD_CALLBACKS = new ThreadLocal();
        CGLIB$update$0 = Class.forName("cn.jq.springdemo.service.impl.UserServiceImpl2").getDeclaredMethod("update", Class.forName("cn.jq.springdemo.model.User"));
        CGLIB$save$1 = Class.forName("cn.jq.springdemo.service.impl.UserServiceImpl2").getDeclaredMethod("save", Class.forName("cn.jq.springdemo.model.User"));
        CGLIB$listAll$2 = Class.forName("cn.jq.springdemo.service.impl.UserServiceImpl2").getDeclaredMethod("listAll");
        CGLIB$equals$3 = Class.forName("java.lang.Object").getDeclaredMethod("equals", Class.forName("java.lang.Object"));
        CGLIB$toString$4 = Class.forName("java.lang.Object").getDeclaredMethod("toString");
        CGLIB$hashCode$5 = Class.forName("java.lang.Object").getDeclaredMethod("hashCode");
        CGLIB$clone$6 = Class.forName("java.lang.Object").getDeclaredMethod("clone");
    }

    public final void update(User var1) {
        try {
            InvocationHandler var10000 = this.CGLIB$CALLBACK_0;
            if (var10000 == null) {
                CGLIB$BIND_CALLBACKS(this);
                var10000 = this.CGLIB$CALLBACK_0;
            }

            var10000.invoke(this, CGLIB$update$0, new Object[]{var1});
        } catch (Error | RuntimeException var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    public final void save(User var1) {
        try {
            InvocationHandler var10000 = this.CGLIB$CALLBACK_0;
            if (var10000 == null) {
                CGLIB$BIND_CALLBACKS(this);
                var10000 = this.CGLIB$CALLBACK_0;
            }

            var10000.invoke(this, CGLIB$save$1, new Object[]{var1});
        } catch (Error | RuntimeException var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    public final List listAll() {
        try {
            InvocationHandler var10000 = this.CGLIB$CALLBACK_0;
            if (var10000 == null) {
                CGLIB$BIND_CALLBACKS(this);
                var10000 = this.CGLIB$CALLBACK_0;
            }

            return (List)var10000.invoke(this, CGLIB$listAll$2, new Object[0]);
        } catch (Error | RuntimeException var1) {
            throw var1;
        } catch (Throwable var2) {
            throw new UndeclaredThrowableException(var2);
        }
    }

    public final boolean equals(Object var1) {
        try {
            InvocationHandler var10000 = this.CGLIB$CALLBACK_0;
            if (var10000 == null) {
                CGLIB$BIND_CALLBACKS(this);
                var10000 = this.CGLIB$CALLBACK_0;
            }

            return (Boolean)var10000.invoke(this, CGLIB$equals$3, new Object[]{var1});
        } catch (Error | RuntimeException var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    public final String toString() {
        try {
            InvocationHandler var10000 = this.CGLIB$CALLBACK_0;
            if (var10000 == null) {
                CGLIB$BIND_CALLBACKS(this);
                var10000 = this.CGLIB$CALLBACK_0;
            }

            return (String)var10000.invoke(this, CGLIB$toString$4, new Object[0]);
        } catch (Error | RuntimeException var1) {
            throw var1;
        } catch (Throwable var2) {
            throw new UndeclaredThrowableException(var2);
        }
    }

    public final int hashCode() {
        try {
            InvocationHandler var10000 = this.CGLIB$CALLBACK_0;
            if (var10000 == null) {
                CGLIB$BIND_CALLBACKS(this);
                var10000 = this.CGLIB$CALLBACK_0;
            }

            return ((Number)var10000.invoke(this, CGLIB$hashCode$5, new Object[0])).intValue();
        } catch (Error | RuntimeException var1) {
            throw var1;
        } catch (Throwable var2) {
            throw new UndeclaredThrowableException(var2);
        }
    }

    protected final Object clone() throws CloneNotSupportedException {
        try {
            InvocationHandler var10000 = this.CGLIB$CALLBACK_0;
            if (var10000 == null) {
                CGLIB$BIND_CALLBACKS(this);
                var10000 = this.CGLIB$CALLBACK_0;
            }

            return var10000.invoke(this, CGLIB$clone$6, new Object[0]);
        } catch (Error | CloneNotSupportedException | RuntimeException var1) {
            throw var1;
        } catch (Throwable var2) {
            throw new UndeclaredThrowableException(var2);
        }
    }

    public UserServiceImpl2$$EnhancerByCGLIB$$45b44dc4() {
        CGLIB$BIND_CALLBACKS(this);
    }

    public UserServiceImpl2$$EnhancerByCGLIB$$45b44dc4(UserDao var1) {
        super(var1);
        CGLIB$BIND_CALLBACKS(this);
    }

    public static void CGLIB$SET_THREAD_CALLBACKS(Callback[] var0) {
        CGLIB$THREAD_CALLBACKS.set(var0);
    }

    public static void CGLIB$SET_STATIC_CALLBACKS(Callback[] var0) {
        CGLIB$STATIC_CALLBACKS = var0;
    }

    private static final void CGLIB$BIND_CALLBACKS(Object var0) {
        UserServiceImpl2$$EnhancerByCGLIB$$45b44dc4 var1 = (UserServiceImpl2$$EnhancerByCGLIB$$45b44dc4)var0;
        if (!var1.CGLIB$BOUND) {
            var1.CGLIB$BOUND = true;
            Object var10000 = CGLIB$THREAD_CALLBACKS.get();
            if (var10000 == null) {
                var10000 = CGLIB$STATIC_CALLBACKS;
                if (var10000 == null) {
                    return;
                }
            }

            var1.CGLIB$CALLBACK_0 = (InvocationHandler)((Callback[])var10000)[0];
        }

    }

    public Object newInstance(Callback[] var1) {
        CGLIB$SET_THREAD_CALLBACKS(var1);
        UserServiceImpl2$$EnhancerByCGLIB$$45b44dc4 var10000 = new UserServiceImpl2$$EnhancerByCGLIB$$45b44dc4();
        CGLIB$SET_THREAD_CALLBACKS((Callback[])null);
        return var10000;
    }

    public Object newInstance(Callback var1) {
        CGLIB$SET_THREAD_CALLBACKS(new Callback[]{var1});
        UserServiceImpl2$$EnhancerByCGLIB$$45b44dc4 var10000 = new UserServiceImpl2$$EnhancerByCGLIB$$45b44dc4();
        CGLIB$SET_THREAD_CALLBACKS((Callback[])null);
        return var10000;
    }

    public Object newInstance(Class[] var1, Object[] var2, Callback[] var3) {
        CGLIB$SET_THREAD_CALLBACKS(var3);
        UserServiceImpl2$$EnhancerByCGLIB$$45b44dc4 var10000 = new UserServiceImpl2$$EnhancerByCGLIB$$45b44dc4;
        switch(var1.length) {
        case 0:
            var10000.<init>();
            break;
        case 1:
            if (var1[0].getName().equals("cn.jq.springdemo.dao.impl.UserDao")) {
                var10000.<init>((UserDao)var2[0]);
                break;
            }

            throw new IllegalArgumentException("Constructor not found");
        default:
            throw new IllegalArgumentException("Constructor not found");
        }

        CGLIB$SET_THREAD_CALLBACKS((Callback[])null);
        return var10000;
    }

    public Callback getCallback(int var1) {
        CGLIB$BIND_CALLBACKS(this);
        InvocationHandler var10000;
        switch(var1) {
        case 0:
            var10000 = this.CGLIB$CALLBACK_0;
            break;
        default:
            var10000 = null;
        }

        return var10000;
    }

    public void setCallback(int var1, Callback var2) {
        switch(var1) {
        case 0:
            this.CGLIB$CALLBACK_0 = (InvocationHandler)var2;
        default:
        }
    }

    public Callback[] getCallbacks() {
        CGLIB$BIND_CALLBACKS(this);
        return new Callback[]{this.CGLIB$CALLBACK_0};
    }

    public void setCallbacks(Callback[] var1) {
        this.CGLIB$CALLBACK_0 = (InvocationHandler)var1[0];
    }

    static {
        CGLIB$STATICHOOK1();
    }
}

       CGLib采用了非常底层的字节码技术,其原理是通过字节码技术为一个类创建子类,并在子类中采用方法拦截的技术拦截所有父类方法的调用,顺势织入横切逻辑。但因为采用的是继承,所以不能对final修饰的类进行代理,要拦截的方法不能是final,static,private修饰。JDK动态代理与CGLib动态代理均是实现Spring AOP的基础。

      通俗讲就是CGLib是通过生成代理类,并让它继承目标类,在对目标类中可以继承的方法做覆盖,并在该方法中做功能增强。由于多态关系,实则调用的还是子类的方法。

         

3、动态代理总结:

     相对于静态代理,动态代理大大减少了我们的开发任务,同时减少了对业务的依赖,降低了耦合度,达到职责分离的效果。

     动态代理使用倒是不难,但是,它里面涉及的一些设计原则还需要透彻理解,不过认真实现,阅读下动态代理对象的源码更能加深理解

 

     站在前辈的肩膀上,每天进步一点点

ends~

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值