Java代理模式

本文介绍了代理模式,它是一种设计模式,可通过代理对象访问目标对象,在不修改原目标对象的前提下扩展其功能。还详细阐述了静态代理、动态代理和cglib代理的相关内容,包括目录结构、实现要求、注意事项等,并给出了参考链接。
代理模式

代理模式是一种设计模式,提供了对目标对象额外的访问方式,即通过代理对象访问目标对象,这样可以在不修改原目标对象的前提下,提供额外的功能操作,扩展目标对象的功能。

简言之,代理模式就是设置一个中间代理来控制访问原目标对象,以达到增强原对象的功能和简化访问方式。
在这里插入图片描述

静态代理

静态代理目录结构
在这里插入图片描述
主题接口 IUserDao

public interface IUserDao {
    void saveUser();
}

主题接口实现类(被代理类) UserDao

public class UserDao implements IUserDao{
    @Override
    public void saveUser() {
        System.out.println("保存用户数据");
    }
}

代理类 UserDaoProxy

public class UserDaoProxy implements IUserDao {
    
    //目标对象
    private IUserDao targer;

    public UserDaoProxy(IUserDao iUserDao){
        this.targer = iUserDao;
    }

    @Override
    public void saveUser() {
        System.out.println("开启事务");
        targer.saveUser();
        System.out.println("提交事务");
    }
}

测试类 ProxyTest

public class ProxyTest {
    @Test
    void testStaticProxy(){
        //目标对象
        IUserDao target = new UserDao();
        //代理对象
        UserDaoProxy proxy = new UserDaoProxy(target);
        proxy.saveUser();
    }
}
动态代理

要求真实对象必须有实现接口
说明:

  • Proxy提供了创建动态代理类和实例的静态方法,它也是由这些方法创建的所有动态代理类的超类。
//返回指定接口的代理类的实例,该接口将方法调用分派给指定的调用处理程序。
public static Object newProxyInstance(ClassLoader loader,//类加载器<?>[] interfaces,//代理类实现的接口列表
                                      InvocationHandler h//调度方法调用的调用处理函数
                                      ) throws IllegalArgumentException                                  

InvocationHandler 是由代理实例的调用处理程序实现的接口

Object invoke(Object proxy,   //调用该方法的代理实例
              方法 method,  //所述方法对应于调用代理实例上的接口方法的实例
              Object[] args) //接口方法参数
       throws Throwable

IUserDao、UserDao同上
UserDaoProxy

public class ProxyFactory {

    //目标对象
    private Object targer;

    public ProxyFactory(Object targer){
        this.targer = targer;
    }

    public Object getProxyInstance() {
        return Proxy.newProxyInstance(targer.getClass().getClassLoader(), targer.getClass().getInterfaces(), new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                System.out.println(proxy.getClass());
                System.out.println("开启事务");
                method.invoke(targer, args);
                System.out.println("提交事务");
                return null;
            }
        });
    }
}

一般可以改成如下
说明:
代理类继承InvocationHandler

public class ProxyFactory2 implements InvocationHandler{

    //目标对象
    private Object targer;

    public ProxyFactory2(Object targer){
        this.targer = targer;
    }

    public <T> T getProxyInstance() {
        return (T) Proxy.newProxyInstance(targer.getClass().getClassLoader(),
                targer.getClass().getInterfaces(),
                this);
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("开启事务");
        Object invoke = method.invoke(targer, args);
        System.out.println("提交事务");
        return invoke;
    }
}

动态代理测试

public class ProxyTest {
    @Test
    void testStaticProxy(){
        //目标对象
        IUserDao target = new UserDao();
        //代理对象
//        IUserDao proxyInstance = (IUserDao) new UserDaoProxy(target).getProxyInstance();
        IUserDao proxyInstance = new UserDaoProxy2(target).getProxyInstance();//将强转放到了代理类中
        proxyInstance.saveUser();
    }
}

