动态代理的总结

动态代理

作用:可以在程序运行过程中,创建代理对象。通过代理对象执行放,可以给目标类的方法增加额外的功能(功能增强)

JDK动态实现代理的步骤

  1. 创建目标类
  2. 创建InvocationHandler接口实现类,在这个类实现给目标方法增加功能
  3. 使用JDK中的Proxy类,创建代理对象,实现创建对象的能力

创建方法:

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

public class MyTest implements InvocationHandler {
    //为了防止对象的丢失,我们在这里储存一个对象
    private Object user;

    public MyTest(Object user) {
        this.user=user;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {
        Object res=null;
        res=method.invoke(user, 参数args);
        return res;
    }
}

使用JDK进行代理:

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

public class MyApp {
    public static void main(String[] args) {
    SomeService something = new SomeServiceimp();
    InvocationHandler handler = new MyTest(something);
    SomeService proxy = proxy=(SomeService) Proxy.newProxyInstance(
            post.getClass().getClassLoader(),
            post.getClass().getInterfaces(),handler);
    proxy.doSome();
    }
    
}

如果想要对其进行限制,则可以在MyTest文件中进行限制。

cglib动态代理

cglib是一个第三方数据库,创建代理对象,原理是继承,通过继承目标类创建子类,
子类就是代理对象。

要求:目标类不能是final类,方法也不能是final方法

动态代理的作用

动态代理的作用:
1. 在目标类源代码不改变的情况下,增加功能
2. 减少代码重复
3. 专注业务逻辑代码,减少干扰项
4. 解耦合,能够让自己的业务和杂项相分离

AOP

AOP:面向切面编程,基于动态代理的,可以使用jdk、cglib两种动态代理的方式,AOP就是动态代理的规范化
,把动态代理的实现步骤、方法都定义好了,让开发人员使用一种统一的方式,使用动态代理。


如何理解AOP(面向切面编程):

  1. 需要在分析功能的时候找出切面

    什么是切面:切面就是目标类的增加功能,切面有一个特点:一般都是非逻辑业务、独立使用
  2. 合理的安排切面的执行时间(是在方法执行前 还是在方法执行后)
  3. 合理安排切面执行的位置。(确定好是哪个类、哪个方法的增强类)

AOP的实现

AOP是一个规范,是动态的一个规范化、一个标准。


AOP的技术实现框架:

  1. Spring:Spring在内部实现了AOP规范,能够做AOP的工作,且Spring主要在事务处理中使用AOP,但是
    Spring中的AOP比较笨重,过程繁琐,极少使用。
  2. aspectJ:一个开源的专门做AOP框架,而Spring中集成了aspectJ框架,通过Spring就能够使用aspectJ的功能,aspectJ实现AOP的方式有两种:
    1. 使用xml配置文件:配置全局事务
    2. 使用注解,在项目中使用AOP功能,一般都采用注解的方式,aspectJ的注解有五个

切面点表达式

execution(访问权限 方法返回值 方法声明那个(参数) 异常类型)

符号意义
*0~任意多个字符
在方法参数中,表示任意多个参数
在包明后,表示当前包及其子包路径
+用在类名后,表示当前类及其子类
用在接口后,表示当前接口及其实现类

Spring框架的学习

aspectJ的五个注解:

@Before
  1. 作用:前置通知,即在方法执行前执行
  2. 属性:Value, 内部是切入点表达式,表示切面的执行功能的位置
  3. 位置: 方法上面
  4. 特点:
    1. 在目标执行前先执行
    2. 不会改变目标方法的执行结果
    3. 不会影响目标方法的执行
@AfterReturning(后置声明)

​ 要求:

  1. 公共方法: public
  2. 方法没有返回值
  3. 方法名可以自定义
  4. 方法可以有参数的

属性:

  1. Value 切入点表达式
  2. returning 自定义的变量,表示目标方法的返回值

位置:在方法定义的上方

特点:

  1. 在目标方法执行之后执行
  2. 能够获取到目标方法的返回值,可以根据这个返回值做不同的处理
  3. 可以对返回值进行修改
@Around
  1. 要求
    1. 方法公共:public
    2. 必须有一个返回值,推荐使用Object
    3. 方法名称自定义
    4. 方法有参数,固定的参数proceedingJoinPoint
  2. 属性: Value:切入表达式
  3. 位置:在方法的正上方
  4. 特点:
    1. 是功能最强的通知,在方法前、后都可以添加通知
    2. 能够控制目标方法是否调用执行
    3. 修改原来方法的执行结果,影响最后的调用结果
AfterThrowing
  1. 要求:
    1. 方法公共 :public
    2. 没有返回值
    3. 方法名称自定义
    4. 方法中有一个Exception参数,也可以有JoinPoint
  2. 属性
    1. Value 切入点表达式
    2. throwing 自定义的变量表示目标方法抛出的对象,变量名与方法的参数名必须相同
  3. 特点:
    1. 在目标方法抛出异常时执行
    2. 可以做异常的监控程序,监控目标方法执行时是不是有异常,如果有异常,可以放松邮件、短信通知
After
  1. 此方法一定会被执行
  2. 此方法的执行总是在目标方法执行之后

实现AOP的方法

  1. 创建maven项目

  2. 添加依赖

    1. 加入Spring依赖
    2. 加入aspectJ依赖
    3. 加入测试单元
  3. 创建目标类:接口和它的实现类。

    要做的是给类中的方法增加功能

  4. 创建切面类:只是一个普通的类

    1. 在类的上面加入@Aspect

    2. 在类中定义方法,方法就是要执行的功能代码

      在方法上面加入aspectj中的通知注解,例如@before,有需要指定切入点的表达式execution()

  5. 创建Spring的配置文件:声明对象,把对象统一交给容器去管理

    ​ 声明方式:1. 注解 2. xml文件配置

    1. 声明目标对象

    2. 声明切向对象

    3. 声明aspectj框架中自动代理生成器标签

      自动代理生成器:用来完成代理对象的自动创建功能

  6. 创建测试类,从Spring中 ,从Spring容器中获取目标(实际上就是代理对象)

    通过执行代理方法,实现AOP增强功能

实践

@Aspect

是aspectj中的框架中的注解

作用;表示当前类是切面类

切面类:是给业务方法增加功能的类,在这个类中有切面的功能代码

位置:在类的上方

切面类
  1. 作用:定义方法,方法是实现切面功能

  2. 要求:

    1. 方法是公共的 public

    2. 方法没有返回值

    3. 防范名称自定义

    4. 方法可以有参数,也可以没有参数

      如果有参数,参数不是自定义的,仅有几个参数类型可以使用

声明 自动代理器

使用aspectj框架内部的功能,创建目标对象的代理对象

创建代理对象是在内存中实现的,修改目标对象的内存中的结构、创建为代理对象。

所以目标对象就是被修改后的代理对象.

aspectj-autoproxy会把Spring容器中的所有的目标对象一次性都生成代理对象

<aop:aspectj-autoproxy/>

JoinPoint

  1. joinPoint描述

    joinPoint是业务方法,要加入切面功能的业务方法

  2. JoinPoint作用

    可以再通知方法中获取方法执行是的信息,例如方法的名称、方法的参数

  3. 使用方法:如果这个你的切面功能需要用到参数信息,就是用JoinPoint方法,这个JoinPoint参数的值是由框架所赋予的,必须是第一个参数

  4. 例子

@Before(Value="execution(void *..KDA.doSomething(参数1, 参数2  ) )")
public void myTest(JoinPoint jp){
    System.out.println(jp.getSignature)
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值