AOP:面向切面编程
1.介绍——AOP:面向切面编程。正常程序都是从上到下执行相关代码,aop是在纵向执行流程中添加横切面, 从左到右的关系。不需要修改成语原有代码,它将代码动态的切入到类的指定方法、指定位置上的编程思想就是面向切面的编程。
特点:高扩展性、释放原有功能部分逻辑
eg:一般程序执行顺序,从上往下。
public class Demo {
public static void demo1() {
System.out.println("demo1");
}
public static void demo2() {
System.out.println("demo2");
}
public static void demo3() {
System.out.println("demo3");
}
public static void main(String[] args) {
demo1();
demo2();
demo3();
}
}
2.概念
(1)原有功能:切点,pointcut
(2)前置通知:在切点之前执行的功能,before advice
(3)后置通知:在切点之后执行的功能,after advice
(4)如果切点执行过程中出现异常,会触发异常通知,throws advice
(5)所有功能总称为切面
(6)织入:把切面嵌入到原有功能的过程
3.通知类型
(1)前置通知(Before advice):在某个连接点(Join point)之前执行的通知,但这个通知不能阻止连接点的执行(除非它抛出一个异常)。
(2)返回后通知(After returning advice):在某个连接点(Join point)正常完成后执行的通知。例如,一个方法没有抛出任何异常正常返回。
(3)抛出异常后通知(After throwing advice):在方法抛出异常后执行的通知。
(4)后置通知(After(finally)advice):当某个连接点(Join point)退出的时候执行的通知(不论是正常返回还是发生异常退出)。
(5)环绕通知(Around advice):包围一个连接点(Join point)的通知,如方法调用。这是最强大的一种通知类型。环绕通知可以在方法前后完成自定义的行为。它也会选择是否继续执行连接点或直接返回它们自己的返回值或抛出异常来结束行。
4.AOP实现切面过程
工程目录图:
(1)切入类的介绍:
public class Demo {
public void demo1() {
System.out.println("demo1");
}
public void demo2() {
System.out.println("demo2");
}
public void demo3() {
System.out.println("demo3");
}
}
(2)在环境xml中配置dtd说明文档:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context-3.0.xsd">
(3)对此对象的demo2()方法生成AOP切面:
<aop:config>
<aop:pointcut expression="excution(* com.likui.test.Demo.demo2())" id="mypoint"/>
</aop:config>
</beans>
(4)形成前置和后置通知:新建前置通知类继承前置接口
public class MyBeforeAdvice implements MethodBeforeAdvice{
@Override
public void before(Method arg0, Object[] arg1, Object arg2) throws Throwable {
// TODO Auto-generated method stub
System.out.println("执行前置通知!");
}
}
新建后置通知类继承后置通知接口
public class MyAfterAdvice implements AfterReturningAdvice{
@Override
public void afterReturning(Object arg0, Method arg1, Object[] arg2, Object arg3) throws Throwable {
// TODO Auto-generated method stub
System.out.println("执行后置通知!");
}
}
(5)xml文件中成前置、后置和切入类对象,对于切入点进行通知属性配置:
<!-- 配置通知类对象 -->
<bean id="mybefore" class="com.likui.advice.MyBeforeAdvice"></bean>
<bean id="myafter" class="com.likui.advice.MyAfterAdvice"></bean>
<!-- 配置切面 -->
<aop:config>
<!-- 配置切点 -->
<aop:pointcut expression="execution(* com.likui.test.Demo.demo2())" id="mypoint"/>
<!-- 配置通知 -->
<aop:advisor advice-ref="mybefore" pointcut-ref="mypoint"/>
<aop:advisor advice-ref="myafter" pointcut-ref="mypoint"/>
</aop:config>
<!-- 配置类对象 -->
<bean id="demo" class="com.likui.test.Demo"></bean>
(6)测试类编写:
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");
Demo demo=ac.getBean("demo",Demo.class);
demo.demo1();
demo.demo2();
demo.demo3();
}
}
(7)对Demo类中demo2()方法进行前置和后置切面结果展示: