文档章节

AOP技术讨论

乒乓狂魔
 乒乓狂魔
发布于 2015/10/15 08:19
字数 1549
阅读 994
收藏 18
aop

#1 2015-10-14 AOP讨论

强烈推荐文章

本文则是根据上述文章进行的群内讨论的提纲

#2 从AOP拦截的时机来看待AOP

  • 编译期
  • 字节码加载前
  • 字节码加载后

如图:

AOP实现机制分类

  • 1 aspectj : 在编译期静态植入

  • 2 JDK Proxy: 目标类加载后,为其接口动态生成代理类

  • 3 cglib : 目标类加载后,为其动态生成子类,将切面逻辑加入子类中

  • 4 自定义类加载器:在目标类加载前,将切面逻辑加入目标类字节码中

  • 5 字节码转换器:在目标类加载前,将切面逻辑加入目标类字节码中(jdk1.5的Instrumentation);在目标类加载后,将切面逻辑加入目标类字节码中(jdk1.6的Instrumentation触发jvm重新类加载)

    在类的字节码载入jvm前会调用ClassFileTransformer的transform方法,从而实现修改原类方法的功能,实现aop

    日志记录工具anylog,就是使用自定义的ClassFileTransformer来动态修改字节码(内部借助于javassist来修改字节码)

#3 角色梳理:AOP联盟、Aspectj、SpringAOP

##3.1 AOP的概念

  • Pointcut:切入点,表示在哪里进行拦截,简单理解如正则表达式

  • Joinpoint:连接点,符合上述正则表达式的一个具体对象

  • Advice:增强,即拦截逻辑

    Advice的类型:

    • 1 前置增强(Before advice)
    • 2 后置返回增强(After returning advice)
    • 3 后置异常增强(After throwing advice)
    • 4 环绕增强(Around Advice)
    • 5 引入增强(对类进行增强)
  • Aspect:切面,包含切入点和增强

  • Target Object:要代理的目标对象

  • AOP Proxy:代理对象

  • Weaving:织入,可以是编译期、字节码加载前、字节码加载后

##3.2 Aspectj

如下简单使用案例:

aspectj使用案例

这里有个系列文章跟我学aspectj

  • 在编译时期就织入
  • 不能使用传统的JDK编译
  • 等等

#4 SpringAOP的发展历程

##4.1 JDK和CGLib动态代理的原始方式

JDK动态代理:

JDK动态代理

CGLib动态代理:

CGLib动态代理

##4.2 ProxyFactory对jdk和cglib的封装

ProxyFactory简单的对jdk和cglib的封装,根据配置(强制采用cglib)或者自行决定(根据是否实现接口)采用jdk动态代理还是cglib动态代理。

使用案例如下:

ProxyFactory使用案例

对jdk动态代理的封装(cglib也类似不再说明):

InvocationHandler h:固定是JdkDynamicAopProxy,其中对

InvocationHandler的接口方法Object invoke(Object proxy, Method method, Object[] args)实现如下:

JdkDynamicAopProxy对InvocationHandler的实现

  • 第一步:根据调用的类和方法获取拦截器MethodInterceptor集合,内部会使用pointcut来进行过滤。后面详细说说MethodInterceptor和Advice的区别。

    ProxyFactory有如下两种方法:

    addAdvice(Advice advice)
    addAdvisor(Advisor advisor)
    

    Advisor:其实是Advice和Pointcut的集合,所以在添加Advice是会给出一个默认的Pointcut

    Pointcut可以是:

    • 正则表达式类型 JdkRegexpMethodPointcut

    • aspectj的pointcut表达式类型,如

      execution(* com.aspectj.demo.test.HelloWorld.main(..))
      @annotation(aop.demo.Tag)
      
  • 第二步:如果拦截器集合为空(即没有代理该方法),则通过反射直接执行目标对象target的方法

  • 第三步:如果拦截器集合不为空,依次执行拦截器MethodInterceptor中的invoke方法。

MethodInterceptor和Advice的区别:

Advice:定义了拦截逻辑,如MethodBeforeAdvice,接口定义如下:

public interface MethodBeforeAdvice extends BeforeAdvice {
	void before(Method method, Object[] args, Object target) throws Throwable;
}

而MethodInterceptor则是决定Advice的调用时机,同时对外提供统一的调用方法invoke,如MethodBeforeAdviceInterceptor

public class MethodBeforeAdviceInterceptor implements MethodInterceptor, Serializable {

	private MethodBeforeAdvice advice;

	public MethodBeforeAdviceInterceptor(MethodBeforeAdvice advice) {
		Assert.notNull(advice, "Advice must not be null");
		this.advice = advice;
	}

	@Override
	public Object invoke(MethodInvocation mi) throws Throwable {
		this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis() );
		return mi.proceed();
	}
}

上述就是ProxyFactory对jdk和cglib的封装,简化了我们的操作。但是还有如下问题:

  • 一个ProxyFactory只能代理一个目标对象target
  • 还要手动的配置每一个Advisor bean对应的Advice和Pointcut。

##4.3 批量代理

上述ProxyFactory还只能针对某一个target进行代理

