通俗易懂讲解代理模式

什么是代理模式?

代理模式的定义:代理模式给某一对象提供一个代理对象,并由代理对象控制对原有对象的引用。通俗的来说就是我们所说的中介。

举个例子来介绍: 现在包租婆要租房子,一方面通过自己给客户介绍,另外一方面是将房子给中介公司,让其帮忙代理出租房子,用图展示如下:
代理模式

代理模式涉及到如何角色:

  1. 客户端
  2. 代理对象
  3. 目标对象
  4. 代理对象和目标对象的公共接口

代理模式的优点

隔离作用:在某些情况下,一个客户端不想或者不能直接引用一个委托对象,而代理对象可以在客户端和委托对象之间起到中介作用,其特征是代理类和委托类实现相同接口

有哪几种代理模式?

1、静态代理

委托类

public class Landlady implements  House {
    public void sellHouse() {
        System.out.println("我是女房东我需要租房子");
    }
}

代理类

public class LandladyProxy implements House {
    private Landlady landlady;

    public LandladyProxy(Landlady landlady) {
        this.landlady = landlady;
    }

    public void sellHouse() {
        System.out.println("我是中介公司我是来帮包租婆租房子的");
        landlady.sellHouse();
        System.out.println("中介公司已经把房子租出去了");
    }
}

租客类

public class Renter {

    public static void main(String[] args) {
        rentHouse();
    }

    public static  void rentHouse(){
        Landlady landlady = new Landlady();
        LandladyProxy proxy = new LandladyProxy(landlady);
        proxy.sellHouse();
    }
}

委托类和代理类共同实现的接口

public interface House {

    public void sellHouse();
}

代理类总结****

**优点:**可以做到在符合开闭原则的情况下对目标类进行功能扩展

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

2、 动态代理

在动态代理中,我们不需要在手动去创建代理类,我们只需要编写一个动态处理器就可以了。真正的代理对象是由JDK在运行时为我们动态来创建的。

实现动态代理类的步骤

  1. 实现动态处理器 invocationHandler

    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    
    public class HouseInvocationHandler implements InvocationHandler {
        /**
         *
         * @param proxy  代理对象
         * @param method  委托类的的方法名称
         * @param args  委托类方法参数
         * @return  执行方法返回结果
         * @throws Throwable
         */
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            System.out.println(method);
            System.out.println("这个方法是动态代理方法处理器");
            return null;
        }
    
        public static void main(String[] args) {
            Object o = Proxy.newProxyInstance(House.class.getClassLoader(), new Class[]{House.class}, new HouseInvocationHandler());
            if (o instanceof House) {
                House house = (House) o;
                house.sellHouse();
            }
        }
    }
    
    1. 创建代理类对象
    /**
    java.lang.reflect.Proxy#newProxyInstance(ClassLoader loader,
                                              Class<?>[] interfaces,
                                              InvocationHandler h)
        loader类加载器
        interfaces 被代理的接口类对象
      	动态处理器
    */
    Object o = Proxy.newProxyInstance(House.class.getClassLoader(), new Class[{House.class}, new HouseInvocationHandler());
    
    1. 转换为接口类实例,并使用代理类
       public static void main(String[] args) {
            Object o = Proxy.newProxyInstance(House.class.getClassLoader(), new Class[]{House.class}, new HouseInvocationHandler());
            if (o instanceof House) {
                House house = (House) o;
                house.sellHouse();
            }
        }
    
    
    /执行结果
    public abstract void com.aliyun.bean.House.sellHouse()
    这个方法是动态代理方法处理器
    
    

    动态代理总结:

    **优点:**降低了对业务接口的耦合度

    **缺点:**只能对接口进行代理,无法对非接口和非抽象类进行代理

    3、 CGLIB代理

    CGLIB是什么?
    CGLIB是为了弥补jdk动态代理只能针对接口,而无法针对没有接口的类,CGLIB采用了非常底层字节码技术,其原理就是通过字节码技术为一个类创建一个子类,并在子类中采用方法拦截技术拦截所有的父类方法调用(可以说成是子类重写了父类的方法)。因为CGLIB是针对于类继承而设计的代理技术,那么对于类为final的是无法使用CGLIB代理
    CGLIB使用步骤:

    1、导入CGLIB依赖包

       <!-- https://mvnrepository.com/artifact/cglib/cglib -->
            <dependency>
                <groupId>cglib</groupId>
                <artifactId>cglib</artifactId>
                <version>3.2.10</version>
            </dependency>
    

    2、创建目标类

    import net.sf.cglib.proxy.Enhancer;
    import net.sf.cglib.proxy.MethodInterceptor;
    import net.sf.cglib.proxy.MethodProxy;
    
    import java.lang.reflect.Method;
    
    public class UserService {
    
        public void showUsers(){
            System.out.println("this is user.........");
        }
    
        public String getResult(){
            System.out.println("this is super getResult");
            return String.valueOf(Math.random());
        }
    
    
        public static void main(String[] args) {
            Enhancer enhancer = new Enhancer();
            enhancer.setSuperclass(UserService.class);
            enhancer.setCallback(new MethodInterceptor() {
                public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
                    System.out.println(method.getName());
                    System.out.println("this is interceptor.....");
                    System.out.println(methodProxy.getSuperName());
                    // 执行父类的方法
                    Object o1 = methodProxy.invokeSuper(o, objects);
                    return o1;
                }
            });
            Object o = enhancer.create();
    
            if (o instanceof UserService) {
                UserService userService = (UserService) o;
                userService.showUsers();
                System.out.println("=============================================================================>");
                System.out.println(userService.getResult());
    
            }
        }
    }
    
    

    3、创建代理类

    /*
    
    
    new MethodInterceptor() {
    			/**
    			o 被代理类
    			method 代理类的方法
    			objects 代理类的参数
    			MethodProxy 父类的引用,包含执行的父类的方法对象
    			
    			*/
    	
                public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
                    System.out.println(method.getName());
                    System.out.println("this is interceptor.....");
                    System.out.println(methodProxy.getSuperName());
                    // 执行父类的方法
                    Object o1 = methodProxy.invokeSuper(o, objects);
                    return o1;
                }
            }
    */
    
    Enhancer enhancer = new Enhancer();
            enhancer.setSuperclass(UserService.class);
            enhancer.setCallback(new MethodInterceptor() {
                public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
                    System.out.println(method.getName());
                    System.out.println("this is interceptor.....");
                    System.out.println(methodProxy.getSuperName());
                    // 执行父类的方法
                    Object o1 = methodProxy.invokeSuper(o, objects);
                    return o1;
                }
            });
            Object o = enhancer.create();
    

    4、实现MethodInterceptor

    /*
    
    
    new MethodInterceptor() {
    			/**
    			o 被代理类
    			method 代理类的方法
    			objects 代理类的参数
    			MethodProxy 父类的引用,包含执行的父类的方法对象
    			
    			*/
    	
                public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
                    System.out.println(method.getName());
                    System.out.println("this is interceptor.....");
                    System.out.println(methodProxy.getSuperName());
                    // 执行父类的方法
                    Object o1 = methodProxy.invokeSuper(o, objects);
                    return o1;
                }
            }
    */
    
    

    CGLIB代理总结

    优点:弥补了JDK动态代理只能对于接口代理的缺点

    缺点:对于类为final的无法代理

    代理模式实践

    SpringAOP

    mybatis

    等等
    如有表达不足的请大家指出,谢谢能看完这篇文章

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值