面向切面(AOP)开发

AOP是什么

AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,是一种概念,通过预编译方式和运行期间动态代理实现程序功能的统一维护的一种技术。使用Aop开发,使得业务逻辑各部分之间的耦合度降低,使你的业务逻辑更关注自己本身的业务,提高程序的可重用性,同时提高了开发的效率。
举个最简单的例子就是权限登录问题,有些类需要登录后才能被允许访问,所以需要在调用这些类之前,需要进行拦截(前);或者多个类中,你需要知道这些类中的方法被调用时,执行市场是多少(前后)等。
其AOP的目的就是对代码本身来说,无法满足需求时,对它进行增强,来满足业务需求。当然它的需求是建立在原有业务逻辑之上的,不能且无法修改原有的业务逻辑!

AOP实现方案

实现Aop的方案有多种:静态代理、动态代理、springAop、spring拦截器、sevlet过滤器、AspectJ。其实springaop的底层实现就是依赖动态代理实现的,但是springaop是它封装的动态代理,那么当然你也可以自已进行动态代理的编程,所以我也把代理模式纳为了实现Aop的方式中。看到网上都说aop是spring的产物,这跟spring有什么关系,难道你实现aop,必须依赖spring吗。

静态代理

在编译期的时候,生成代理对象,其实通过代理模式来实现的AOP,就是在代理对象中被增强的方法前后加入了增强的代码逻辑。

动态代理

与静态代理同理,只不过动态代理是在运行期时织入。实现方式有两种:

  1. jdk本身的动态代理:依赖java.lang.reflect包下的InvocationHandler和Proxy类,实现原理是为被代理的业务接口生成代理类,将AOP逻辑写入到代理类中,在运行期时动态织入AOP,使用反射执行织入的逻辑。
  2. cglib动态代理:CGLib是动态代码字节生成的实现,它封装字节码生成工具Asm,原理是在运行期间目标字节码加载后,针对代理的类,动态生成一个目标类的子类, 然后子类覆盖代理类中的方法, 如果是private或是final类修饰的方法,则不会被重写。将切面逻辑加入到子类中,所以使用Cglib实现AOP不需要基于接口。

springAop

spring AOP基于动态代理的方式,对原来的业务类生成代理对象(在运行期通过反射技术生成的),其原理就是生产一个代理对象,增强后的方法在代理对象中,调用的时候,调用的是这个代理对象中的方法。

  1. springAop的术语:
    (1)Join Point连接点:程序执行的一个点,就是对要被增强的那个方
    法的一个定义。
   (2)PointCut切入点:切入点,肯定不是要切1个、2个点,肯定是
   现在或将来会有多个要被切,否则你直接在这两个上面直接添加
   逻辑不就得了,干嘛还要整这么麻烦,所以切点就是切多个点,切入点就是
   要被切的点的一个集合,就是Join Point的集合。
  (3)introduction:spring4提出的新特性
  (4)Target Object目标对象:被增强的方法所在的类的对象,被称为目标对象,
  增强后的方法在代理对象中,所以原有的对象为目标对象,增强后的方法
  所在的对象为代理对象。因为spring的aop是用动态代理实现的,所以它
  是把被增强的方法所在的类生成一个代理对象,被增强的方法增强后都
  在这个代理对象中。
  (5)Aop Proxy Aop代理:Target Object目标对象中提到的代理对象。
  (6)Weaving织入:就是要把切面切进去到完成的这个过程,也就是增强的
  过程被称为织入,是个动词。
  (7)Advance增强:描述了增强的逻辑和增强的方式。增强的逻辑就是要
  增强的代码,比如打印时间等逻辑,增强的方式就是对被切的点怎么增强,
  有(Before、After、Around、AfterReturning、AfterThrowing)5种增强方式。
  (8)切面:下面这张图应该能说明白  

切面
其实spring的aop很简单,就是对被增强的方法所在的类创建一个代理对象,这个代理对象中的方法是增强后的方法。表面上你看到的是调用的原对象,其实在执行过程中调用的是代理对象中的方法。spring的aop它的底层是基于动态代理实现的。springaop的动态代理把那两种代理方式都使用了,会优先使用jdk自带的代理方式,如果没有接口,则使用cglib代理。

  1. 常用的springAop的实现方式:
(1)springaop配置xml方式(配置文件中的aop相关的标签,是spring定
	义的,不是aspectj的)
