Spring AOP、代理、基于代理类的AOP实现、AspectJ开发
文章目录
1 AOP
1.1 AOP简介
AOP(Aspect-Oriented Programming),即面向切面编程(也叫面向方面编程),是面向对象编程(OOP)的一种补充,是一种比较成熟的编程方式。
为了解决这一问题,AOP思想随之产生。AOP采取横向抽取机制,将分散在各个方法中的重复代码提取出来,然后在程序编译或运行时,再将这些提取出来的代码应用到需要执行的地方。这种采用横向抽取机制的方式,采用传统的OOP思想显然是无法办到的,因为OOP只能实现父子关系的纵向的重用。虽然AOP是一种新的编程思想,但却不是OOP的替代品,它只是OOP的延伸和补充。
AOP的使用,可以实开发者专注于核心业务的实现,不必过多关注其他辅助业务逻辑的实现,提高了开发效率,增强了代码的可维护性。
1.2 AOP术语
- 切面(Aspect):封装的用于横向插入系统功能(如事务、日志等)的类。
- 连接点(Joinpoint):在程序执行过程中的某个阶段点。
- 切入点(Pointcut):切面与程序的交叉点,即那些需要处理的连接点。
- Advice(通知/增强处理):AOP框架在特定的切入点执行的增强处理,即在定义好的切入点处所要执行的程序代码。可以将其理解为切面类中的方法。
- Target Object(目标对象):指所有被通知的对象,也被称为被增强对象。如果AOP框架采用的是动态的AOP实现,那么该对象就是一个被代理对象。
- Proxy (代理) :将通知应用到目标对象之后,被动态创建的对象。
- Weaving (织入) :将切面代码插入到目标对象上,从而生成代理对象的过程。
2 代理
2.1 静态代理
以日志的写法为例,来体验静态代理。通常日志的写法:
2.2 动态代理
2.2.1 JDK动态代理
两个方法:
- invoke:是接口InvocationHandler中定义的方法,在Java中叫作回调。一旦LogHandler被调用时,就会主动调用invoke方法。
- newProxy:主要作用是来创建proxy的,将我们的目标对象进行绑定,返回一个代理类。好处是可以代理任何东西,并没有限制在IHello接口上。
实际调用时,newProxy创建代理对象,(iHello.hello("Just")
)调用hello方法时,实际上调用了invoke方法。invoke中也是典型的面向切面的编程。
JDK动态代理的实现需要一个接口和一个实现类,不是很灵活。
2.2.2 基于CGLIB实现动态代理
CGLIB是可以直接对目标类进行动态代理。
3 基于代理类的AOP实现
3.1 Spring的通知类型
Spring按照通知在目标类方法的连结点位置,可以分为5种类型:
3.2 ProxyFactoryBean
ProxyFactoryBean是FactoryBean接口的实现类, FactoryBean负责实例化一个Bean ,而ProxyFactoryBean负责为其他Bean创建代理实例。在Spring中, 使用ProxyFactoryBean是创建AOP代理的基本方式。常用配置属性为:
4 AspectJ开发
4.1 概述
AspectJ是一个基于Java语言的AOP框架,它提供了强大的AOP功能。Spring 2.0以后,Spring AOP引入了对AspectJ的支持,并允许直接使用AspectJ进行编程,而Spring自身的AOP API也尽量与AspectJ保持一致。新版本的Spring框架,也建议使用AspectJ来开发AOP。使用AspectJ实现AOP有两种方式:一种是基于XML的声明式AspectJ, 另一种是基于注解的声明式AspectJ。
4.2 两种声明式AspectJ
4.2.1 基于XML的声明式AspectJ
通过XML方式来定义切面、切入点和通知,<aop:config>
元素极其子元素:
-
配置切面
配置切面使用<aop:aspect>
元素,该元素会将一个已经定义好的Bean转换成切面Bean,所以配置文件中需要预先定义好一个普通的Spring Bean。配置时需要指定id和ref两个属性:id定义该切面的唯一标识名称;ref用于引用普通的Bean。 -
配置切入点
当<aop:pointcut>
元素作为<aop:config>
元素的子元素定义时,表示该切入点是全局切入点,它可被多个切面所共享;当<aop:pointcut>
元素作为<aop:aspect>
元素的子元素时,表示该切入点只对当前切面有效。在定义<aop:pointcut>
元素时,通常会指定id和expression两个属性:id用于指定切入点的唯一标识名称;expression用于指定切入点关联的切入点表达式。
切入点表达式execution(* cn.edu.ujn.jdk.*.*(..))
:意思是匹配cn.edu.ujn.jdk
包中任意类的任意方法的执行。
解释:第一个*
代表返回类型为所有类型;cn.edu.ujn.jdk
为需要拦截的包名;第二个*
代表所有的类名;第三个*
代表所有方法;括号中的两个..
表示任意参数。
切入点表达式基本格式:execution(modifiers-pattern? ret-type-pattern declaring-tyoe-pattern name-pattern(param-pattern) throws-pattern?)
modifiers-pattern:定义的目标方法的访问修饰符,如public、private等。
ret-type-pattern:定义目标方法的返回值类型,如void、String等。
declaring-tyoe-pattern:定义目标方法的类路径,如cn.edu.ujn.jdk.UserDaoImpl
。
name-pattern:具体需要被代理的目标方法,如add方法。
param-pattern:需要被代理的目标方法包含的参数。
throws-pattern:需要被代理的目标方法抛出的异常类型。
注意:带有?的部分为可配置项,而其他部分属于必须配置项。 -
配置通知
使用<aop:aspect>
的子元素可以配置5种常用通知,这5个子元素不支持使用子元素,但在使用时可以指定一些属性其常用属性和描述如下:
4.2.2 基于注解的声明式AspectJ
AspectJ框架为AOP的实现提供了一套注解,用以取代Spring配置文件中为实现AOP功能所配置的臃肿代码。AspectJ的注解及其描述如下所示:
声明:
若本人发布的作品涉及版权或存在其他问题,请联系我删除。
谢谢浏览!