这章我们来说一说AOP,再说aop之前我们先回顾一下动态代理;
1、动态代理的实现方式有两种:
(1)jdk动态代理:使用jdk中的Proxy,Method,InvocaitonHanderl创建代理对象。jdk动态代理要求目标类必须实现接口
(2)cglib动态代理:第三方的工具库,创建代理对象,原理是继承。 通过继承目标类,创建子类。子类就是代理对象。 要求目标类不能是final的, 方法也不能是final的
2、动态代理的作用:
(1)在目标类源代码不改变的情况下,增加功能。
(2)减少代码的重复
(3)专注业务逻辑代码
(4)解耦合,让你的业务功能和日志,事务非业务功能分离。
3、接下来我们通过代码来演示下JDK动态代理的具体实现:
//接口和实现类
public interface Animal {
public void eat();
}
public class AnimalImpl implements Animal {
@Override
public void eat() {
System.out.println("小猫再吃鱼!!!");
}
}
//切面类
public class MyProxy implements InvocationHandler {
//目标对象
public Object target;
public MyProxy(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("当前时间:"+new Date());
Object res = method.invoke(target, args);
return res;
}
}
//测试方法
@Test
void test1() {
Animal target = new AnimalImpl();
MyProxy myProxy = new MyProxy(target);
Animal proxy = (Animal) Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), myProxy);
proxy.eat();
}4、Aop:面向切面编程, 基于动态代理的,可以使用jdk,cglib两种代理方式。Aop就是动态代理的规范化, 把动态代理的实现步骤,方式都定义好了,让开发人员用一种统一的方式,使用动态代理。
5、AOP(Aspect Orient Programming)面向切面编程
(1)Aspect:切面,给你的目标类增加的功能,就是切面。 像上面用的日志,事务都是切面。切面的特点: 一般都是非业务方法,独立使用的。
(2)Orient:面向, 对着。
(3)Programming:编程
6、怎么理解面向切面编程 ?
(1)需要在分析项目功能时,找出切面。
(2)合理的安排切面的执行时间(在目标方法前, 还是目标方法后)
(3)合理的安全切面执行的位置,在哪个类,哪个方法增加增强功能
7、术语:
1)Aspect:切面,表示增强的功能, 就是一堆代码,完成某个一个功能。非业务功能,常见的切面功能有日志, 事务, 统计信息, 参数检查, 权限验证。
2)JoinPoint:连接点 ,连接业务方法和切面的位置。 就某类中的业务方法
3)Pointcut : 切入点 ,指多个连接点方法的集合。多个方法
4)目标对象: 给哪个类的方法增加功能, 这个类就是目标对象
5)Advice:通知,通知表示切面功能执行的时间。
8、aspectJ: 一个开源的专门做aop的框架。spring框架中集成了aspectj框架,通过spring就能使用aspectj的功能。aspectJ框架实现aop有两种方式:
1.使用xml的配置文件 : 配置全局事务
2.使用注解,我们在项目中要做aop功能,一般都使用注解, aspectj有5个注解。
9、学习aspectj框架的使用。
1)切面的执行时间, 这个执行时间在规范中叫做Advice(通知,增强)在aspectj框架中使用注解表示的。也可以使用xml配置文件中的标签
1)@Before
2)@AfterReturning
3)@Around
4)@AfterThrowing
5)@After
10、切入点表达式(掌握)
AspectJ 定义了专门的表达式用于指定切入点。表达式的原型是:
execution(modifiers-pattern? ret-type-pattern
declaring-type-pattern?name-pattern(param-pattern)
throws-pattern?)解释: modifiers-pattern] 访问权限类型
ret-type-pattern 返回值类型
declaring-type-pattern 包名类名
name-pattern(param-pattern) 方法名(参数类型和参数个数)
throws-pattern 抛出异常类型
?表示可选的部分
以上表达式共 4 个部分。
execution(访问权限 方法返回值 方法声明(参数) 异常类型)
切入点表达式要匹配的对象就是目标方法的方法名。所以,execution 表达式中明显就 是方法的签名。注意,表达式中黑色文字表示可省略部分,各部分间用空格分开。在其中可 以使用以下符号:
举例:
execution(public * *(..)): 指定切入点为:任意公共方法。
execution(* set*(..)): 指定切入点为:任何一个以“set”开始的方法。
execution(* com.xyz.service.*.*(..)) :指定切入点为:定义在 service 包里的任意类的任意方法。
execution(* com.xyz.service..*.*(..)): 指定切入点为:定义在 service 包或者子包里的任意类的任意方法。“..”出现在类名中时,后 面必须跟“*”,表示包、子包下的所有类。
execution(* *..service.*.*(..)) :指定所有包下的 serivce 子包下所有类(接口)中所有方法为切入点
execution(* *.service.*.*(..)):指定只有一级包下的 serivce 子包下所有类(接口)中所有方法为切入点
今天我们主要讲解了动态代理的实现,和aop的理论部分,我们总结一下今天主要讲解的内容:
aop:面向切面编程,切面指的是一段代码,一段你需要对目标方法增强的代码,这段代码大部分情况下是和业务代码没有关联的,比如记录该方法执行的时间,或者是提交事务的代码。
那么我们为什么要面向切面编程呢?应为面向切面编程,可以在不改动目标方法代码的前提下,对目标方法进行增强。也可以对所有目标方法增加统一的监控代码,这样也降低了非业务代码和业务代码的耦合度,便于维护。
| 留言与评论(共有 0 条评论) “” |