Spring AOP

什么是AspectJ?
AspectJ是一个面向切面的框架,它扩展了Java语言。AspectJ定义了AOP语法,它有一个专门的编译器用来生成遵守Java字节编码规范的Class文件

什么是AOP?AOP赫尔Spring AOP有什么区别?

AOP是一种思想,面向切面的思想;Spring AOP是AOP的一种实现;AspectJ也是AOP的一种实现;

Spring AOP和AspectJ有什么联系?
与OOP对比,AOP是处理一些横切性问题,这些横切性问题不会影响到主逻辑实现的,但是会散落到代码的各个部分,难以维护。AOP就是把这些问题和主业务逻辑分开,达到与主业务逻辑解耦的目的。
aop的应用场景:日志记录 权限验证 效率检查 事务管理
Spring一开始是借用AspectJ的语法,但是底层还是用的是Spring自己的技术;
AspectJ是静态织入的,就是在编译的时候就已经织入好了,而SpringAOP是动态织入的,是在运行的时候织入的。

spring AOP提供两种编程风格
@AspectJ support ------------>利用aspectj的注解
Schema-based AOP support ----------->xml aop:config 命名空间
证明:spring,通过源码分析了,我们可以知道spring底层使用的是JDK或者CGLIB来完成的代理,并且在官网上spring给出了aspectj的文档,和springAOP是不同的。

aspect:一定要给spring去管理 抽象 aspectj->类
pointcut:切点表示连接点的集合 ------------------->表;(我的理解:PointCut是JoinPoint的谓语,这是一个动作,主要是告诉通知连接点在哪里,切点表达式决定 JoinPoint 的数量)
Joinpoint:连接点 目标对象 servlet中的方法 ----------------> 记录;(我的理解:JoinPoint是要关注和增强的方法,也就是我们要作用的点)
Weaving :把代理逻辑加入到目标对象上的过程叫做织入
target 目标对象 原始对象
aop Proxy 代理对象 包含了原始对象的代码和增加后的代码的那个对象
advice:通知 位置 logic
通知类型:
Before 连接点执行之前,但是无法阻止连接点的正常执行,除非该段执行抛出异常
After 连接点正常执行之后,执行过程中正常执行返回退出,非异常退出
After throwing 执行抛出异常的时候
After (finally) 无论连接点是正常退出还是异常退出,都会执行
Around advice: 围绕连接点执行,例如方法调用。这是最有用的切面方式。around通知可以在方法调用之前和之后执行自定义行为。它还负责选择是继续加入点还是通过返回自己的返回值或抛出异常来快速建议的方法执行。
Proceedingjoinpoint 和JoinPoint的区别:
Proceedingjoinpoint 继承了JoinPoint,proceed()这个是aop代理链执行的方法。并扩充实现了proceed()方法,用于继续执行连接点。JoinPoint仅能获取相关参数,无法执行连接点。
JoinPoint的方法
1.java.lang.Object[] getArgs():获取连接点方法运行时的入参列表;
2.Signature getSignature() :获取连接点的方法签名对象;
3.java.lang.Object getTarget() :获取连接点所在的目标对象;
4.java.lang.Object getThis() :获取代理对象本身;

写一个简单例子:
@Conponent
@Aspectj (1)
class TestAspectj{
//声明一个切点
@Pointcut("execution(* com.service..*.*(..))(2)")
public void pointcut(){
}

//声明一个通知,通知主要两点:位置,就是通知到哪里;通知的内容;
@Before("Pointcut()") (3)
public void before(){
//通知的内容
...
}
}
在上面的例子(1)中,AspectJ引的是Aspectj包,而不是Spring的包;该注释就是讲Aspectj交给Spring去管理;
在(2)中,声明的是切点,具体关于哪些连接点呢,即任何修饰符修饰的方法,任何返回值类型,在com.service包或者子包下的任何类的任何参数方式;在声明连接点的时候还可以用within,args,within和execution的区别是execution可以很仔细的声明连接点到具体的方法具体的参数下,而within只能声明到具体的包下的具体类;args只能声明参数;this和target,在上面说了,target 目标对象/原始对象;aop Proxy是代理对象,包含了原始对象的代码和增加后的代码的那个对象。在这里,如果用的是jdk的动态代理,则两个对象不相等,如果是cglib则相等;@EnableAspectJAutoProxy(proxyTargetClass = false)的时候是jdk动态代理,JDK代理的实现方式是基于接口实现,代理类继承Proxy,实现接口;@EnableAspectJAutoProxy(proxyTargetClass = true)的时候是cglib,而CGLIB继承被代理的类来实现;
在(3)中,该通知需要通知到一个地方,这里就是通知到该切点下的所有连接点。也可以直接在@Before("")

Introductions 引入:
这里比较抽象,举个例子,现在有接口Dao,Dao的实现类XXDao,接着创建一个空的接口TestDao,现在在Aspectj中进行如下声明:
@DeclareParents(value="com.dao.*+", defaultImpl=XXDao.class)
public static TestDao testDao;
当我们在ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
Dao dao = ctx.getBean("TestDao");//这里虽然是获取TestDao,但是其实是相当于将XXDao中的代码复制到TestDao中,也相当于TestDao实现了Dao,并且实现的代码是跟XXDao一致的。

posted on 2019-07-08 14:02  吴胖子哦  阅读(83)  评论(0编辑  收藏  举报

导航