AOP 面向切面编程,和IOC 控制反转是 Spring 框架的两个重要思想。
AOP以自己的话来说,以一个对象的某个方法为切点,在这个切点的前后加上一些增强功能,使得该整体具有更多的功能。
看以下代码的例子
原本我是直接回家(目标:gohome)就这么一件事,但是事情并不那么简单,以我要回家这个点,前前后后都发生了事情。
所发生的事(advice)作为一个切面切入到我要回家的这件事中。于是,我在回家之前得做什么,回家之后得做什么,都在切面安排好了。
还可以以切面中的某个点切入其他事情,如果事情太多,还可以有多个切面同时切入一个点。当然一个整体可以有多个切点。切面中的功能可以切入到切点的前面或后面。
package com.springAOP;
public class Gohome {
public Gohome() {
}
public String goHome() {
System.out.println("开开心心回家咯-----(目标对象)");
// int i = 1 / 0; //制造一个异常
return "吃饱喝足后去散散步吧";
}
}
定义一个切面
package com.springAOP;
import org.aspectj.lang.ProceedingJoinPoint;
public class Advice {
//出现异常后调用的通知
public void afterException() {
System.out.println("突发事件:被老板叫住,需要处理完额外的任务才能走!!!!!!!(出现异常调用的通知)");
}
//前置通知
public void work() {
System.out.println("不知不觉到了下班时间,收拾好准备回家吧。。(前置通知)");
}
//环绕通知
public Object around(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("回家前,整理邮件(环绕通知前)");
Object proceed = pjp.proceed();
System.out.println("回家后,整理邮件(环绕通知后)");
return proceed;
}
//后置通知(出现异常也会调用)
public void cookie() {
System.out.println("今天就做辣椒炒肉做晚餐吧(后置通知:出现异常也会调用)");
}
//后置通知(出现异常不用调用)
public void afterReturning(Object value) {
System.out.println(value + "(后置通知:出现异常不会调用)");
}
}
把这个切面切入到目标对象中(配置文件 applicationContext.xml)需要导入 aop 约束
配置切入点时,第一个 * 号表示任意访问修饰符,一般为 public ,该 * 可以省略
第二个 * 号表示返回值任意,方法名也可以写成 * 号,表示其中的所有方法都要执行配置的通知。
括号中的两个点表示参数任意,可有可无
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/beans"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd ">
<!-- 配置目标对象 -->
<bean name="gohome" class="com.springAOP.Gohome"></bean>
<!-- 配置通知对象 -->
<bean name="advice" class="com.springAOP.Advice"></bean>
<!-- 配置将通知织入目标对象 -->
<aop:config>
<!-- 配置切入点 -->
<aop:pointcut expression="execution(* *com.springAOP.Gohome.goHome(..))" id="pc"/>
<!-- 配置切面 -->
<aop:aspect id="aspect" ref="advice">
<!-- 异常通知 -->
<aop:after-throwing method="afterException" pointcut-ref="pc"/>
<!-- 前置通知 -->
<aop:before method="work" pointcut-ref="pc"/>
<!-- 环绕通知 -->
<aop:around method="around" pointcut-ref="pc"/>
<!-- 后置通知 (出现异常也会通知)-->
<aop:after method="cookie" pointcut-ref="pc"/>
<!-- 后置通知 (出现异常不会通知) returning 用来接收目标对象的返回值(无返回值则不接收)-->
<aop:after-returning method="afterReturning" pointcut-ref="pc" returning="value"/>
</aop:aspect>
</aop:config>
</beans>
执行目标对象的动作
package com.springAOP;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test {
public static void main(String[] args) {
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
Gohome gh = (Gohome) ac.getBean("gohome");
gh.goHome();
}
}
执行结果:
本来我执行的 goHome,但是 advice 中的各个方法也都执行了,说明那些方法确实切进来了。
以上是以个人理解举的例子,仅供参考!