1、在XML配置文件中配置切面、切入点、增强处理。spring-1.5之前只能使用XML Schema方式配置切面、切入点、增强处理。

spring配置文件中,所有的切面、切入点、增强处理都必须定义在<aop:config.../>元素内部。<beans.../>元素可以包含多个<aop:config.../>元素,一个<aop:config>可以包含pointcut、advisor、aspect元素,且三个元素必须按照此顺序来定义。其中aspect下可以包含多个子元素。

使用<aop:config.../>方式进行配置时,可能与spring的自动代理方式相冲突,例如使用<aop:aspectj-autoproxy>或类似方式显示启用了自动代理,则可能导致出现问题(比如有些增强处理没有被织入)。所以要么全使用<aop:config.../>的配置方式,要么全使用自动代理方式,不要混合使用。

2、配置切面

使用<aop:aspect.../>定义,bean可以是Java bean也可以是容器bean(即可以给bean注入依赖),如果切面bean是容器bean,<aop:aspect.../>使用ref属性引用。使用<aop:aspect.../>可以指定的属性:

1》id:定义该切面的标识名。

2》ref:用于将ref引用的容器bean转换成切面bean。

3》order:指定该切面bean的优先级,该属性的作用与前面@AspectJ中的@Order注解、Ordered接口的作用完全一样,order属性值越小,该切面对应的优先级越高。

3、配置增强处理

使用XML配置增强处理需要以下元素:

<aop:before.../>:配置Before增强处理。

<aop:after.../> :配置After增强处理。

<aop:after-returning.../>:配置AfterReturning增强处理。

<aop:after-throwing.../>:配置AfterThrowing增强处理。

<aop:around.../>:配置Around增强处理。

这些元素都不支持使用子元素,但可以指定以下属性:

pointcut:指定一个切入点表达式,spring将在匹配该表达式的连接点时织入该增强处理。

pointcut-ref:该属性指定一个已经存在的切入点名称,通常pointcut、pointcut-ref两个属性只是用其中之一。

method:该属性指定一个方法名,指定将切面bean的该方法转换为增强处理。

throwing:该属性只对<after-throwing.../>元素有效,用于指定一个形参名,AfterThrowing增强处理方法可通过该形参访问目标方法所抛出的异常。

returning:该属性只对<after-returning.../>元素有效,用于指定一个形参名,AfterReturning增强处理方法可通过该形参访问目标方法的返回值。

当定义切入点表达式时,XML配置方式完全支持excution、within、args、this、target、bean等切入点指示符。

      要组合切入点表达式时,使用的是and(相当于&&)、or(相当于||)、not(相当于!)

举个例子:

HelloImpl.java

package com.lfy.impl;

import com.lfy.bean.Hello;

/**
* 被增强的目标类
* @author lfy
*
*/
public class HelloImpl implements Hello { @Override
public void foo() { System.out.println("执行Hello组件的foo()方法");
} @Override
public void addUser(String name, String pass) { System.out.println("执行Hello组件的addUser()添加用户: "+name);
} @Override
public int addGroup(String groupName, int groupMemberNumber) { System.out.println("执行Hello组件的addGroup()添加群组: "+groupName);
if(groupMemberNumber<0||groupMemberNumber>100) {
throw new IllegalArgumentException("群组成员数在0~100之间");
}
return 0;
} @Override
public int fourAdviceGetParamer(String param) { System.out.println("执行Hello组件的fourAdviceGetParamer()方法,param:"+param);
return 5;
} }

FourAdviceGetParamerAspect.java

package com.lfy.aspect;