我们现在的需求是:对一批对象进行批量代理。这时需要两大部分:

  • 一批Advice和Pointcut组合,即会有多个Advisor,符合不同Pointcut的进行不同的Advice增强。这里即切面,切面并没有具体的类进行描述,可以理解成一个Advisor的集合(一个Advisor包含了一个Advice和一个Pointcut),如下所示

    如xml配置形式配置切面:

    xml配置形式配置切面

    注解形式配置切面,同时要开启aop:aspectj-autoproxy配置:

    注解形式配置切面

  • 切面仅仅是描述哪些类的哪些方法被哪些Advice增强,仅仅是描述而已,需要有一个类来承担这样的批量代理的工作,这就是基类AbstractAutoProxyCreator来完成这一项工作,对于每一个符合条件的bean都仍然采用ProxyFactory来进行代理的创建:

    AbstractAutoProxyCreator批量代理

    所以Spring中的AOP全部是基于ProxyFactory这套创建流程的。而AbstractAutoProxyCreator子类则是分别取解析不同的切面配置

    如上述的aop:config配置是启用了AspectJAwareAdvisorAutoProxyCreator来进行批量代理的

    如上述注解形式开启的aop:aspectj-autoproxy是启用了AnnotationAwareAspectJAutoProxyCreator来进行批量代理的

##4.4 Spring对aspectj的引入的体现

我们知道aspectj是静态织入,Spring是怎么来引入aspectj呢?

aspectj是静态织入,需要单独的编译器来进行编译,但是功能强大。如使用案例:

aspectj使用案例

强大的pointcut表达式功能(具体的自行去搜),同时还具有了注解功能,如下:

等这些都是aspectj的实现

而什么才叫Spring最原始的AOP呢?就是ProxyFactory这一层,仅仅对jdk和cglib进行了简单的封装。

Spring原始的ProxyFactory代理,手动编程或配置进行代理都比较麻烦,引入了aspectj的某些功能

  • 引入了aspectj的pointcut表达式功能
  • 引入了上述注解功能

但是引入之后呢,还是全部转化成Spring原本的Advisor,最终仍然使用原本的ProxyFactory来创建代理,而不是像aspectj那样需要单独的编译器。

© 著作权归作者所有

共有 人打赏支持
乒乓狂魔
粉丝 1012
博文 105
码字总数 271356
作品 0
长宁
程序员
私信 提问
spring aop 切点声明

多条件 任意公共方法的执行: execution(public (..)) 任何一个以“set”开始的方法的执行: execution( set(..)) AccountService 接口的任意方法的执行: execution( com.xyz.service.Accou...

Canaan_
2017/11/05
0
0
在.NET Core中三种实现“可插拔”AOP编程方式(附源码)

一看标题肯定会联想到使用动态编织的方式实现AOP编程,不过这不是作者本文讨论的重点。 本文讨论另外三种在netcore中可实现的方式,Filter(过滤器,严格意义上它算是AOP方式),DynamicProx...

另一个老李
09/02
0
0
3幅图让你了解Spring AOP

AOP(Aspect Oriented Programming),是面向切面编程的技术。AOP基于IoC基础,是对OOP的有益补充。 AOP之所以能得到广泛认可,主要是因为它将应用系统拆分分了2个部分:核心业务逻辑(Core bu...

白志华
2015/10/18
18
0
Spring Aop配置时的切入点表达式

对应的中文: 任意公共方法的执行: execution(public (..)) 任何一个以“set”开始的方法的执行: execution( set(..)) AccountService 接口的任意方法的执行: execution( com.xyz.service...

cswy
2013/12/05
0
0
关于JFINAL对AOP的支持

@JFinal 你好,想跟你请教个问题:波总,群里总听大家在讨论AOP,按我原来使用JFINAL的理解,aop就当挡截器在用了,接收了controller的参数,增强了处理,后来听说jfinal又增加了业务层aop,d...

长篇小说
2016/02/04
1K
2

没有更多内容

加载失败,请刷新页面

加载更多

开源 java CMS - FreeCMS2.8会员我的评论

项目地址:http://www.freeteam.cn/ 我的评论 从左侧管理菜单点击我的评论进入。在这里可以查看当前登录会员的所有评论记录。 删除评论 选择评论然后点击删除按钮可以完成删除操作。 为了防止...

freeteam
18分钟前
1
0
Eureka Server启用 https服务指北

文章共 591字,阅读大约需要 2分钟 ! 概 述 在我的前文《Eureka Server 开启Spring Security Basic认证》中已经给 Eureka Server 开启了最基本的鉴权措施,本文则让 HTTPS加持于 Eureka Ser...

CodeSheep
56分钟前
17
0
OSChina 周二乱弹 —— 其实我在地板也睡不着

Osc乱弹歌单(2018)请戳(这里) 【今日歌曲】 @witt-z :分享歌词: 阴天 在不开灯的房间,当所有思绪都一点一点沉淀。 分享莫文蔚的单曲《阴天》: 《阴天》- 莫文蔚 手机党少年们想听歌,...

小小编辑
今天
530
9
微服务分布式事务实现

https://www.processon.com/view/link/5b2144d7e4b001a14d3d2d30

WALK_MAN
今天
3
0
《大漠烟尘》读书笔记及读后感文章3700字

《大漠烟尘》读书笔记及读后感文章3700字: 在这个浮躁的社会里,你有多久没有好好读完一本书了? 我们总觉得自己和别人不一样,所以当看到别人身上的问题时,很少有“反求诸己”,反思自己。...

原创小博客
今天
5
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部