NO.10 Java代理模式

本文介绍Java代理模式的应用场景及其实现原理,通过示例代码详细解释如何利用Java反射机制实现面向切面编程(AOP),并展示如何在不修改原有业务逻辑的基础上添加日志记录等功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

NO.10 Java代理模式

之前,我们一直学习的是面向对象编程,现在学习另外一种思想——面向切面编程AOP。

假如说学生数据Student是从控制层到服务层再到持久层(数据库),支付信息同样也存到数据库。现在对系统添加日志,权限的管理。需要分别在controller层,service层,dao层添加日志,说明信息的流转。现在在service层添加一个日志——开始学生信息服务层,同样也需要一个结束信息服务层。
倘若业务比较多,添加的日志也就多,那么,有没有一种方式将日志信息、或者权限管理不用写在业务代码中,也就是想写日志,配置一下写在另外的一个地方。这个时候就需要用到另外一种思想——面向切面。
在service层,用一条线切开,在切开地方编程,当经过此处,就留下日志信息,那么有没有一种方式将代码写到这条线上,而不是写在服务层里?这就是所谓的面向切面,Java里有一种方式去实现这个业务逻辑,就是Java代理模式。

StuCardService的实现类 StuCardServiceImpl

package com.xt.spring.aop.normal;

public class StuCardServiceImpl implements StuCardService{
    public void deposit(String cardNo, String money) {
        //一般日志
        System.out.println("开始存钱");
        System.out.println("向学生卡" + cardNo + "存钱:" + money);
        System.out.println("存钱结束");
    }
    public void payMoney(String cardNo, String money) {
        System.out.println("使用学生卡" + cardNo + "支付:" + money);
    }
}

要代理服务层,这是一种实现,需要实现一个接口InvocationHandler
运用反射手动代理,代理的都是代理接口,通过接口代理实现类

package com.xt.spring.aop.normal;

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

public class ServiceProxy implements InvocationHandler{

    //被代理的对象
    private Object target;

    //proxy 代理类  method 需要执行的方法 args 方法的参数
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

        System.out.println("开始操作");
        //invoke 调用这个方法invoke(被代理的对象,参数) 这个对象的这个方法要执行
        Object returnValue = method.invoke(target, args);
        System.out.println("操作结束");
        //将方法的返回值返回
        return returnValue;
    }

    //对象被创建代理的方法
    public Object creatProxyInstance(Object target){
        this.target = target;
        //newProxyInstance(loader,interfaces,h)loader表示类加载器 interfaces 需要代理的类所实现的接口,h当前代理的这个对象
        Object returnValue = Proxy.newProxyInstance(this.target.getClass().getClassLoader(), this.target.getClass().getInterfaces(), this);
        return returnValue;
    }
}

想要添加日志,可以在代理类中添加,invoke方法要执行,可以在该方法里写日志,将日志由StuCardServiceImpl转到ServiceProxy。
而为什么会执行invoke方法?这时代理模式的固定方式。paymoney方法要执行,其实是调用了代理对象的invoke方法,paymoney就是执行了Object returnValue = method.invoke(target, args);这个操作。

package com.xt.spring.aop.normal;

import org.junit.Test;

public class AOPTest {

    @Test
    public void test(){
        StuCardService scd = new StuCardServiceImpl();
        scd.deposit("12132412", "400");
    }

    @Test
    public void proxyTest(){
        StuCardService scd = new StuCardServiceImpl();

        //创建StuCardService的代理对象 通用代理类这个对象去创建想要去代理的对象  返回的是object,需要强转
        StuCardService scdProxy = (StuCardService) new ServiceProxy().creatProxyInstance(scd);
        //scdProxy是ServiceProxy这个代理对象依据scd创建的代理对象。
        scdProxy.payMoney("454545", "200");
    }
}

举个例子说,开办了一个公司,有财务,公司要记账,公司人员去税务局交税,去银行存款,公司要通过税务人员去交税存款,现在有一个代理机构,这个代理机构代表公司去交税,存款。这个代理机构可以代理很多家公司。要代理财务(财务支付—缴费,存钱两个功能),可以没有实现类,没有财务人员,由代理机构进行操作。

以上是最原始的代理方式。
综上所述:
java代理模式:
将日志写在切面内,而不直接显示在业务层
原理是java反射机制
需要实现一个接口InvocationHandler,实现invoke方法
创建代理对象–接口,通过代理接口,代理实现类
invoke(Object代理类,Method执行的方法,Object[]方法的参数)
method.invoke(代理对象,args)表示调用这个方法
method是代理对象的需要执行的方法

代理对象的创建:
Proxy.newProxyInstance(类加载器this.target.getclass.getClassLoader(),interface需要代理的这个类的接口,当前代理的对象)
将日志转移到invoke方法里

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值