Spring的代理模式

一:静态代理

角色分析:

  • 抽象角色 : 一般使用接口或者抽象类来实现

  • 真实角色 : 被代理的角色

  • 代理角色 : 代理真实角色 ; 代理真实角色后 , 一般会做一些附属的操作 .

  • 客户 : 使用代理角色来进行一些操作

抽象角色(接口类)

package com.service;
//抽象角色
public interface Rent {
    public void rent();
}

真实角色

package com.service;
//真实角色
public class Host implements Rent{
    @Override
    public void rent() {
        System.out.println("房屋出租");
    }
}

抽象角色

package com.service;

public class Proxy implements Rent{
    private Host host;
    public Proxy(Host host){
        this.host=host;
    }
    public void seeHouse(){
        System.out.println("带客户体验房屋");
    }
    public void fare(){
        System.out.println("客户买房");
    }
    @Override
    public void rent() {
        seeHouse();
        host.rent();
        fare();
    }
}

客户类:

        Host host =new Host();
        Proxy proxy=new Proxy(host);
        proxy.rent();

运行

 优点

  • 可以使得我们的真实角色更加纯粹 . 不再去关注一些公共的事情 .
  • 公共的业务由代理来完成 . 实现了业务的分工 ,
  • 公共业务发生扩展时变得更加集中和方便 .

缺点

        多了代理类 , 工作量变大了 . 开发效率降低

二:动态代理(我们想要静态代理的好处,又不想要静态代理的缺点,所以 , 就有了动态代理)

  • 动态代理的代理类是动态生成的 . 静态代理的代理类是我们提前写好的

  • 动态代理分为两类 : 一类是基于接口动态代理 , 一类是基于类的动态代理

  • 基于接口的动态代理----JDK动态代理
  • 基于类的动态代理–cglib

核心:InvocationHandler 和 Proxy 

 

抽象角色:和前面的静态代理一致

真实角色:和前面的静态代理一致

代理角色:

package com.service;

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

//代理角色
public class ProxyInvocationHandler implements InvocationHandler {
    private Rent rent;

    public void setRent(Rent rent) {
        this.rent = rent;
    }
    //生成代理类,重点是第二个参数,获取要代理的抽象角色!之前都是一个角色,现在可以代理一类角色
    public Object getProxy() {
        return Proxy.newProxyInstance(this.getClass().getClassLoader(), rent.getClass().getInterfaces(), this);
    }
    //参数
    //proxy - 调用该方法的代理实例
    //method -所述方法对应于调用代理实例上的接口方法的实例。方法对象的声明类将是该方法声明的接口,它可以是代理类继承该方法的代理接口的超级接口。
    //args -包含的方法调用传递代理实例的参数值的对象的阵列,或null如果接口方法没有参数。原始类型的参数包含在适当的原始包装器类的实例中,例如java.lang.Integer或java.lang.Boolean 。
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        seeHouse();
        Object result = method.invoke(rent, args);
        fare();
        return result;
    }
    public void seeHouse() {
        System.out.println("带房客看房");
    }

    public void fare() {
        System.out.println("收中介费");
    }
}

测试代码实现:

先创建真实角色对象,再创建代理角色对象,然后代理角色对象调用方法获取真实角色对象在代理角色类里面。

代理角色对象调用生成代理角色类方法生成对象强转为抽象角色类,让后用对象去调用方法。

这里我试过强转为真实角色,会报错。

之所以不行,因为我们是动态代理,对象是动态生成的,用真实对象不能动态生成。

 

Host host=new Host();
        ProxyInvocationHandler proxyInvocationHandler=new ProxyInvocationHandler();
        proxyInvocationHandler.setRent(host);
        Rent proxy= (Rent) proxyInvocationHandler.getProxy();
        proxy.rent();

运行结果

下面我再给大家深刻理解一下。在代理角色类里面不再定义真实角色,而是定义一个普通类对象。

抽象角色:

package com.service;

public interface UserService {
    void add();
    void delete();
    void update();
    void query();
}

真实角色:

package com.service;

public class UserServiceImpl implements UserService{

    @Override
    public void add() {
        System.out.println("增加了一个用户");
    }

    @Override
    public void delete() {
        System.out.println("删除了一个用户");
    }

    @Override
    public void update() {
        System.out.println("更新了一个用户");
    }

    @Override
    public void query() {
        System.out.println("查询了一个用户");
    }
}

动态代理类:

package com.service;

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

public class ProxyInvocationHander1 implements InvocationHandler {
    private Object target;

    public void setTarget(Object target) {
        this.target = target;
    }
    public Object getProxy(){
        return Proxy.newProxyInstance(this.getClass().getClassLoader(),target.getClass().getInterfaces(),this);
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        log(method.getName());
        Object result=method.invoke(target,args);
        return result;
    }
    public void log(String methodName){
        System.out.println("执行了"+methodName+"方法");
    }
}

对于getProxy这个方法,我们只需要修改其第二个参数就Ok 

对于invoke方法,只需要修改其返回对象的第一个参数为你自己定义的对象。

测试:

        UserServiceImpl userService=new UserServiceImpl();
        ProxyInvocationHander1 proxyInvocationHander1=new ProxyInvocationHander1();
        proxyInvocationHander1.setTarget(userService);
        UserService userService1= (UserService) proxyInvocationHander1.getProxy();
        userService1.add();
        userService1.delete();
        userService1.query();
        userService1.update();

对了,这里的代理是不需要去XML中配置的,也不用使用注解。 

参考文献:Spring

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

零维展开智子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值