【Spring aop】Spring aop的XML和注解的两种配置实现
转载:http://blog.csdn.net/flysun3344/article/details/51679956
一:XML形式配置(传统aop联盟配置和AspectJ的aop配置)
- <?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:p="http://www.springframework.org/schema/p"
- xmlns:context="http://www.springframework.org/schema/context"
- xmlns:aop="http://www.springframework.org/schema/aop"
- 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">
- <!-- 切面类 -->
- <bean id="aop" class="cn.itcast.f_aop_xml.Aop"></bean>
- <!-- Aop配置 -->
- <aop:config>
- <!-- 定义一个切入点表达式: 拦截哪些方法 -->
- <aop:pointcut expression="execution(* cn.itcast.f_aop_xml.*.*(..))" id="pt"/>
- <!-- 切面 -->
- <aop:aspect ref="aop">
- <!-- 环绕通知 -->
- <aop:around method="around" pointcut-ref="pt"/>
- <!-- 前置通知: 在目标方法调用前执行 -->
- <aop:before method="begin" pointcut-ref="pt"/>
- <!-- 后置通知: -->
- <aop:after method="after" pointcut-ref="pt"/>
- <!-- 返回后通知 -->
- <aop:after-returning method="afterReturning" pointcut-ref="pt"/>
- <!-- 异常通知 -->
- <aop:after-throwing method="afterThrowing" pointcut-ref="pt"/>
- </aop:aspect>
- </aop:config>
- </beans>
注意对切面的配置有两种方式:一种是传统的aop联盟制定的aop通知的配置,一种是spring支持的AspectJ框架的切面
切入点表达式有如下形式:
- <!-- 定义一个切入点表达式: 拦截哪些方法 -->
- <!--<aop:pointcut expression="execution(* cn.itcast.g_pointcut.*.*(..))" id="pt"/>-->
- <!-- 【拦截所有public方法】 -->
- <!--<aop:pointcut expression="execution(public * *(..))" id="pt"/>-->
- <!-- 【拦截所有save开头的方法 】 -->
- <!--<aop:pointcut expression="execution(* save*(..))" id="pt"/>-->
- <!-- 【拦截指定类的指定方法, 拦截时候一定要定位到方法】 -->
- <!--<aop:pointcut expression="execution(public * cn.itcast.g_pointcut.OrderDao.save(..))" id="pt"/>-->
- <!-- 【拦截指定类的所有方法】 -->
- <!--<aop:pointcut expression="execution(* cn.itcast.g_pointcut.UserDao.*(..))" id="pt"/>-->
- <!-- 【拦截指定包,以及其自包下所有类的所有方法】 -->
- <!--<aop:pointcut expression="execution(* cn..*.*(..))" id="pt"/>-->
- <!-- 【多个表达式】 -->
- <!--<aop:pointcut expression="execution(* cn.itcast.g_pointcut.UserDao.save()) || execution(* cn.itcast.g_pointcut.OrderDao.save())" id="pt"/>-->
- <!--<aop:pointcut expression="execution(* cn.itcast.g_pointcut.UserDao.save()) or execution(* cn.itcast.g_pointcut.OrderDao.save())" id="pt"/>-->
- <!-- 下面2个且关系的,没有意义 -->
- <!--<aop:pointcut expression="execution(* cn.itcast.g_pointcut.UserDao.save()) && execution(* cn.itcast.g_pointcut.OrderDao.save())" id="pt"/>-->
- <!--<aop:pointcut expression="execution(* cn.itcast.g_pointcut.UserDao.save()) and execution(* cn.itcast.g_pointcut.OrderDao.save())" id="pt"/>-->
- <!-- 【取非值】 -->
- <!--<aop:pointcut expression="!execution(* cn.itcast.g_pointcut.OrderDao.save())" id="pt"/>-->
- <aop:pointcut expression=" not execution(* cn.itcast.g_pointcut.OrderDao.save())" id="pt"/>
切面类如下
- // 切面类
- public class Aop {
- public void begin(){
- System.out.println("开始事务/异常");
- }
- public void after(){
- System.out.println("提交事务/关闭");
- }
- public void afterReturning() {
- System.out.println("afterReturning()");
- }
- public void afterThrowing(){
- System.out.println("afterThrowing()");
- }
- public void around(ProceedingJoinPoint pjp) throws Throwable{
- System.out.println("环绕前....");
- pjp.proceed(); // 执行目标方法
- System.out.println("环绕后....");
- }
- }
调用的接口如下
- public class UserDao implements IUserDao{
- @Override
- public void save() {
- System.out.println("-----核心业务:保存!!!------");
- }
- }
测试类如下
- public class App {
- ApplicationContext ac =
- new ClassPathXmlApplicationContext("cn/itcast/f_aop_xml/bean.xml");
- // 目标对象有实现接口,spring会自动选择“JDK代理”
- @Test
- public void testApp() {
- IUserDao userDao = (IUserDao) ac.getBean("userDao");
- System.out.println(userDao.getClass());//$Proxy001
- userDao.save();
- }
- // 目标对象没有实现接口, spring会用“cglib代理”
- @Test
- public void testCglib() {
- OrderDao orderDao = (OrderDao) ac.getBean("orderDao");
- System.out.println(orderDao.getClass());
- orderDao.save();
- }
- }
上面的xml的配置主要是针对aspectJ框架支持的切面的配置。当前aop的配置基本上都用上面这种形式的配置。这里也简单介绍下传统的aop联盟定义的通知的配置方法,仅仅作为了解即可。aop联盟定义了五种通知类型如下:
我们在aop编程时需要自定义通知类,实现上面的五种通知就可以了;例子如下:
传统aop联盟配置方式一如下:
传统aop联盟配置方式二:只需将上面的<aop:config>替换为BeanNameAutoProxyCreator的配置即可,如下:
二:注解形式配置
配置文件
- <?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:p="http://www.springframework.org/schema/p"
- xmlns:context="http://www.springframework.org/schema/context"
- xmlns:aop="http://www.springframework.org/schema/aop"
- 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">
- <!-- 开启注解扫描 -->
- <context:component-scan base-package="cn.itcast.e_aop_anno"></context:component-scan>
- <!-- 开启aop注解方式 -->
- <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
- </beans>
切面类如下;
- @Component
- @Aspect // 指定当前类为切面类
- public class Aop {
- // 指定切入点表单式: 拦截哪些方法; 即为哪些类生成代理对象
- @Pointcut("execution(* cn.itcast.e_aop_anno.*.*(..))")
- public void pointCut_(){
- }
- // 前置通知 : 在执行目标方法之前执行
- @Before("pointCut_()")
- public void begin(){
- System.out.println("开始事务/异常");
- }
- // 后置/最终通知:在执行目标方法之后执行 【无论是否出现异常最终都会执行】
- @After("pointCut_()")
- public void after(){
- System.out.println("提交事务/关闭");
- }
- // 返回后通知: 在调用目标方法结束后执行 【出现异常不执行】
- @AfterReturning("pointCut_()")
- public void afterReturning() {
- System.out.println("afterReturning()");
- }
- // 异常通知: 当目标方法执行异常时候执行此关注点代码
- @AfterThrowing("pointCut_()")
- public void afterThrowing(){
- System.out.println("afterThrowing()");
- }
- // 环绕通知:环绕目标方式执行
- @Around("pointCut_()")
- public void around(ProceedingJoinPoint pjp) throws Throwable{
- System.out.println("环绕前....");
- pjp.proceed(); // 执行目标方法
- System.out.println("环绕后....");
- }
- }
接口类如下:
- @Component // 加入容器
- public class UserDao implements IUserDao{
- @Override
- public void save() {
- System.out.println("-----核心业务:保存!!!------");
- }
- }
测试类如下:
同一种的测试类