SpringAop学习(二)

简介: SpringAop学习(二)

静态代理的缺点

当我们的目标类多个方法时,使用静态代理就需要为这多个方法写差不多的操作,这样会使得我们的代码变的越来越臃肿。我们就可以使用动态代理的方式来处理这个问题

动态代理

动态代理的两种实现方法:基于接口的代理使用jdk的方式,基于继承的代理使用cglib

jdk动态代理

Jdk动态代理只能代理实现接口的类,没有实现接口的类不能实现JDK的动态代理。

Java动态代理类位于java.lang.reflect包下,一般主要涉及到以下两个类:

(1)Interface InvocationHandler :该接口中仅定义了一个方法public object invoke(Object obj;Method method, Object[] args)在实际使用时,第一个参数obj一般是指代理类, method是被代理的方法, args为该方法的参数数组。 这个抽象方法在代理类中动态实现。


(2)Proxy :该类即为动态代理类

newProxyInstance方法用来返回一个代理对象,这个方法总共有3个参数,

  • ClassLoader loader:一个ClassLoader对象,定义了由哪个ClassLoader对象来对生成的代理对象进行加载
  • Class<?>[] interfaces:一个Interface对象的数组,表示的是我将要给我需要代理的对象提供一组什么接口,如果我提供了一组接口给它,那么这个代理对象就宣称实现了该接口(多态),这样我就能调用这组接口中的方法了
  • InvocationHandler h:一个InvocationHandler对象,表示的是当我这个动态代理对象在调用方法的时候,会关联到哪一个InvocationHandler对象上

案例

接口

public interface Subject {
    void work();
}

真实对象

public class RealSubject implements Subject{
    @Override
    public void work() {
        System.out.println("----------吃饭");
    }
}

jdk动态代理类

public class JdkProxySubject implements InvocationHandler {
    private RealSubject realSubject;
    public JdkProxySubject(RealSubject realSubject) {
        this.realSubject = realSubject;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("------买菜");
        Object result=null;
        try {
            result = method.invoke(realSubject,args);
        } catch (Exception e) {
            e.printStackTrace();
        }  finally {
            System.out.println("------洗碗");
        }
        return result;
    }
}

客户端调用

public class Client {
    public static void main(String[] args) {
        Subject subject = (Subject) Proxy.newProxyInstance(RealSubject.class.getClassLoader(),
                RealSubject.class.getInterfaces(),
                new JdkProxySubject(new RealSubject()));
        subject.work();
    }
}
  • RealSubject.class.getInterfaces() 该方法是获取到RealSubject实现的接口,如果有RealSubject实现多个接口都可通过该方法获取到。
  • RealSubject.class.getInterfaces()可以替换成new Class[]{Subject.class}的效果是一样的

20190803015630300.png

效果

20190803014457117.png

cglib动态代理

注意事项:

  • cglib是通过继承来实现动态代理的
  • 无法对static,final类进行代理
  • 无法对private,static方法进行代理

案例

真实对象,不需要接口

public class RealSubject{
    public void work() {
        System.out.println("----------cglib---吃饭");
    }
}

代理对象

public class DemoMethodInterceptor implements MethodInterceptor{
    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        System.out.println("before in cglib------买菜");
        Object result = null;
        try{
            result = proxy.invokeSuper(obj, args);
        }catch (Exception e){
            System.out.println("get ex:"+e.getMessage());
            throw e;
        }finally {
            System.out.println("after in cglib------洗碗");
        }
        return result;
    }
}

客户端调用

public class Client {
    public static void main(String[] args){
        Enhancer enhancer = new Enhancer();
        //真实对象(代理对象需要去继承这个对象)
        enhancer.setSuperclass(RealSubject.class);
        //设置回调方法,也就是我们需要植入的代码
        enhancer.setCallback(new DemoMethodInterceptor());
        //创建新的代理对象
        RealSubject subject = (RealSubject) enhancer.create();
        //执行代理对象的方法
        subject.work();
    }
}
相关文章
|
存储 负载均衡 Dubbo
深入理解Dubbo-4.Dubbo扩展SPI
深入理解Dubbo-4.Dubbo扩展SPI
252 1
|
11月前
|
机器学习/深度学习 人工智能 搜索推荐
探索人工智能在现代医疗中的革新应用
本文深入探讨了人工智能(AI)技术在医疗领域的最新进展,重点分析了AI如何通过提高诊断准确性、个性化治疗方案的制定以及优化患者管理流程来革新现代医疗。文章还讨论了AI技术面临的挑战和未来发展趋势,为读者提供了一个全面了解AI在医疗领域应用的视角。
256 11
|
9月前
【YashanDB 知识库】如何排查 YMP 报错:”OCI 版本为空或 OCI 的架构和本地系统的架构不符“
在迁移预检查的版本检查阶段报错“OCI 版本为空”,原因是 OCI 架构与本地系统不符或依赖库缺失。排查发现 `libdrv_oracle.so` 缺少 `libnsl.so.1` 库,尽管 OCI 客户端路径已正确加入 `LD_LIBRARY_PATH`。解决方法包括下载安装相应动态库版本,或通过软链接指向更高版本库(如 `libnsl.so.2`)。总结:确保动态库路径正确配置,并使用 `ldd` 查看依赖库,必要时创建软链接以解决问题。
|
关系型数据库 分布式数据库 数据库
PostgreSQL+Citus分布式数据库
PostgreSQL+Citus分布式数据库
387 15
|
C# 开发者 前端开发
揭秘混合开发新趋势:Uno Platform携手Blazor,教你一步到位实现跨平台应用,代码复用不再是梦!
【8月更文挑战第31天】随着前端技术的发展,混合开发日益受到开发者青睐。本文详述了如何结合.NET生态下的两大框架——Uno Platform与Blazor,进行高效混合开发。Uno Platform基于WebAssembly和WebGL技术,支持跨平台应用构建;Blazor则让C#成为可能的前端开发语言,实现了客户端与服务器端逻辑共享。二者结合不仅提升了代码复用率与跨平台能力,还简化了项目维护并增强了Web应用性能。文中提供了从环境搭建到示例代码的具体步骤,并展示了如何创建一个简单的计数器应用,帮助读者快速上手混合开发。
421 0
|
设计模式 开发框架 .NET
分享一个 .NET Core Console 项目使用依赖注入的详细例子
分享一个 .NET Core Console 项目使用依赖注入的详细例子
264 0
|
监控 Devops 持续交付
构建高效可靠的云基础设施:DevOps和SRE的最佳实践
【5月更文挑战第30天】在数字化转型的浪潮中,企业对云基础设施的依赖日益增加。本文探讨了如何通过结合DevOps和Site Reliability Engineering(SRE)的最佳实践来构建一个高效、可靠且灵活的云环境。文章首先概述了DevOps和SRE的核心原则,接着提出了一系列策略来优化云资源的管理、自动化流程、以及提高系统的弹性。最后,文中将分享一些成功的案例分析,以帮助读者理解这些原则在实际场景中的应用。
|
Cloud Native 关系型数据库 分布式数据库
数据库性能诊断工具DBdoctor通过阿里云PolarDB产品生态集成认证
DBdoctor(V3.1.0)成功通过阿里云PolarDB分布式版(V2.3)集成认证,展现优秀兼容性和稳定性。此工具是聚好看科技的内核级数据库性能诊断产品,运用eBPF技术诊断SQL执行,提供智能巡检、根因分析和优化建议。最新版V3.1.1增加了对PolarDB-X和OceanBase的支持,以及基于cost的索引诊断功能。PolarDB-X是阿里巴巴的高性能云原生分布式数据库,兼容MySQL生态。用户可通过提供的下载地址、在线试用链接和部署指南体验DBdoctor。
698 0
|
Rust Linux 开发工具
Rust安装
该文介绍了如何在Linux、mac和Windows上安装Rust编程语言。在Linux和mac系统中,可以通过运行一个curl命令自动下载并安装;在Windows上,需从官方网站下载安装包。安装完成后,使用`rustc --version`检查Rust版本以确认安装成功。此外,还提到了如何更新Rust(使用`rustup update`)和卸载(使用`rustup self uninstall`)以及查看官方文档(运行`rustup doc`)。推荐的开发工具有Visual Studio Code和JetBrains CLion,需要安装Rust插件。
|
canal SQL 消息中间件
阿里Canal框架(数据同步中间件)初步实践
阿里Canal框架(数据同步中间件)初步实践
1203 85
阿里Canal框架(数据同步中间件)初步实践