import java.util.Arrays;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut; /**
* Around、Before、After、AfterReturning四种增强处理<br>
* 访问目标方法最简单的做法是定义增强处理方法时将第一个参数定义为JoinPoint类型,
* 当该增强处理方法被调用时,该JoinPoint参数就代表了织入增强处理的连接点。JoinPoint
* 提供了如下的常用访问方法:<br>
* 1>Objeact[] getArgs():返回目标方法的参数<br>
* 2>Signature getSignature():返回目标方法的相关信息<br>
* 3>Object getTarget():返回被增强处理的对象<br>
* 4>Object getThis():返回AOP框架为目标对象生成的代理对象。<br>
* 在这些方法中,只有Around增强处理中可以对目标方法的参数进行修改!<br>
* @author lfy
*
* 切入点组合连接符有&&、||、!
*/
public class FourAdviceGetParamerAspect { public Object processTx(ProceedingJoinPoint jp) throws Throwable { System.out.println("FourAdviceGetParamerAspect.Around执行目标方法之前,模拟开始事务...");
//获取目标方法原始的调用参数
Object[] args=jp.getArgs();
if(args!=null && args.length>0 && args[0].getClass() == String.class) {
//修改目标方法调用参数的第一个参数
args[0]="[增强的前缀]"+args[0];
}
//改变后的参数去执行目标方法,并保存目标方法执行后的返回值
Object rvt=jp.proceed(args);
System.out.println("FourAdviceGetParamerAspect.Around执行目标方法之后,模拟结束事务...");
System.out.println("<---------------->");
//如果rvt的类型是Integer,将rvt改为它的平方
if(rvt!=null&&rvt instanceof Integer) {
rvt=(Integer)rvt*(Integer)rvt;
}
return rvt;
} public void authority(JoinPoint jp) { System.out.println("FourAdviceGetParamerAspect.Before模拟执行权限检查");
//返回被织入增强的目标方法
System.out.println("被织入的目标方法是: "+jp.getSignature().getName());
System.out.println("被织入的目标方法的参数: "+Arrays.toString(jp.getArgs()));
System.out.println("被织入增强处理的目标对象为: "+jp.getTarget());
System.out.println("<---------------->");
} public void release(JoinPoint jp) { System.out.println("FourAdviceGetParamerAspect.After模拟方法结束后的释放资源...");
//返回被织入增强的目标方法
System.out.println("被织入的目标方法是: "+jp.getSignature().getName());
System.out.println("被织入的目标方法的参数: "+Arrays.toString(jp.getArgs()));
System.out.println("被织入增强处理的目标对象为: "+jp.getTarget());
System.out.println("<---------------->");
} public void log(JoinPoint jp,Object rvt) { System.out.println("FourAdviceGetParamerAspect.AfterReturning获取目标方法返回值: "+rvt);
System.out.println("FourAdviceGetParamerAspect.AfterReturning模拟记录日志功能...");
//返回被织入增强的目标方法
System.out.println("被织入的目标方法是: "+jp.getSignature().getName());
System.out.println("被织入的目标方法的参数: "+Arrays.toString(jp.getArgs()));
System.out.println("被织入增强处理的目标对象为: "+jp.getTarget());
System.out.println("<---------------->");
}
}

beans.xml

<?xml version="1.0" encoding="UTF-8"?>
<!-- spring配置文件的根元素,使用spring-beans-4.0.xsd语义约束 -->
<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/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.0.xsd"> <aop:config>
<!-- 配置全局切入点,设置在<aop:config>下是全局切入点标签,
可以被多个切面共享。设置在<aop:aspect>下是某个切面的
切入点标签 ,表示该切入点只能在该切面中有效。
-->
<aop:pointcut id="myPointcut0" expression="execution(int com.lfy.impl.HelloImpl.fourAdviceGetParamer(..))"/> <!-- 将fourAdviceGetParamerBean转换成切面bean,切面
bean的名称为fourAdviceGetParamerAspect,指定该
切面的优先级为2
-->
<aop:aspect id="fourAdviceGetParamerAspect" ref="fourAdviceGetParamerBean" order="2">
<!-- 直接指定切入点表达式 -->
<aop:around pointcut="execution(int com.lfy.impl.HelloImpl.fourAdviceGetParamer(..))" method="processTx"/>
<aop:before pointcut-ref="myPointcut0" method="authority"/>
<!-- 定义一个After增强处理,直接指定切入点,以切面bean(即:fourAdviceGetParamerAspect)中的release()方法作为增强处理方法 -->
<aop:after pointcut-ref="myPointcut0" method="release"/>
<aop:after-returning pointcut-ref="myPointcut0" method="log" returning="rvt"/>
</aop:aspect>
</aop:config> <bean id="fourAdviceGetParamerBean" class="com.lfy.aspect.FourAdviceGetParamerAspect"/>
<bean id="hello" class="com.lfy.impl.HelloImpl"/>
<bean id="world" class="com.lfy.impl.WorldImpl"/>
</beans>

