这里写目录标题
动态代理
作用:可以在程序运行过程中,创建代理对象。通过代理对象执行放,可以给目标类的方法增加额外的功能(功能增强)
JDK动态实现代理的步骤
- 创建目标类
- 创建InvocationHandler接口实现类,在这个类实现给目标方法增加功能
- 使用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(面向切面编程):
- 需要在分析功能的时候找出切面
什么是切面:切面就是目标类的增加功能,切面有一个特点:一般都是非逻辑业务、独立使用 - 合理的安排切面的执行时间(是在方法执行前 还是在方法执行后)
- 合理安排切面执行的位置。(确定好是哪个类、哪个方法的增强类)
AOP的实现
AOP是一个规范,是动态的一个规范化、一个标准。
AOP的技术实现框架:
- Spring:Spring在内部实现了AOP规范,能够做AOP的工作,且Spring主要在事务处理中使用AOP,但是
Spring中的AOP比较笨重,过程繁琐,极少使用。 - aspectJ:一个开源的专门做AOP框架,而Spring中集成了aspectJ框架,通过Spring就能够使用aspectJ的功能,aspectJ实现AOP的方式有两种:
- 使用xml配置文件:配置全局事务
- 使用注解,在项目中使用AOP功能,一般都采用注解的方式,aspectJ的注解有五个
切面点表达式
execution(访问权限 方法返回值 方法声明那个(参数) 异常类型)
符号 | 意义 |
---|---|
* | 0~任意多个字符 |
… | 在方法参数中,表示任意多个参数 在包明后,表示当前包及其子包路径 |
+ | 用在类名后,表示当前类及其子类 用在接口后,表示当前接口及其实现类 |
Spring框架的学习
aspectJ的五个注解:
@Before
- 作用:前置通知,即在方法执行前执行
- 属性:Value, 内部是切入点表达式,表示切面的执行功能的位置
- 位置: 方法上面
- 特点:
- 在目标执行前先执行
- 不会改变目标方法的执行结果
- 不会影响目标方法的执行
@AfterReturning(后置声明)
要求:
- 公共方法: public
- 方法没有返回值
- 方法名可以自定义
- 方法可以有参数的
属性:
- Value 切入点表达式
- returning 自定义的变量,表示目标方法的返回值
位置:在方法定义的上方
特点:
- 在目标方法执行之后执行
- 能够获取到目标方法的返回值,可以根据这个返回值做不同的处理
- 可以对返回值进行修改
@Around
- 要求
- 方法公共:public
- 必须有一个返回值,推荐使用Object
- 方法名称自定义
- 方法有参数,固定的参数proceedingJoinPoint
- 属性: Value:切入表达式
- 位置:在方法的正上方
- 特点:
- 是功能最强的通知,在方法前、后都可以添加通知
- 能够控制目标方法是否调用执行
- 修改原来方法的执行结果,影响最后的调用结果
AfterThrowing
- 要求:
- 方法公共 :public
- 没有返回值
- 方法名称自定义
- 方法中有一个Exception参数,也可以有JoinPoint
- 属性
- Value 切入点表达式
- throwing 自定义的变量表示目标方法抛出的对象,变量名与方法的参数名必须相同
- 特点:
- 在目标方法抛出异常时执行
- 可以做异常的监控程序,监控目标方法执行时是不是有异常,如果有异常,可以放松邮件、短信通知
After
- 此方法一定会被执行
- 此方法的执行总是在目标方法执行之后
实现AOP的方法
-
创建maven项目
-
添加依赖
- 加入Spring依赖
- 加入aspectJ依赖
- 加入测试单元
-
创建目标类:接口和它的实现类。
要做的是给类中的方法增加功能
-
创建切面类:只是一个普通的类
-
在类的上面加入@Aspect
-
在类中定义方法,方法就是要执行的功能代码
在方法上面加入aspectj中的通知注解,例如@before,有需要指定切入点的表达式execution()
-
-
创建Spring的配置文件:声明对象,把对象统一交给容器去管理
声明方式:1. 注解 2. xml文件配置
-
声明目标对象
-
声明切向对象
-
声明aspectj框架中自动代理生成器标签
自动代理生成器:用来完成代理对象的自动创建功能
-
-
创建测试类,从Spring中 ,从Spring容器中获取目标(实际上就是代理对象)
通过执行代理方法,实现AOP增强功能
实践
@Aspect
是aspectj中的框架中的注解
作用;表示当前类是切面类
切面类:是给业务方法增加功能的类,在这个类中有切面的功能代码
位置:在类的上方
切面类
-
作用:定义方法,方法是实现切面功能
-
要求:
-
方法是公共的 public
-
方法没有返回值
-
防范名称自定义
-
方法可以有参数,也可以没有参数
如果有参数,参数不是自定义的,仅有几个参数类型可以使用
-
声明 自动代理器
使用aspectj框架内部的功能,创建目标对象的代理对象
创建代理对象是在内存中实现的,修改目标对象的内存中的结构、创建为代理对象。
所以目标对象就是被修改后的代理对象.
aspectj-autoproxy会把Spring容器中的所有的目标对象一次性都生成代理对象
<aop:aspectj-autoproxy/>
JoinPoint
-
joinPoint描述
joinPoint是业务方法,要加入切面功能的业务方法
-
JoinPoint作用
可以再通知方法中获取方法执行是的信息,例如方法的名称、方法的参数
-
使用方法:如果这个你的切面功能需要用到参数信息,就是用JoinPoint方法,这个JoinPoint参数的值是由框架所赋予的,必须是第一个参数
-
例子
@Before(Value="execution(void *..KDA.doSomething(参数1, 参数2 ) )")
public void myTest(JoinPoint jp){
System.out.println(jp.getSignature)
}