我的编程空间,编程开发者的网络收藏夹
学习永远不晚

JavaAOP动态代理详细介绍

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

JavaAOP动态代理详细介绍

1.IOC与AOP概念

IOC:控制反转,把对象创建和对象之间的调用过程,交给Spring进行管理。使用IOC的目的是为了降低耦合度。

AOP:面向切面编程,通过预编译方式和运行期间动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。AOP的底层实现是基于动态代理(实现方式是当切入接口时,使用JDK原生动态代理;当切入普通方法时,使用cglib动态代理)。

2.为何使用动态代理

随着业务的不断扩展:

(1)日志功能:如果日志代码修改,需要修改多处。

(2)校验功能:如果多处需要校验,需要修改多处。

这时就需要使用动态代理来解决问题,动态代理的实现方式有两种:

[1]JDK原生动态代理:缺点是必须基于接口完成

[2]cglib动态代理:他可以不用基于接口完成

2.1 JDK原生动态代理

2.1.1 MathService接口类

public interface MathService {
    //+
    public Double add(double a,double b);
    //-
    public Double sub(double a,double b);
    /
        ClassLoader loader=target.getClass().getClassLoader();
        Class<?>[] interfaces=target.getClass().getInterfaces();
        InvocationHandler h=new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                //可以加上需要的非业务代码
                //method.getName()获取方法名
                // Arrays.asList(args)获取输入值
                System.out.println("this is "+method.getName()+" method begin with"+ Arrays.asList(args));
                //method:表示代理对象要代理的方法
                //invoke:回调该函数
                //args:方法需要的参数
                Object result = method.invoke(target, args);//代理对象回调该方法
                return result;
            }
        };
        //先写此处方法,才可找到上述三个方法填写方式
        Object o = Proxy.newProxyInstance(loader, interfaces, h);
        return o;
    }
}

2.1.4 测试类

public class Test01 {
    public static void main(String[] args) {
        MathServiceImpl target=new MathServiceImpl();
        ProxyFactory proxyFactory=new ProxyFactory(target);
        MathService proxy = (MathService) proxyFactory.getProxy();
        Double add = proxy.add(15.0, 5.0);
        System.out.println(add);
    }
}

2.2 cglib动态代理

2.2.1 MathServiceImpl类

public class MathServiceImpl{
    public Double add(double a, double b) {
        Double result=a+b;
        return result;
    }
    public Double sub(double a, double b) {
        Double result=a-b;
        return result;
    }
    public Double mul(double a, double b) {
        Double result=a*b;
        return result;
    }
    public Double div(double a, double b) {
        Double result=a/b;
        return result;
    }
}

2.2.2 ProxyFactory动态代理工厂

注意:

(1)引入cglib的jar包.

<dependency>
  <groupId>cglib</groupId>
  <artifactId>cglib</artifactId>
  <version>3.2.5</version>
</dependency>  

(2)创建一个代理类工厂并实现接口MethodInterceptor

public class ProxyFactory implements MethodInterceptor {
    private Object target;
    public ProxyFactory(Object target) {
        this.target = target;
    }
    //获取代理对象
    public Object getProxy(){
        Enhancer enhancer=new Enhancer();
        //指定被代理对象的父类
        enhancer.setSuperclass(target.getClass());
        //指定回调类
        enhancer.setCallback(this);
        //创建代理对象
        return enhancer.create();
    }
    //当代理对象执行代理方法时触发的方法
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
//        System.out.println("before++++++++++++++++++++");
//        Object result = method.invoke(target, args);
        //可以加上需要的非业务代码
        //method.getName()获取方法名
        // Arrays.asList(args)获取输入值
        System.out.println("this is "+method.getName()+" method begin with"+ Arrays.asList(args));
        //method:表示代理对象要代理的方法
        //invoke:回调该函数
        //args:方法需要的参数
        Object result = method.invoke(target, args);//代理对象回调该方法
        return result;
    }
}

2.2.3 测试类

public class Test01 {
    public static void main(String[] args) {
        MathServiceImpl target=new MathServiceImpl();
        ProxyFactory proxyFactory=new ProxyFactory(target);
        MathServiceImpl proxy = (MathServiceImpl) proxyFactory.getProxy();
        Double add = proxy.add(1, 2);
        System.out.println(add);
    }
}

3.AOP动态代理

3.1 添加对应依赖

<dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
      <version>5.2.15.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-aspects</artifactId>
      <version>5.2.15.RELEASE</version>
    </dependency>

3.2 配置spring.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context
       https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">
    <!--包扫描-->
    <context:component-scan base-package="com.qy151wd.proxy.proxy.aop"/>
    <!--开启aop注解-->
    <aop:aspectj-autoproxy/>
</beans>

3.3 MathService接口类

public interface MathService {
    public Double add(double a, double b);
    public Double sub(double a, double b);
    public Double mul(double a, double b);
    public Double div(double a, double b);
}

3.4 MathServiceImpl实现接口类

