代理模式(AOP的基础,本文主要为SpringAOP的学习做铺垫)

代理模式

:代理模式是SpringAOP的基础,而本篇文章主要是为学习SpringAOP做铺垫,完整地学习代理模式请参考其他文章

[1]代理模式分类

A、静态代理
B、动态代理:[JDK动态代理]和[CGLIB动态代理]

[2]代理模式的三个要是

A、抽象的类或接口 ------完成一件怎样的事情
B、被代理的对象 -----事情操作的具体内容
C、代理对象-----帮助我们完成事情的同时增加其他功能
具体的例子:我们找中介租房子
A、抽象的类或接口 ------租房子
B、被代理的对象 -----房东
C、代理对象 -----中介

[3]代理模式的好处

A、房东可以安心做自己的事情-----(被代理对象可以安心做自己的事情)
B、我们有了问题直接找中介-----(被代理对象变得比较安全)
C、提升了代码的拓展性

[4]三种代理模式的代码实现

1.静态代理代码实现(以租房为例)
A、租房接口类

package cn.qt.proxy1;
//租房
public interface LetRoon {
    public void zf();
}

B、被代理的对象
房东1

package cn.qt.proxy1;
//房东把房子租出去
public class FD implements LetRoon{
    @Override
    public void zf() {
        System.out.println("------出租桂碧园12楼4层3户------");
    }
}

房东2

package cn.qt.proxy1;

public class FD2 implements LetRoon{
    @Override
    public void zf() {
        System.out.println("出租桂碧园12楼5层6户");
    }
}

C、代理对象
中介类

package cn.qt.proxy1;
//中介代理租房
public class ZJ implements LetRoon{
    private int money;

    public ZJ(int money) {
        this.money = money;
    }

    @Override
    public void zf() {
        //中介拓展的方法
        System.out.println("-----收取50元介绍费----");
        //中介处理租房的信息
        if (money<=800){
            //代理房东1的租房
            FD fd=new FD();
            fd.zf();
        }else if (money>800&&money<2000){
            //代理房东2的租房
            FD2 fd2=new FD2();
            fd2.zf();
        }
        //中介拓展的方法
        System.out.println("-----收取500元管理费----");
    }
}

D、客户类(租房者)

package cn.qt.proxy1;
//租房者
public class MyRent {
    public static void main(String[] args) {
        ZJ zj=new ZJ(900);//租一个每月价格为900块的房子
        zj.zf();
    }
}

静态代理模式的缺点:随着被代理对象的增加,代理对象(中介)的压力会越来越大,而且里面书写的代码也比较臃肿。

2.JDK动态代理
A、接口类租房

package cn.qt.proxy2;
//租房
public interface LetRoon {
    public void zf();
}

B、被代理对象(房东对象)
房东1

package cn.qt.proxy2;

//房东把房子租出去
public class FD implements LetRoon{
    @Override
    public void zf() {
        System.out.println("------出租桂碧园12楼4层3户------");
    }
}

房东2

package cn.qt.proxy2;

public class FD2 implements LetRoon{
    @Override
    public void zf() {
        System.out.println("出租桂碧园12楼5层6户");
    }
}

C.实现InvocationHandler接口的中介对象

package cn.qt.proxy2;

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

//书写动态产生代理对象的方法
public class MyInv implements InvocationHandler {

    private LetRoon lr;
    public void setLr(LetRoon lr) {
        this.lr = lr;
    }
    //执行该方法会动态产生代理对象
    public Object getProxy(){
        /*
        * 参数一:保证类型是ClassLoade
        * 参数二:接口的class类型数组
        * 参数三:参数类型是InvocationHandler即可
        * */
        return Proxy.newProxyInstance(MyInv.class.getClassLoader(),new Class[]{LetRoon.class},this);
    }

    //这个方法就类似于书写中介的zf(),即书写代理对象的扩展
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
  	   /**
         * proxy:代理对象----中介
         * method:代理对象中的方法
         * args:参数----null
         */
        System.out.println("收取推荐费50元");
        //运用反射执行指定方法的zf()。//应为所有的房东对象都是LetRoom的子类
        Object invoke = method.invoke(lr, args);
        System.out.println("收取管理费500元");
        return invoke;
    }
}

D.测试类(租房者类)

package cn.qt.proxy2;

public class Test {
    public static void main(String[] args) {
        MyInv my=new MyInv();
        //设置具体的房东
        my.setLr(new FD2());
        //运行时,虚拟机会自动产生代理的对象
        LetRoon proxy =(LetRoon) my.getProxy();
        proxy.zf();
    }
}

下面是用于理解的图
在这里插入图片描述
JDK代理模式的缺点
      我们发现JDK代理模式必须要有接口的操作,若没有这一接口,JDK动态代理则无法使用

3.CGLIB动态代理代码实现

A、导包
在这里插入图片描述
B、被代理对象(房东类)

package cn.qt.proxy3;

public class FD {
    public void zf(){
        System.out.println("----出租9号楼4层2户的房子-----");
    }
}

C、代理对象(中介类)

package cn.qt.proxy3;

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 MethodInv implements MethodInterceptor {
    //产生代理类对象
    public Object getProxy(){
        Enhancer en = new Enhancer();
        //类似于之前的接口
        en.setSuperclass(FD.class);
        en.setCallback(this);
        //使整个设置的内容生效
        return en.create();
    }
    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
      /*
      * o:被代理的对象
      * method:被代理对象的方法
      * objects:参数
      * methodProxy:代理对象中的方法
      * */
        System.out.println("--收取推荐费100元--");
       //调用真正房东的zf()方法
        Object o1 = methodProxy.invokeSuper(o, objects);
        System.out.println("--收取管理费600元--");
        return o1;
    }
}

D、测试类(租房者类)

package cn.qt.proxy3;

public class Test {
    public static void main(String[] args) {
        MethodInv inv=new MethodInv();
        FD proxy =(FD) inv.getProxy();
        proxy.zf();
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值