注意

  • 若在invoke中调用 proxy.toString()会出现栈溢出,原因是改方法会继续调用invoke方法,出现循环调用,最终栈溢出。
  • 关于invoke方法中proxy参数的作用:只有proxy 实例在InvocationHandler 实现类里加载才能产生第二个参数method (静态代码块是虚拟机加载类的时候执行的,而且只执行一次)
cglib代理

引入依赖

compile "cglib:cglib:3.2.5"

UserDao

public class UserDao {
    public void saveUser() {
        System.out.println("保存用户数据");
    }
}

ProxyFactory

public class ProxyFactory implements MethodInterceptor {
    //目标对象
    private Object target;

    public ProxyFactory(Object target){
        this.target = target;
    }

    public Object getProxyInstance() {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(target.getClass());
        enhancer.setCallback(this);
        return enhancer.create();
    }

    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        System.out.println("开启事务");
        Object invoke = method.invoke(target, args);
        System.out.println("提交事务");
        return invoke;
    }
}

ProxyTest类

public class ProxyTest {
    @Test
    public void testcglibProxy(){
        //目标对象
        UserDao target = new UserDao();
        //代理对象
        UserDao proxy = (UserDao) new ProxyFactory(target).getProxyInstance();
        proxy.saveUser();
    }
}
代理方式实现优点缺点特点
JDK静态代理代理类与委托类实现同一接口,并且在代理类中需要硬编码接口实现简单,容易理解代理类需要硬编码接口,在实际应用中可能会导致重复编码,浪费存储空间并且效率很低
JDK动态代理代理类与委托类实现同一接口,主要是通过代理类实现InvocationHandler并重写invoke方法来进行动态代理的,在invoke方法中将对方法进行增强处理不需要硬编码接口,代码复用率高只能够代理实现了接口的委托类底层使用反射机制进行方法的调用
CGLIB动态代理代理类将委托类作为自己的父类并为其中的非final委托方法创建两个方法,一个是与委托方法签名相同的方法,它在方法中会通过super调用委托方法;另一个是代理类独有的方法。在代理方法中,它会判断是否存在实现了MethodInterceptor接口的对象,若存在则将调用intercept方法对委托方法进行代理可以在运行时对类或者是接口进行增强操作,且委托类无需实现接口不能对final类以及final方法进行代理底层将方法全部存入一个数组中,通过数组索引直接进行方法调用

参考:
https://segmentfault.com/a/1190000011291179#articleHeader3
https://www.jianshu.com/p/9a61af393e41?from=timeline&isappinstalled=0

内容概要:本文介绍了基于贝叶斯优化的CNN-LSTM混合神经网络在时间序列预测中的应用,并提供了完整的Matlab代码实现。该模型结合了卷积神经网络(CNN)在特征提取方面的优势与长短期记忆网络(LSTM)在处理时序依赖问题上的强大能力,形成一种高效的混合预测架构。通过贝叶斯优化算法自动调参,提升了模型的预测精度与泛化能力,适用于风电、光伏、负荷、交通流等多种复杂非线性系统的预测任务。文中还展示了模型训练流程、参数优化机制及实际预测效果分析,突出其在科研与工程应用中的实用性。; 适合人群:具备一定机器学习基基于贝叶斯优化CNN-LSTM混合神经网络预测(Matlab代码实现)础和Matlab编程经验的高校研究生、科研人员及从事预测建模的工程技术人员,尤其适合关注深度学习与智能优化算法结合应用的研究者。; 使用场景及目标:①解决各类时间序列预测问题,如能源出力预测、电力负荷预测、环境数据预测等;②学习如何将CNN-LSTM模型与贝叶斯优化相结合,提升模型性能;③掌握Matlab环境下深度学习模型搭建与超参数自动优化的技术路线。; 阅读建议:建议读者结合提供的Matlab代码进行实践操作,重点关注贝叶斯优化模块与混合神经网络结构的设计逻辑,通过调整数据集和参数加深对模型工作机制的理解,同时可将其框架迁移至其他预测场景中验证效果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值