Spring AOP基于xml的配置以及使用

本文介绍Spring AOP(面向切面编程)的概念与实践,详细解释为何需要AOP,通过实例展示如何利用AOP减少代码重复,提高代码可维护性。包括AOP的配置方法、通知类型及测试过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

   Spring AOP,也就是面向切面编程,是对于面向对象编程的一种补充,也是Spring框架的一项重要内容,核心思想是动态代理。

为什么需要AOP:

        但我们在开发的过程中,我们慢慢会发现,有一些代码会不断重复出现,而且随着代码量增大,这一类代码会不断的重复出现,如果没有使用AOP,这一类的代码我们一般会采取复制粘贴的方式去解决,但是这样会造成难以维护,假如有一天,我们需要对这一类重复代码进行修改,还得找到每一个用到这重复代码进行修改,这样就会比较麻烦,还容易出错。这时候,如果我们能够把这类重复代码单独提取出来,就可以对它进行单独处理,并且也不用复制粘贴了,这就很方便了,而这就是AOP。

       假如,我们有一个用户操作类,里面封装着对用户数据的操作,有保存,更新,删除等方法,这些方法都有共同的部分,每次执行操作前都需要开启事务,和操作后关闭事务。使用AOP我们就可以将这些操作事务的部分给提取出来。AOP就是类似这种应用

Spring AOP的用法例子:

  1. 导包,需要导入(Maven导包)                                                                                                                                                
    <dependency>
    	<groupId>org.springframework</groupId>
    	<artifactId>spring-aop</artifactId>
    	<version>4.3.20.RELEASE</version>
    </dependency>

     

  2. 编写需要增强的类UserServiceImpl

    package com.springday.service;
    
    public interface UserService {
    	public void save();
    	
    	public void delete();
    	
    	public void update();
    	
    	public void find();
    }

     

    package com.springday.service;
    
    public class UserServiceImpl implements UserService {
    
    	@Override
    	public void save() {
    		System.out.println("保存操作");//模拟进行操作
    	}
    
    	@Override
    	public void delete() {
    		System.out.println("删除操作");
    
    	}
    
    	@Override
    	public void update() {
    		System.out.println("更新操作");
    	}
    
    	@Override
    	public void find() {
    		System.out.println("查找操作");
    	}
    
    }

      

  3. 编写通知类MyAdvice

    package com.springday.springaop;
    
    import org.aspectj.lang.ProceedingJoinPoint;
    
    //通知类
    public class MyAdvice {
    	
    	//前置通知	
    //		|-目标方法运行之前调用
    	//后置通知(如果出现异常不会调用)
    //		|-在目标方法运行之后调用
    	//环绕通知
    //		|-在目标方法之前和之后都调用
    	//异常拦截通知
    //		|-如果出现异常,就会调用
    	//后置通知(无论是否出现 异常都会调用)
    //		|-在目标方法运行之后调用
    //----------------------------------------------------------------
    	//前置通知
    	public void before(){
    		System.out.println("这是前置通知!!");
    	}
    	//后置通知
    	public void afterReturning(){
    		System.out.println("这是后置通知(如果出现异常不会调用)!!");
    	}
    	//环绕通知
    	public Object around(ProceedingJoinPoint pjp) throws Throwable {
    		System.out.println("这是环绕通知之前的部分!!");
    		Object proceed = pjp.proceed();//调用目标方法
    		System.out.println("这是环绕通知之后的部分!!");
    		return proceed;
    	}
    	//异常通知
    	public void afterException(){
    		System.out.println("出事啦!出现异常了!!");
    	}
    	//后置通知
    	public void after(){
    		System.out.println("这是后置通知(出现异常也会调用)!!");
    	}
    }

     

  4.  在Spring的配置文件applicationContext.xml进行AOP配置如下 

    <?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: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-4.3.xsd
    		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
    		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd">
    	
    	
    	 <!-- 导入AOP(约束)命名空间 -->
    	 <!-- 1、配置目标对象 -->
    	 <bean name="userServiceTarget" class="com.springday.service.UserServiceImpl"></bean>
    	 <!-- 2、配置通知对象 -->
    	 <bean name="myAdvice" class="com.springday.springaop.MyAdvice"></bean>
    	 <!-- 3、配置将通知织入目标对象 -->
    	 <aop:config>
    	 	<!-- 配置切入点(要增强的方法) 
    	 		public void com.springday.service.UserService.save()
    	 	    void com.springday.service.UserService.save()
    	 	    * com.springday.service.UserService.save() //任意返回类型
    	 	    * com.springday.service.UserService.*()  //对所有UserService所有方法进行增强
    	 	    * com.springday.service.UserService.*(..) //对传入的参数不作要求
    	 	    * com.springday.service.*Service.*(..)
    	 	    * com.springday.service..*Service.*(..)
    	 	-->
    	 	<aop:pointcut expression="execution(* com.springday.service.*Service.*(..))" id="pc"/>
    	 	<aop:aspect ref="myAdvice">
    	 		<!-- 指定名为before的方法作为前置通知-->
    	 		<aop:before method="before" pointcut-ref="pc"/>
    	 		<!-- 后置 -->
    	 		<aop:after-returning method="afterReturning" pointcut-ref="pc"/>
    	 		<!-- 环绕通知 -->
    	 		<aop:around method="around" pointcut-ref="pc"/>
    	 		<!-- 异常拦截通知 -->
    	 		<aop:after-throwing method="afterException" pointcut-ref="pc"/>
    	 		<!-- 指定名为after的方法作为后置通知-->
    	 		<aop:after method="after" pointcut-ref="pc"/>
    	 	</aop:aspect>
    	 </aop:config>
    </beans>

     

  5.  编写测试类,测试配置了AOP后增强的方法

    package com.springday.springaop;
    
    import javax.annotation.Resource;
    
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.test.context.ContextConfiguration;
    import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
    import com.springday.service.UserService;
    
    //创建容器
    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration("classpath:com/springday/springaop/applicationContext.xml")
    public class Demo {
    	
    	@Resource(name="userServiceTarget")
    	private UserService us;
    	
    
    	@Test //测试注解
    	public void fun1() {
    		us.save();
    	}
    }
    

     

  6. 运行结果显示如下 

     可以看到,我们在执行保存操作时,多了上面红框的内容,只要符合配置上面切入点表达式的,

    <aop:pointcut expression="execution(* com.springday.service.*Service.*(..))" id="pc"/>

    都会执行一遍通知类的方法 

     

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值