(2)springaop注解@Aspectj方式(配置切面时的注解是aspectj的,
	是其核心仍是动态代理):
	说明:@AspectJ使用了Java 5的注解,可以将切面声明为普通的Java类。
	@AspectJ样式在AspectJ 5发布的AspectJ project部分中被引入。
	Spring 2.0使用了和AspectJ 5一样的注解,并使用AspectJ来做切
	入点解析和匹配。但是,AOP在运行时仍旧是纯的Spring AOP,并
	不依赖于AspectJ的编译器或者织入器(weaver)。

AspectJ

aspectj是原始的 aop 技术, 是Java语言的扩展,定义了AOP语法,提供了非常完善的AOP能力,几乎能在java class的任何时刻使用织入功能,它有一个专门的编译器(ajc)用来生成遵守Java字节编码规范的Class文件,可以对类的成员变量,方法等进行拦截。Spring的AOP技术只限于对bean中的方法进行拦截,所以比springAop要复杂的多。

springAopaspectj
在纯 Java 中实现使用 Java 编程语言的扩展实现
不需要单独的编译过程除非设置 LTW,否则需要 AspectJ 编译器 (ajc)
只能使用运行时织入运行时织入不可用。支持编译时、编译后和加载时织入
功能不强-仅支持方法级编织更强大 - 可以编织字段、方法、构造函数、静态初始值设定项、最终类/方法等…。
只能在由 Spring 容器管理的 bean 上实现可以在所有域对象上实现
仅支持方法执行切入点支持所有切入点
代理是由目标对象创建的, 并且切面应用在这些代理上在执行应用程序之前 (在运行时) 前, 各方面直接在代码中进行织入
比 AspectJ 慢更好的性能
易于学习和应用相对于 Spring AOP 来说更复杂
AspectJ 的AOP,可以在三种时期进行代理,或者注入:
1.编译时织入
利用ajc编译器替代javac编译器,直接将源文件(java或者aspect文件)编
译成class文件并将切面织入进代码。

2.编译后织入
利用ajc编译器向javac编译期编译后的class文件或jar文件织入切面代码。

3.加载时织入
不使用ajc编译器,利用aspectjweaver.jar工具,使用java agent代理在
类加载期将切面织入进代码。(aspectjweaver.jar中,存在着@Before,@After注解,
并且有他们织入的实现(ASM动态代理))

具体aspectj的实现请自行google,说实话,开发以来,spring的aop已经满足了需求,还没遇见过变态的需求,也就还没使用过aspectj

其他行为AOP

从上述AOP中,体会到aop就是在被拦截的对象周围执行其他逻辑。那我就想到了拦截器、过滤器,他们也是起到了该作用效果,只不过没有那么细腻而已,所以我自己认为下述两种方式也可以理解为AOP的实现。

过滤器

拦截的是web访问url地址,严格意义上讲,filter只是适用于web中,依赖于Servlet容器,利用Java的回调机制进行实现,和框架无关,可以控制最初的http请求,但是更细一点的类和方法控制不了。

拦截器

  1. spring的拦截器:有两个
    (1)HandlerInterceptor是springMVC项目中的拦截器,它拦截的目标是请求的地址,比MethodInterceptor先执行。
    (2)MethodInterceptor是AOP项目中的拦截器,它拦截的目标是方法,即使不是controller中的方法。
  2. 使用动态代理自行代码实现。

区别

拦截器和过滤器,虽然作用效果相同,但是其作用的对象不同。我认为拦截器和过滤器可以从两方面来理解:

  1. 感观上
    (1)首先就是作用的对象不同
    (2)过滤器就是从现有数据中,过滤出来想要的数据,而拦截器是在执行被拦截的方法前,再添加一些其他的逻辑
  2. 实现上
    (1)拦截器是基于java的反射机制,使用代理模式,而过滤器是基于函数回调。
    (1)拦截器不依赖servlet容器,过滤器依赖于servlet容器。
    (2)拦截器只能对controller起作用,而过滤器可以对几乎所有的请求起作用(可以保护资源)。
    (3)拦截器可以访问controller上下文,堆栈里面的对象,而过滤器不可以。
    (4)执行顺序:过滤器–>拦截器–>controller或者method–>拦截器–>过滤器

总结:从上述内容来看,除了aspectj和过滤器,其他的aop实现都是通过代理模式实现的。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值