尚硅谷设计模式学习(13)---[代理模式(Proxy)---静态代理,动态代理,Cglib代理]

Posted 小智RE0

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了尚硅谷设计模式学习(13)---[代理模式(Proxy)---静态代理,动态代理,Cglib代理]相关的知识,希望对你有一定的参考价值。

🚀🚀🚀尚硅谷传送门==>B站尚硅谷Java设计模式

❤❤❤感谢尚硅谷❤❤❤

🕐🕑🕒最近开始计划学习一下设计模式了,加油!!!



📢代理模式

代理模式:给一个对象提供副本,通过这个 副本对象 来控制 真实对象 的访问。那么就算是想要扩展新的内容或功能,在副本对象上修改即可.
(可理解为分身,可通过分身到本体,对于分身的管理操作会影响到本体,)

被代理的对象可以是远程对象、创建开销大的对象或需要安全控制的对象

具体可分为3种:

静态代理
动态代理 (JDK代理、接口代理)
Cglib代理 (在内存动态的创建对象)


🌈静态代理

代理对象与目标对象要实现相同的接口,然后通过调用相同的方法来调用目标对象的方法。

使用静态代理模式;在不修改目标对象的功能前提下, 能通过代理对象对目标功能扩展;
但是由于代理对象需要与目标对象实现一样的接口,所以就要产生很多代理类;
如果说接口要增加方法,目标对象和代理对象都要增加方法实现.

案例:

代理和目标的共同接口UserDao

//接口   ,目标对象和代理对象都要实现;
public interface UserDao {
    //添加用户方法;
    public abstract void addUser();
}

目标RealUserDao

//目标;
public class RealUserDao implements UserDao{
    @Override
    public void addUser() {
        System.out.println("目标对象说要添加用户");
    }
}

代理ProxyUserDao

//代理;
public class ProxyUserDao implements UserDao{

    //把目标聚合过来;
    private UserDao target;

    public ProxyUserDao(UserDao target) {
        this.target = target;
    }

    @Override
    public void addUser() {
        System.out.println("静态代理开始-->");
        target.addUser();
        System.out.println("结束--->");
    }
}

模拟客户端Client

public class Client {
    public static void main(String[] args) {

        ProxyUserDao proxyUserDao =new ProxyUserDao(new RealUserDao());

        //通过代理对象,调用到目标对象的方法;
        proxyUserDao.addUser();
    }
}

/*
静态代理开始-->
目标对象说要添加用户
结束--->
*/

🌈动态代理

只需要目标对象去实现接口即可 ; 代理对象不需要实现接口.

代理类所在的包:java.lang.reflect.Proxy

代理对象使用JDK的API,动态形式在内存中构建代理对象;
使用方法newProxyInstance( ) 时,

参数 :ClassLoader loader ;指定当前目标对象使用的类加载器;
参数: Class<?>[] interfaces : 目标对象实现的接口.
参数: InvocationHandler h) 执行目标对象方法时,触发事件发生器,会通过反射得到执行的目标对象方法.

public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException

接口UserDao

//接口 仅需要目标对象实现;
public interface UserDao {
    //添加用户方法;
    public abstract void addUser();
}

目标类RealUserDao

//目标;
public class RealUserDao implements UserDao{
    @Override
    public void addUser() {
        System.out.println("目标对象说要添加用户");
    }
}

代理类

//代理工厂;
public class ProxyFactory {

    //维护目标对象;
    private Object target;

    //初始化;
    public ProxyFactory(Object target) {
        this.target = target;
    }

    //动态代理;
    public  Object getProxyInstance(){

        return Proxy.newProxyInstance(target.getClass().getClassLoader(),
                target.getClass().getInterfaces(),
                new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        System.out.println("动态代理/JDK代理");
                        Object invoke = method.invoke(target, args);
                        return invoke;
                    }
                });
    }
}

模拟客户端

public class Client {

    public static void main(String[] args) {

        //创建目标对象;
        UserDao realUserDao = new RealUserDao();

        //为目标对象 创建 代理对象;
        UserDao proxyFactory= (UserDao)new ProxyFactory(realUserDao).getProxyInstance();

        proxyFactory.addUser();
    }
}

/*
动态代理/JDK代理
目标对象说要添加用户
*/

🌈Cglib代理

Cglib代理(子类代理)
在内存中构建一个子类对象 ; 实现对目标对象功能扩展.

Cglib百科

Cglib包的底层是通过使用字节码处理框架ASM来转换字节码并生成新的类.

注意代理的类不能定义为final,否则报错java.lang.IllegalArgumentException:
目标对象的方法若为final/static,就不会被拦截(不会执行目标对象额外的业务方法)

需要的maven依赖;

 <!-- https://mvnrepository.com/artifact/cglib/cglib -->
<dependency>
    <groupId>cglib</groupId>
    <artifactId>cglib</artifactId>
    <version>3.2.11</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.ow2.asm/asm-commons -->
<dependency>
    <groupId>org.ow2.asm</groupId>
    <artifactId>asm-commons</artifactId>
    <version>7.1</version>
</dependency>

类图原理

getInstance ( ) 方法为目标对象target创建代理对象;
重写的 intercept ( ) 方法,实现了对于目标对象的方法调用.

目标类RealUserDao

//目标类;
public class RealUserDao {
    //添加用户;
    public  void addUser(){
        System.out.println("用了Cglib的方式,无需使用接口");
        System.out.println("添加用户的方法");
    }
}

代理类ProxyFactory

//代理;
public class ProxyFactory implements MethodInterceptor {
    //定义目标对象;
    private Object target;

    //初始化;
    public ProxyFactory(Object target) {
        this.target = target;
    }

    //返回 target的代理对象;
    public Object getProxyInstance(){
        //创建工具类;
        Enhancer enhancer = new Enhancer();
        //设置父类;
        enhancer.setSuperclass(target.getClass());
        //设置回调函数;
        enhancer.setCallback(this);
        //返回代理对象;
        return enhancer.create();
    }


    //重写的 intercept () 方法,实现了对于目标对象的方法调用.
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("开始Cglib代理模式");

        Object invoke = method.invoke(target, objects);
        System.out.println("Cglib代理模式==> 提交  <==");
        return invoke;
    }
}

模拟客户端

//模拟客户端;
public class Client {
    public static void main(String[] args) {
        //目标对象;
        RealUserDao target =new RealUserDao();

        //取到目标对象的 代理对象;
        RealUserDao proxyFactory = (RealUserDao) new ProxyFactory(target).getProxyInstance();
        //执行代理对象的方法;
        proxyFactory.addUser();
    }
}

/*

开始Cglib代理模式
用了Cglib的方式,无需使用接口
添加用户的方法
Cglib代理模式==> 提交  <==

*/

以上是关于尚硅谷设计模式学习(13)---[代理模式(Proxy)---静态代理,动态代理,Cglib代理]的主要内容,如果未能解决你的问题,请参考以下文章

尚硅谷设计模式学习---[装饰者模式]

尚硅谷设计模式学习---[单例模式]

尚硅谷设计模式学习---[桥接模式(Bridge)]

尚硅谷设计模式学习(23)---[策略模式(strategy pattern)]

尚硅谷设计模式学习---[简单工厂模式,工厂方法模式,抽象工厂模式]

尚硅谷设计模式学习(17)---[迭代器模式(Iterator Pattern)]