spring学习总结(十):基于 XML 的配置AOP

这篇博客详细介绍了如何在Spring中使用XML配置进行AOP的声明,包括声明切面、切入点和通知。虽然AspectJ注解更常见,但XML配置提供了Spring特有的方式来定义切面。通知类型可以通过特定的XML元素来定义,并引用切入点表达式或直接包含切入点。

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

基于 XML 的配置声明AOP

  • 除了使用 AspectJ 注解声明切面, Spring 也支持在 Bean 配置文件中声明切面. 这种声明是通过 aop schema 中的 XML 元素完成的.
  • 正常情况下, 基于注解的声明要优先于基于 XML 的声明. 通过 AspectJ 注解, 切面可以与 AspectJ 兼容, 而基于 XML 的配置则是 Spring 专有的. 由于 AspectJ 得到越来越多的 AOP 框架支持, 所以以注解风格编写的切面将会有更多重用的机会.

声明切面

①.当使用xml声明切面时,需要在 <beans> 根元素中导入aop工作空间  aop Schema

②.在 Bean 配置文件中, 所有的 Spring AOP 配置都必须定义在 <aop:config> 元素内部. 对于每个切面而言, 都要创建一个 <aop:aspect> 元素来为具体的切面实现引用后端 Bean 实例. 

③.切面 Bean 必须有一个标示符, 供 <aop:aspect> 元素引用
<!-- 配置切面的bean -->
<bean id="loggerAspectJ"
	class="com.xyc.spring.aop.xml.LoggerAspectJ"></bean>
	
<bean id="viladationAspectj"
	class="com.xyc.spring.aop.xml.ViladationAspectj"></bean>
		
	
<!-- 配置AOP -->
<aop:config>
	<!-- 配置切面及通知 -->
	<aop:aspect ref="loggerAspectJ" order="2">
	</aop:aspect>
	<aop:aspect ref="viladationAspectj" order="1">
	</aop:aspect>
</aop:config>	
		

声明切入点

①.切入点使用 <aop:pointcut> 元素声明
②.切入点必须定义在 <aop:aspect> 元素下, 或者直接定义在 <aop:config> 元素下.
  • 定义在 <aop:aspect> 元素下: 只对当前切面有效
  • 定义在 <aop:config> 元素下: 对所有切面都有效
③.基于 XML 的 AOP 配置不允许在切入点表达式中用名称引用其他切入点. 

<!-- 配置切点表达式 -->
<aop:pointcut expression="execution(* com.xyc.spring.aop.xml.Calculator.*(..))" id="pointcut"/>

声明通知

  • 在 aop Schema 中, 每种通知类型都对应一个特定的 XML 元素. 
  • 通知元素需要使用 <pointcut-ref> 来引用切入点, 或用 <pointcut> 直接嵌入切入点表达式.  method 属性指定切面类中通知方法的名称.
<!-- 前置通知 -->
<aop:before method="beforeMethod" pointcut-ref="pointcut"/>
<!-- 后置通知 -->
<aop:after method="afterMethod" pointcut-ref="pointcut"/>
<!-- 返回通知 -->
<aop:after-returning method="afterReturning" pointcut-ref="pointcut" returning="result"/>
<!-- 异常通知 -->
<aop:after-throwing method="afterThrowing" pointcut-ref="pointcut" throwing="e"/>
 
 <!-- 环绕通知 -->
 <!-- <aop:around method="around" pointcut-ref="pointcut"/> -->

具体实现:

Calculator.java
/**
 * 
 * @ClassName:  Calculator   
 * @Description:计算器接口
 * @author: xyc 
 * @date:   2016年12月24日 下午2:45:58   
 *
 */
public interface Calculator {

    int add(int i, int j);
    
    int sub(int i, int j);
    
    int mul(int i, int j);
    
    int div(int i, int j);
    
CalculatorLogger.java
/**
 * 
 * @ClassName:  CalculatorLogger   
 * @Description:计算器实现类
 * @author: xyc 
 * @date:   2016年12月24日 下午2:46:11   
 *
 */
public class CalculatorLogger implements Calculator {

    @Override
    public int add(int i, int j) {
        int result = i + j;
        return result;
    }

    @Override
    public int sub(int i, int j) {
        int result = i - j;
        return result;
    }

    @Override
    public int mul(int i, int j) {
        int result = i * j;
        return result;
        
    }