SpringAOPTest.java

package com.lfy.main;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext; import com.lfy.bean.Hello;
import com.lfy.bean.World; /**
* 2、基于XML Schema方式
* @author lfy
* 未登记的知识点:
* 1>指定增强处理的优先级,@Order注解及Orderd接口
* 2>切入点指示符
*/
public class SpringAOPTest { public static void main(String[] args) { ApplicationContext ctx=new ClassPathXmlApplicationContext("beans.xml");
Hello hello=ctx.getBean("hello", Hello.class);
System.out.println("修改后的目标方法的返回值:"+hello.fourAdviceGetParamer("唐僧")); } }

运行结果:

4、配置切入点

XML配置方式也可以通过定义切入点来重复使用切入点表达式。spring提供了<aop:pointcut.../>元素定义切入点。当把<aop:pointcut.../>元素作为<aop:config.../>元素的子元素定义时,表明该切入点可被多个切面共享;当把<aop:pointcut.../>元素作为<aop:aspect.../>的子元素定义时,表明该切入点只能在该切面中有效。

配置<aop:pointcut.../>元素通常需要指定的属性有:

id:指定该切入点的标识名。

expression:指定该切入点关联的切入点表达式。

<aop:pointcut id="myPointcut0" expression="execution(int com.lfy.impl.HelloImpl.fourAdviceGetParamer(..))"/>

如果已经使用了注解定义了某个切入点,也可以给expression指定该已有的切入点。(但不推荐注解和XML Schema混合使用,我们在第十七篇讲过,容易出错。)

<aop:pointcut id="myPointcut0" expression="com.lfy.aspect.PointcutUtil.myPointcut()"/>

spring-第十八篇之spring AOP基于XML配置文件的管理方式的更多相关文章

  1. 8 -- 深入使用Spring -- 4...6 AOP代理:基于注解的XML配置文件的管理方式

    8.4.6 基于XML配置文件的管理方式 Spring 2.x 提供一个新的aop:命名空间来定义切面.切入点和增强处理. XML配置方式优点: ⊙ 如果应用没有使用JDK 1.5 以上版本,那么应用 ...

  2. Spring Boot(十八):使用Spring Boot集成FastDFS

    Spring Boot(十八):使用Spring Boot集成FastDFS 环境:Spring Boot最新版本1.5.9.jdk使用1.8.tomcat8.0 功能:使用Spring Boot将文 ...

  3. Spring(十八):Spring AOP(二):通知(前置、后置、返回、异常、环绕)

    AspectJ支持5种类型的通知注解: @Before:前置通知,在方法执行之前执行: @After:后置通知,在方法执行之后执行: @AfterRunning:返回通知,在方法返回结果之后执行(因此 ...

  4. (转)Spring Boot(十八):使用 Spring Boot 集成 FastDFS

    http://www.ityouknow.com/springboot/2018/01/16/spring-boot-fastdfs.html 上篇文章介绍了如何使用 Spring Boot 上传文件 ...

  5. Spring Boot(十八):使用 Spring Boot 集成 FastDFS

    上篇文章介绍了如何使用 Spring Boot 上传文件,这篇文章我们介绍如何使用 Spring Boot 将文件上传到分布式文件系统 FastDFS 中. 这个项目会在上一个项目的基础上进行构建. ...

  6. Spring(十九):Spring AOP(三):切面的优先级、重复使用切入点表达式

    背景: 1)指定切面优先级示例:有的时候需要对一个方法指定多个切面,而这多个切面有时又需要按照不同顺序执行,因此,切面执行优先级别指定功能就变得很实用. 2)重复使用切入点表达式:上一篇文章中,定义前 ...

  7. 跟我学SpringCloud | 第十二篇:Spring Cloud Gateway初探

    SpringCloud系列教程 | 第十二篇:Spring Cloud Gateway初探 Springboot: 2.1.6.RELEASE SpringCloud: Greenwich.SR1 如 ...

  8. Spring Boot 2.X(十八):集成 Spring Security-登录认证和权限控制

    前言 在企业项目开发中,对系统的安全和权限控制往往是必需的,常见的安全框架有 Spring Security.Apache Shiro 等.本文主要简单介绍一下 Spring Security,再通过 ...

  9. 跟我学SpringCloud | 第八篇:Spring Cloud Bus 消息总线

    SpringCloud系列教程 | 第八篇:Spring Cloud Bus 消息总线 Springboot: 2.1.6.RELEASE SpringCloud: Greenwich.SR1 如无特 ...

随机推荐

  1. Html5移动端页面自适应布局详解(rem布局)

    在移动设备上进行网页的重构或开发,首先得搞明白的就是移动设备上的viewport,通读网上的各种对于viewport的解释之后 大概viewport可以理解为三种 1.layout viewport  ...

  2. 帝国CMS 列表内容模板[!--empirenews.listtemp--]改写为灵动标签[e:loop={}]

    需求描述: 1.将专题列表下的列表单元,自动根据专题页标题或者页面关键词来匹配展示: 2.第一个精确匹配,后面十一个模糊匹配,总数12个: 正文模板中,引入部分为: [!--empirenews.li ...

  3. vue回到顶部

    backTop() { var top = document.body.scrollTop || document.documentElement.scrollTop; this.duration - ...

  4. 详聊js中的原型/原型链

    先以一段简单的代码为例: function Dog(params){     this.name = param.name;     this.age = param.age;     this.ba ...

  5. css设置不允许复制文本内容

    之前做一个网上答题的页面时,考虑到要防止考生利用复制粘贴来提高作弊的可能性,就设计了不允许复制.方法也很简单,通过设置CSS 的 user-select就可以达到目的: -moz-user-selec ...

  6. 读取FTP上的excel文件,并写入数据库

    今天遇到一些问题,需要从ftp上读取一些excel文件,并需要将excel中的数据写入到数据库,这样就可以通过管理页面查看这些数据. 我将相关工作分为三步,1.从ftp上读取相关文件,并将excel文 ...

  7. dialog写进dll调用

    #ifdef DLG_WINDOW_API #define DLG_WINDOW_EXPORT __declspec(dllexport) #else #define DLG_WINDOW_EXPOR ...

  8. Photoshop画笔工具的使用

    现在我们按下[B]从工具栏选择画笔工具,如果选中了铅笔就[SHIFT B]切换到画笔.然后按下[D],它的作用是将颜色设置为默认的前景黑色.背景白色.也可以点击工具栏颜色区的默认按钮(下左图红色箭头处 ...

  9. Java中Comparable接口和Comparator接口的简单用法

    对象比较器 1.Comparable接口 此接口强行对实现它的每个类的对象进行整体排序,这种排序成为类的自然排序,类的compareTo方法称为类的自然比较方法. 代码示例 import java.u ...

  10. redis集群报错:(error) CLUSTERDOWN The cluster is down

    更换了电脑,把原来的电脑上的虚拟机复制到了新电脑上,启动虚拟机上的centos系统,然后启动redis集群(redis5版本),发现集群可以启动,redis进程也有,但是连接集群中的任意节点就报错,如 ...