spring中AOP代理由spring的IOC容器负责生成,管理,其依赖管理也由IOC容器负责管理,因此,AOP代理可以直接使用容器总的其他bean实例作为目标,这种管理可由IOC容器的依赖注入提供。spring默认使用java动态代理来创建AOP 代理,这样就可以为任何接口实例创建代理了。
spring也可以使用cglib的动态代理,关于jdk动态代理和cglib动态代理之间的区别和联系,请看小编《细说java动态代理和cglib动态代理》,当我们配置了cglib之后,在需要代理类而不是代理某个接口的时候,spring框架会自动切换为cglib。但是默认上使用jdk的动态代理,如果需要我们可以通过配置文件,强制使用cglib代理。
通过上篇博客《Spring的AOP-AspectJ 的静态实现》,我们不难发现,要实现AOP,程序员主要需要下面的操作:
* 定义普通的业务组件
* 定义切入点,一个切入点可能横切多个业务组件
* 定义增强处理,增强处理就是在AOP框架为普通业务组件织入的处理动作;
重点操作在于后两步,所以AOP的代理工作可以整合为下列的公式:
AOP代理的方法 = 增强处理 + 目标对象的方法
spring实现AOP主要有两种方式:
1. 基于注解的“零配置”方式
这里的注解主要是指@Before……,@aspect ;具体操作请继续看:
✎ 启动对AspectJ的支持
<span style="font-family:SimSun;font-size:18px;"><aop:aspectj-autoproxy/></span>
✎ 定义切面bean
当启动了AspectJ的支持后,我们只需要在spring容器中配置一个带@Aspect注解的Bean,spring将会自动识别该Bean,并将该Bean作为切面处理:
<span style="font-family:SimSun;font-size:18px;">package com.ysc.spring; import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; @Aspect public class SecurityHandler { // 这里是该类中的内容 }</span>
使用@aspect注解标注一个java类,该java类将会作为切面bean。而负责自动增强的后处理Bean将会略过该bean,不会对该bean进行任何增强处理;当spring容器检测到某个bean类使用了@aspect注解的修饰之后,spring容器不会对该bean进行增强,所以无需担心该bean类会被增强处理;
✎ Before的增强处理
PS:增强处理有多种方式,这里以Before的增强处理为例:
<span style="font-family:SimSun;font-size:18px;">@Before("adAddMethod()") //@After("adAddMethod()") private void checkSecurity(){ System.out.println("-----------checkSecurity----------"); }</span>
我们对checkSecurity()方法进行Before的增强处理,而被增强的java方法是adAddMethod,这就意味着该add方法将被进行 执行前 检查安全性的增强处理,我们编写一个client.java 的类,执行对UserManager的方法的调用,查看 当前的Add方法被添加增强处理之后的效果:
public class Client { /** * @param args */ public static void main(String[] args) { BeanFactory factory = new ClassPathXmlApplicationContext("applicationContext.xml"); UserManager userManager = (UserManager)factory.getBean("userManager"); userManager.findUserById(1); userManager.modifyUser(1, "lisi", "123"); userManager.addUser("张三", "123"); } }
查看执行结果如下:
-------------userManager.findUserById()---------
-------------userManager.modifyUser()---------
-----------checkSecurity----------
-------------userManager.add()---------
发现只有被添加增强处理的add方法被执行了安全性检查的方法,且在add方法执行之前执行的安全检查,所以使用Before增强处理只能在目标方法执行之前织入增强,而after同理,只能在目标方法执行之后织入增强;
2.基于xml配置文件的管理方式
✎ 配置切面
<span style="font-family:SimSun;font-size:18px;"><aop:config> <aop:aspect id="" ref=""> …… </aop:aspect> </aop:config></span>
✎ 配置增强处理
<span style="font-family:SimSun;font-size:18px;">package com.ysc.spring; import org.aspectj.lang.JoinPoint; public class SecurityHandler { private void checkSecurity(JoinPoint joinpoint){ for(int i =0;i<joinpoint.getArgs().length;i++){ System.out.println(joinpoint.getArgs()[i]); } System.out.println(joinpoint.getSignature().getName()); System.out.println("-----------checkSecurity----------"); } }</span>
✎ 配置切入点
<span style="font-family:SimSun;font-size:18px;"><aop:pointcut expression="execution(* add*(..))" id="addAddMethod"/></span>
这时, 编译Client.java 类,依旧可以实现零配置方式的效果,所以不管是零配置的方式还是基于xml的方式,都可以在spring框架的基础上实现AOP。
当我们理解并清晰了Spring的AOP实现原理之后,发现它其实并不神秘,希望能帮到你更好的理解AOP这个“神秘”的切面编程理念!!