    @Override
    public int div(int i, int j) {
        int result = i / j;
        return result;
    }

}
LoggerAspectJ.java
/**
 * 
 * @ClassName:  LoggerAspectJ   
 * @Description:把这个类声明为一个切面:需要先将该类放入到IOC容器中,然后在声明为切面
 * @author: xyc 
 * @date:   2016年12月24日 下午6:04:05   
 *
 */
public class LoggerAspectJ {

    
    public void beforeMethod(JoinPoint joinPoint){
        String methodName = joinPoint.getSignature().getName();
        List<Object> args = Arrays.asList(joinPoint.getArgs());
        System.out.println("The method "+methodName+" with "+args);
    }
    
    public void afterMethod(JoinPoint joinPoint){
        String methodName = joinPoint.getSignature().getName();
        //在后置通知中不能访问目标方法执行的结果
        System.out.println("The method "+methodName+" end ");
    }
    
    public void afterReturning(JoinPoint joinPoint,Object result){
        String methodName = joinPoint.getSignature().getName();
        System.out.println("The method "+methodName+" result "+result);
    }
    
    public void afterThrowing(JoinPoint joinPoint,Exception e){
        String methodName = joinPoint.getSignature().getName();
        System.out.println("The method "+methodName+" Exception "+e);
    }
    
    
    public Object around(ProceedingJoinPoint pjp){
        
        Object result = null;
        String methodName = pjp.getSignature().getName();
        
        try {
            //前置通知、
            System.out.println("The method "+methodName+" with "+Arrays.asList(pjp.getArgs()));
            //执行目标方法
            result = pjp.proceed();
            //返回通知
            System.out.println("The method "+methodName+" result "+result);
        } catch (Throwable e) {
            //异常通知
            System.out.println("The method "+methodName+" Exception "+e);
            throw new RuntimeException(e);
        }
        //后置通知
        System.out.println("The method "+methodName+" end ");
        return result;
    }
}

ViladationAspectj.java
public class ViladationAspectj {

    public void beforeMethod(JoinPoint joinPoint){
        String methodName = joinPoint.getSignature().getName();
        List<Object> args = Arrays.asList(joinPoint.getArgs());
        System.out.println("--->ViladationAspectj "+methodName+" with "+args);
    }
}

applicationAop-xml.xml
<?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: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/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd">

	<!-- 配置bean -->
	<bean id="calculator"
		class="com.xyc.spring.aop.xml.CalculatorLogger"></bean>


	<!-- 配置切面的bean -->
	<bean id="loggerAspectJ"
		class="com.xyc.spring.aop.xml.LoggerAspectJ"></bean>
		
	<bean id="viladationAspectj"
		class="com.xyc.spring.aop.xml.ViladationAspectj"></bean>
		
	
	<!-- 配置AOP -->
	<aop:config>
		<!-- 配置切点表达式 -->
		<aop:pointcut expression="execution(* com.xyc.spring.aop.xml.Calculator.*(..))" id="pointcut"/>
		<!-- 配置切面及通知 -->
		<aop:aspect ref="loggerAspectJ" order="2">
			<!-- 前置通知 -->
			<aop:before method="beforeMethod" pointcut-ref="pointcut"/>
			<!-- 后置通知 -->
			<aop:after method="afterMethod" pointcut-ref="pointcut"/>
			<!-- 返回通知 -->
			<aop:after-returning method="afterReturning" pointcut-ref="pointcut" returning="result"/>
			<!-- 异常通知 -->
			<aop:after-throwing method="afterThrowing" pointcut-ref="pointcut" throwing="e"/>
			 
			 <!-- 环绕通知 -->
			 <!-- <aop:around method="around" pointcut-ref="pointcut"/> -->
		</aop:aspect>
		<aop:aspect ref="viladationAspectj" order="1">
			<aop:before method="beforeMethod" pointcut-ref="pointcut"/>
		</aop:aspect>
	</aop:config>	
		
</beans>

ApplicationAopXml.java
/**
 * 
 * @ClassName:  ApplicationAop   
 * @Description:测试AOP
 * @author: xyc 
 * @date:   2016年12月24日 下午6:12:59   
 *
 */
public class ApplicationAopXml {

    public static void main(String[] args) {
        
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationAop-xml.xml");
        
        Calculator bean = (Calculator) context.getBean("calculator");
        
        int result = bean.add(3, 2);
        System.out.println("-->"+result);
        
        
        result = bean.div(9, 3);
        System.out.println("-->"+result);
    }
}





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值