切面编程(三)
一、XML实现AOP编程
spring提供了注解的形式实现aop编程,同时也提供xml配置的形式实现,形式不同,最终实现的效果是一致的,下面进行xml实现aop编程的demo具体实现
步骤1.编写切面和切入点
package com.jyk.spring.aop2; import org.aspectj.lang.ProceedingJoinPoint; public class UserAop { //前置通知,执行目标方法前执行 public void begin() { System.out.println("开启事务"); } //后置通知,执行目标方法后执行 public void commit() { System.out.println("结束事务"); } //返回后通知,目标方法调用结束后执行,出现异常不执行 public void afterRunning() { System.out.println("目标方法调用结束后执行"); } //异常通知,目标方法调用发生异常时执行 public void throwException() { System.out.println("执行目标方法出现了异常"); } //环绕通知,环绕目标方法执行 public void arround(ProceedingJoinPoint pj)throws Throwable { System.out.println("环绕前"); //执行目标方法 pj.proceed(); System.out.println("环绕后"); } }
步骤2.编写业务接口和实现
package com.jyk.spring.aop2; public interface UserInterface { public void add(); public void delete(); }
package com.jyk.spring.aop2; public class UserImpl implements UserInterface{ @Override public void add() { System.out.println("核心业务1"); } @Override public void delete() { System.out.println("核心业务2"); } }
步骤3.在配置文件中将切面和业务实现类加入IOC容器,并配置切入点表达式
<?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" xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd "> <!-- 将切面类加入IOC容器 --> <bean id="userAop" class="com.jyk.spring.aop2.UserAop"></bean> <!-- 将业务实现类加入IOC容器 --> <bean id="userImpl" class="com.jyk.spring.aop2.UserImpl"></bean> <!-- Aop配置 --> <aop:config> <!-- 定义一个切入点表达式: 拦截哪些方法 --> <!-- com.jyk.spring.aop2.*.*(..)意为拦截该包下所有类的所有方法 --> <aop:pointcut expression="execution(* com.jyk.spring.aop2.*.*(..))" id="pt" /> <!-- 切面 --> <aop:aspect ref="userAop"> <!-- 环绕通知 --> <aop:around method="arround" pointcut-ref="pt" /> <!-- 前置通知: 在目标方法调用前执行 --> <aop:before method="begin" pointcut-ref="pt" /> <!-- 后置通知: --> <aop:after method="commit" pointcut="execution(* com.jyk.spring.aop2.*.*(..))" /> <!-- 返回后通知 --> <aop:after-returning method="afterRunning" pointcut-ref="pt" /> <!-- 异常通知 --> <aop:after-throwing method="throwException" pointcut-ref="pt" /> </aop:aspect> </aop:config> </beans>
步骤4.验证结果,结果参见切面编程(二),效果与注解实现一致。
ApplicationContext ac = new ClassPathXmlApplicationContext("aop_xml.xml"); //目标对象有实现接口,Spring会默认使用JDK代理 @Test public void testJDK() { UserInterface ui = (UserInterface) ac.getBean("userImpl"); System.out.println(ui.getClass()); ui.add(); ui.delete(); }
二、切入点表达式
切入点表达式的使用丰富多样,可以对指定的“方法”进行拦截; 从而给指定的方法所在的类生层代理对象,下面简单介绍常见的切入点表达式
<!-- Aop配置 --> <aop:config> <!-- 定义一个切入点表达式: 拦截哪些方法 --> <aop:pointcut expression="execution(* com.jyk.spring.aop2.*.*(..))" id="pt"/> <!-- 【拦截所有public方法】 --> <aop:pointcut expression="execution(public * *(..))" id="pt"/> <!-- 【拦截所有save开头的方法 】 --> <aop:pointcut expression="execution(* add*(..))" id="pt"/> <!-- 【拦截指定类的指定方法, 拦截时候一定要定位到方法】 --> <aop:pointcut expression="execution(public * com.jyk.spring.aop2.UserImpl.add(..))" id="pt"/> <!-- 【拦截指定类的所有方法】 --> <aop:pointcut expression="execution(* com.jyk.spring.aop2.UserImpl.*(..))" id="pt"/> <!-- 【拦截指定包,以及其自包下所有类的所有方法】 --> <aop:pointcut expression="execution(* com.jyk.spring..*.*(..))" id="pt"/> <!-- 【多个表达式】 --> <aop:pointcut expression="execution(* com.jyk.spring.aop2.UserImpl.add()) || execution(* com.jyk.spring.aop2.StudentImpl.add())" id="pt"/> <aop:pointcut expression="execution(* com.jyk.spring.aop2.UserImpl.add()) or execution(* com.jyk.spring.aop2.StudentImpl.add())" id="pt"/> <!-- 【取非值】 --> <aop:pointcut expression="!execution(* com.jyk.spring.aop2.UserImpl.add())" id="pt"/> <aop:pointcut expression=" not execution(* com.jyk.spring.aop2.UserImpl.add())" id="pt"/> <!-- 切面 --> <aop:aspect ref="aop"> <!-- 环绕通知 --> <aop:around method="around" pointcut-ref="pt"/> </aop:aspect> </aop:config>