@Service
public class MathServiceImpl implements MathService {
    @Override
    public Double add(double a, double b) {
        Double result=a+b;
        return result;
    }
    @Override
    public Double sub(double a, double b) {
        Double result=a-b;
        return result;
    }
    @Override
    public Double mul(double a, double b) {
        Double result=a*b;
        return result;
    }
    @Override
    public Double div(double a, double b) {
        Double result=a/b;
        return result;
    }
}

3.5 LogAspect类

@Service //若是使用@component也可以
@Aspect //表示该类为切面类
public class LogAspect {
    //任意返回类型 aop包下的所有类都有切面日志 使用通配符
    //第一个*:修饰符和返回值类型
    //第二个*:所有类
    //第三个*:所有方法
    @Before("execution(* com.qy151wd.proxy.proxy.aop.*.*(..))")
    public void before(){
        System.out.println("方法执行前的日志");
    }
    @After("execution(* com.qy151wd.proxy.proxy.aop.*.*(..))") //总会被执行,不管有没有异常
    public void after(){
        System.out.println("方法执行后的日志");
    }
    @AfterReturning("execution(* com.qy151wd.proxy.proxy.aop.*.*(..))")//只有碰到return后才会执行
    public void afterReturning(){
        System.out.println("碰到return后执行");
    }
    @AfterThrowing("execution(* com.qy151wd.proxy.proxy.aop.*.*(..))")//异常通知
    public void afterThrowing(){
        System.out.println("出现异常了");
    }
}

3.6 测试类

public class Test01 {
    public static void main(String[] args) {
        //从spring容器中获取
        ApplicationContext app=new ClassPathXmlApplicationContext("spring.xml");
        MathService mathService = (MathService) app.getBean("mathServiceImpl");
        Double add = mathService.add(10, 5);
        System.out.println(add);
    }
}

到此这篇关于Java AOP动态代理详细介绍的文章就介绍到这了,更多相关Java AOP动态代理内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

JavaAOP动态代理详细介绍

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

Android 启动模式详细介绍

Android 启动模式: 启动模式:LaunchMode在多个Activity跳转的过程中扮演着重要的角色,它可以决定是否生成新的Activity实例,是否重用已存在的Activity实例,是否和其他Activity实例公用一个t
2022-06-06

Linux启动过程详细介绍

Linux启动过程详细介绍启动第一步--加载BIOS 当你打开计算机电源,计算机会首先加载BIOS信息,BIOS信息是如此的重要,以至于计算机必须在最开始就找到它。这是因为BIOS中包含了CPU的相关信息、设备启动顺序信息、硬盘信息、内存信
2022-06-04

linux启动流程详细介绍

linux启动流程简介 我们都知道,由于linux的稳定性,通常被作为服务器系统,要想称为一个PHP的高手,linux是必修之课。那么linux系统从开机到启动,中间到底都发生了什么?本文来简单探讨一下中间的神秘过程。 1、 BIOS加电自
2022-06-04

Sourcemap源代码映射详细介绍

这篇文章主要为大家介绍了Sourcemap源代码映射介绍及示例详解解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪<BR>
2023-05-15

Spring后处理器详细介绍

Bean后置处理器允许在调用初始化方法前后对Bean进行额外的处理。可以在​Spring容器通过插入一个或多个BeanPostProcessor的实现来完成实例化,配置和初始化一个​bean​之后实现一些自定义逻辑回调方法<BR>
2023-02-07

java面向对象——多态的详细介绍

一、概述多态是继封装、继承之后,面向对象的第三大特性。生活中,比如跑的动作,小猫、小狗和大象,跑起来是不一样的。再比如飞的动作,昆虫、鸟类和飞机,飞起来也是不一样的。可见,同一行为,通过不同的事物,可以体现出来的不同的形态。多态,描述的就是这样的状态。多态:是
java面向对象——多态的详细介绍
2020-05-09

Python pass详细介绍及实例代码

Python pass的用法:空语句 do nothing保证格式完整保证语义完整以if语句为例,在c或c++/Java中:if(true) ; //do nothing else {//do something }对应于Python就要
2022-06-04

PHP7代码加密扩展详细介绍

这篇文章主要介绍了PHP7代码加密扩展详细介绍,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。特点简单快速,经实测,几乎不影响性能兼容 OPcache、Xdebug 等其他扩展
2023-06-14

java动态代理(jdk与cglib)详细解析

静态代理:由程序员创建或特定工具自动生成源代码,再对其编译。在程序运行前,代理类的.class文件就已经存在了
2022-11-15

Android Loader详细介绍及实例代码

一,Android装载器基本方法装载器从android3.0开始引进。它使得在activity或fragment中异步加载数据变得简单。装载器具有如下特性:它们对每个Activity和Fragment都有效。他们提供了异步加载数据的能力。它
2022-06-06

C++移动语义详细介绍使用

首先,移动语义和完美转发这两个概念是在C++的模板编程的基础上,新增的特性,主要是配合模板来使用。本篇会从C++的值类型,到移动拷贝与移动赋值来理解移动语义与完美转发
2023-01-28

Activity 四种启动模式详细介绍

Activity 四种启动模式详细介绍在Android中每个界面都是一个Activity,切换界面操作其实是多个不同Activity之间的实例化操作。在Android中Activity的启动模式决定了Activity的启动运行方式。Andr
2023-05-31

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录