广告位联系
返回顶部
分享到

Java AOP动态代理介绍

java 来源:互联网 作者:佚名 发布时间:2022-08-26 10:56:46 人浏览
摘要

1.IOC与AOP概念 IOC:控制反转,把对象创建和对象之间的调用过程,交给Spring进行管理。使用IOC的目的是为了降低耦合度。 AOP:面向切面编程,通过预编译方式和运行期间动态代理实现程

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接口类

1

2

3

4

5

6

7

8

9

10

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);

}

2.1.2 MathServiceImpl实现接口类

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

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;

    }

}

2.1.3 ProxyFactory动态代理工厂

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

public class ProxyFactory {

    //被代理对象

    private Object target;

    public ProxyFactory(Object target) {

        this.target = target;

    }

    //获取代理对象

    public Object getProxy(){

        /**

         * ClassLoader loader, 被代理对象的类加载器

         * Class<?>[] interfaces, 被代理对象实现的接口

         * InvocationHandler h: 当代理对象执行被代理的方法时,会触发该对象中的invoke功能

         */

        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 测试类

1

2

3

4

5

6

7

8

9

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类

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

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

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

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 测试类

1

2

3

4

5

6

7

8

9

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 添加对应依赖

1

2

3

4

5

6

7

8

9

10

<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文件

1

2

3

4

5

6

7

8

9

10

11

12

13

14

<?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接口类

1

2

3

4

5

6

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实现接口类

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

@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类

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

@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 测试类

1

2

3

4

5

6

7

8

9

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);

    }

}


版权声明 : 本文内容来源于互联网或用户自行发布贡献,该文观点仅代表原作者本人。本站仅提供信息存储空间服务和不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权, 违法违规的内容, 请发送邮件至2530232025#qq.cn(#换@)举报,一经查实,本站将立刻删除。
原文链接 : https://blog.csdn.net/qq_50896786/article/details/125646561
相关文章
  • SpringBoot自定义错误处理逻辑介绍

    SpringBoot自定义错误处理逻辑介绍
    1. 自定义错误页面 将自定义错误页面放在 templates 的 error 文件夹下,SpringBoot 精确匹配错误信息,使用 4xx.html 或者 5xx.html 页面可以打印错误
  • Java实现手写一个线程池的代码

    Java实现手写一个线程池的代码
    线程池技术想必大家都不陌生把,相信在平时的工作中没有少用,而且这也是面试频率非常高的一个知识点,那么大家知道它的实现原理和
  • Java实现断点续传功能的代码

    Java实现断点续传功能的代码
    题目实现:网络资源的断点续传功能。 二、解题思路 获取要下载的资源网址 显示网络资源的大小 上次读取到的字节位置以及未读取的字节
  • 你可知HashMap为什么是线程不安全的
    HashMap 的线程不安全 HashMap 的线程不安全主要体现在下面两个方面 在 jdk 1.7 中,当并发执行扩容操作时会造成环形链和数据丢失的情况 在
  • ArrayList的动态扩容机制的介绍

    ArrayList的动态扩容机制的介绍
    对于 ArrayList 的动态扩容机制想必大家都听说过,之前的文章中也谈到过,不过由于时间久远,早已忘却。 所以利用这篇文章做做笔记,加
  • JVM基础之字节码的增强技术介绍

    JVM基础之字节码的增强技术介绍
    字节码增强技术 在上文中,着重介绍了字节码的结构,这为我们了解字节码增强技术的实现打下了基础。字节码增强技术就是一类对现有字
  • Java中的字节码增强技术

    Java中的字节码增强技术
    1.字节码增强技术 字节码增强技术就是一类对现有字节码进行修改或者动态生成全新字节码文件的技术。 参考地址 2.常见技术 技术分类 类
  • Redis BloomFilter布隆过滤器原理与实现

    Redis BloomFilter布隆过滤器原理与实现
    Bloom Filter 概念 布隆过滤器(英语:Bloom Filter)是1970年由一个叫布隆的小伙子提出的。它实际上是一个很长的二进制向量和一系列随机映射
  • Java C++算法题解leetcode801使序列递增的最小交换次

    Java C++算法题解leetcode801使序列递增的最小交换次
    题目要求 思路:状态机DP 实现一:状态机 Java 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 class Solution { public int minSwap(int[] nums1, int[] nums2) { int n
  • Mybatis结果集映射与生命周期介绍

    Mybatis结果集映射与生命周期介绍
    一、ResultMap结果集映射 1、设计思想 对简单的语句做到零配置,对于复杂一点的语句,只需要描述语句之间的关系就行了 2、resultMap的应用场
  • 本站所有内容来源于互联网或用户自行发布,本站仅提供信息存储空间服务,不拥有版权,不承担法律责任。如有侵犯您的权益,请您联系站长处理!
  • Copyright © 2017-2022 F11.CN All Rights Reserved. F11站长开发者网 版权所有 | 苏ICP备2022031554号-1 | 51LA统计