AOP, 面向切面编程
Aspect, 对横切性关注点的一种抽象(简而言之, 上面讲到的动态代理就是一种横切面)
相对而言, 类是对物体的一种抽象, 而切面是对横切性关注点的一种抽象
JoinPoint(连接点): 要拦截的方法
PointCut(切点): 连接点的集合
Advice(通知): 在连接点前后或异常情况发生时做的事情, 如前置通知/后置通知/返回通知/异常通知/环绕通知
引包: 链接:https://pan.baidu.com/s/1lyoSeLmkkFJurBF_4GFH4g 密码:hyz8
1 注解方式配置切面
①前置通知(@Before)
<?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: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-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.2.xsd">
<!-- 开启切面驱动(注解方式) -->
<aop:aspectj-autoproxy/>
<bean id="userService" class="com.rl.spring.service.impl.UserServiceImpl"></bean>
</beans>
配置切面类PermAspect(添加注解@Aspect):
package com.rl.spring.aspect;
import org.aspectj.lang.annotation.Aspect;
@Aspect
public class PermAspect {
}
配置PermAspect类里面的切点和通知
package com.rl.spring.aspect;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
@Aspect
public class PermAspect {
/**
* 第一个*: 代表任意返回值, 如果具体返回值 如: java.lang.String
* 第二个*: 代表任意类
* 第三个*: 代表任意方法
* 第一个..: 代表service包下所有类和子包下的所有类
* 第二个..: 代表方法的参数
*
* 配置完成后 该方法即可拦截service及其子包下的任何类 任何返回值 任何方法以及任何参数
*/
@Pointcut("execution(* com.rl.spring.service..*.*(..))")
public void anyMethod() {
}
/**
* 前置通知
*/
@Before("anyMethod()")
public void preAdive() {
System.out.println("前置通知执行了...");
}
}
需要先配置PermAspect类的bean
<?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: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-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.2.xsd">
<!-- 开启切面驱动(注解方式) -->
<aop:aspectj-autoproxy/>
<!-- 配置切面bean -->
<bean id="permAspect" class="com.rl.spring.aspect.PermAspect"></bean>
<bean id="userService" class="com.rl.spring.service.impl.UserServiceImpl"></bean>
</beans>
测试一下:
测试代码:
package com.rl.spring.test;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.rl.spring.service.UserService;
@RunWith(value=SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations= {"classpath:ApplicationContext.xml"})
public class TestSpring {
@Autowired
UserService userService;
@Test
public void test() {
userService.save();
}
}
测试结果:
传参的方式:
UserServiceImpl:
package com.rl.spring.service.impl;
import com.rl.spring.model.User;
import com.rl.spring.service.UserService;
public class UserServiceImpl implements UserService {
private User user;
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
@Override
public void save(User user) {
System.out.println("保存用户..."+user);
}
@Override
public void update() {
System.out.println("修改用户...");
}
}
PermAspect:
package com.rl.spring.aspect;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import com.rl.spring.model.User;
@Aspect
public class PermAspect {
/**
* 配置切面方法
*
* 第一个*: 代表任意返回值, 如果具体返回值 如: java.lang.String
* 第二个*: 代表任意类
* 第三个*: 代表任意方法
* 第一个..: 代表service包下所有类和子包下的所有类
* 第二个..: 代表方法的参数
*
* 配置完成后 该方法即可拦截service及其子包下的任何类 任何返回值 任何方法以及任何参数
*/
@Pointcut("execution(* com.rl.spring.service..*.*(..))")
public void anyMethod() {
}
/**
* 前置通知
* anyMethod(): 指定切面方法
* args(*): 指定传参, * 为参数名, 在这里args的参数名称必须和方法参数的名称相同 在此例中必须为user
* 如果有多个参数, 则直接用逗号隔开即可
*/
@Before("anyMethod()&&args(user)")
public void preAdive(User user) {
System.out.println(user);
//可以做一些操作
user.setUsername("火星");
System.out.println("前置通知执行了...");
}
}
测试代码:
package com.rl.spring.test;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.rl.spring.model.User;
import com.rl.spring.service.UserService;
@RunWith(value=SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations= {"classpath:ApplicationContext.xml"})
public class TestSpring {
@Autowired
UserService userService;
@Test
public void test() {
User user = new User();
user.setUserId(1);
user.setUsername("lijialin");
user.setPassword("123");
userService.save(user);
}
}
测试结果:
②后置通知(@After)
将配置文件中的bean改为新建的PermAspect1
<?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: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-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.2.xsd">
<!-- 开启切面驱动(注解方式) -->
<aop:aspectj-autoproxy/>
<!-- 配置切面bean -->
<bean id="permAspect" class="com.rl.spring.aspect.PermAspect1"></bean>
<bean id="userService" class="com.rl.spring.service.impl.UserServiceImpl"></bean>
</beans>
PermAspect1
package com.rl.spring.aspect;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import com.rl.spring.model.User;
@Aspect
public class PermAspect1 {
@Pointcut("execution(* com.rl.spring.service..*.*(..))")
public void anyMethod() {
}
@After(value="anyMethod()")
public void postAdvice() {
System.out.println("执行后置通知...");
}
}
测试代码:
package com.rl.spring.test;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.rl.spring.model.User;
import com.rl.spring.service.UserService;
@RunWith(value=SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations= {"classpath:ApplicationContext.xml"})
public class TestSpring {
@Autowired
UserService userService;
@Test
public void test() {
User user = new User();
user.setUserId(1);
user.setUsername("lijialin");
user.setPassword("123");
userService.save(user);
}
@Test
public void test1() {
userService.save();
}
}
③返回通知(@AfterReturning)
返回通知代码:
package com.rl.spring.aspect;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import com.rl.spring.model.User;
@Aspect
public class PermAspect1 {
@Pointcut("execution(* com.rl.spring.service..*.*(..))")
public void anyMethod() {
}
/**
* @AfterReturning: 返回通知的注解, 在返回通知里面可以对业务方法的返回值做最后的统一加工处理
* pointcut: 指定返回通知的切点
* returning: 指定返回值和返回通知的方法的参数名称要一致
*/
@AfterReturning(pointcut="anyMethod()", returning="user")
public void returnAdvice(User user) {
user.setUsername("lijialin");//统一加工处理
System.out.println("执行返回通知...");
}
}
测试代码:
package com.rl.spring.test;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.rl.spring.model.User;
import com.rl.spring.service.UserService;
@RunWith(value=SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations= {"classpath:ApplicationContext.xml"})
public class TestSpring {
@Autowired
UserService userService;
@Test
public void test2() {
User user = userService.queryById(1);
System.out.println("最终返回的user: "+user);
}
}
输出结果:
④例外通知(异常通知) @ AfterThrowing 主要用于运行期的监控, 异常时抛出处理
在UserServiceImpl方法中设置一个异常1/0
异常通知代码:
package com.rl.spring.aspect;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import com.rl.spring.model.User;
@Aspect
public class PermAspect1 {
@Pointcut("execution(* com.rl.spring.service..*.*(..))")
public void anyMethod() {
}
@AfterThrowing(pointcut="anyMethod()", throwing="ex")
public void exceptionAdvice(Exception ex) {
System.out.println("执行例外通知...");
ex.printStackTrace();
}
}
测试代码:
package com.rl.spring.test;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.rl.spring.model.User;
import com.rl.spring.service.UserService;
@RunWith(value=SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations= {"classpath:ApplicationContext.xml"})
public class TestSpring {
@Autowired
UserService userService;
@Test
public void test1() {
userService.save();
}
}
结果输出:
⑤环绕通知(@Around 用的最多, 可以实现前置通知 后置通知 返回通知 例外通知的所有功能)
环绕通知代码:
package com.rl.spring.aspect;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import com.rl.spring.model.User;
@Aspect
public class PermAspect2 {
@Pointcut("execution(* com.rl.spring.service..*.*(..))")
public void anyMethod() {
}
/**
* @Around: 环绕通知的注解, 指定切点
* ProceedingJoinPoint: 正在执行的连接点, 正在执行拦截的方法的抽象
* @throws Throwable
*/
@Around("anyMethod()")
public Object doAroundAdvice(ProceedingJoinPoint jp) throws Throwable {
Object[] args = jp.getArgs();//获得参数
System.out.println("环绕通知前--前置通知..."+args[0]);//本次示例参数只有一个, 取索引0
//环绕通知的执行方法, 如果使用无参 则传递默认参数 返回值就是业务方法的返回值
// Object obj = jp.proceed();//让方法继续走下去
Object obj = jp.proceed(args);//此参数可以修改后再传递过去, 这样就跟原先的参数值不一样的了 但本例中没改, 直接传回去
User user = (User) obj;
user.setUsername("lijialin");
System.out.println("环绕通知后--后置通知..."+" 返回值: "+obj);
return obj;
}
}
测试代码:
package com.rl.spring.test;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.rl.spring.model.User;
import com.rl.spring.service.UserService;
@RunWith(value=SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations= {"classpath:ApplicationContext.xml"})
public class TestSpring {
@Autowired
UserService userService;
@Test
public void test3() {
User user = userService.queryById(1);
System.out.println(user);//也能将返回值输出
}
}
利用环绕通知配置权限
环绕通知代码:
package com.rl.spring.aspect;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import com.rl.spring.model.User;
import com.rl.spring.service.impl.UserServiceImpl;
@Aspect
public class PermAspect2 {
@Pointcut("execution(* com.rl.spring.service..*.*(..))")
public void anyMethod() {
}
@Around("anyMethod()")
public Object doAroundAdvice(ProceedingJoinPoint jp) throws Throwable {
UserServiceImpl us = (UserServiceImpl) jp.getTarget();
User user = us.getUser();
Object obj = null;
if(user != null) {
obj = jp.proceed();
}else {
System.out.println("您还没有登录呢!");
}
return obj;
}
}
测试代码:
package com.rl.spring.test;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.rl.spring.model.User;
import com.rl.spring.service.UserService;
@RunWith(value=SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations= {"classpath:ApplicationContext.xml"})
public class TestSpring {
@Autowired
UserService userService;
@Test
public void test4() {
userService.save(new User());//这里即使是new了一个User 在业务类里面的User还是为null
}
}
输出结果:
2 配置文件方式配置切面
前置通知:
配置文件:
<?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: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-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.2.xsd">
<!-- 配置切面bean -->
<bean id="permAspect" class="com.rl.spring.aspect.PermAspect"></bean>
<bean id="userService" class="com.rl.spring.service.impl.UserServiceImpl"></bean>
<!-- 配置aop -->
<aop:config>
<!-- 配置切点 -->
<aop:pointcut expression="execution(* com.rl.spring.service..*.*(..))" id="mycut"/>
<!-- 配置切面 -->
<aop:aspect ref="permAspect">
<!-- 指定切面中的方法为前置通知 -->
<aop:before method="preAdvice" pointcut-ref="mycut"/>
</aop:aspect>
</aop:config>
</beans>
切面代码:
package com.rl.spring.aspect;
import org.aspectj.lang.JoinPoint;
public class PermAspect {
/**
* 无需注解配置了, 已经在配置文件中定义好了
*/
public void preAdvice(JoinPoint jp) {
Object[] args = jp.getArgs();
System.out.println("执行前置通知..."+"参数: "+args[0]);
}
}
测试代码:
package com.rl.spring.test;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.rl.spring.model.User;
import com.rl.spring.service.UserService;
@RunWith(value=SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations= {"classpath:ApplicationContext.xml"})
public class TestSpring {
@Autowired
UserService userService;
@Test
public void test() {
User user = new User();
user.setUserId(1);
user.setUsername("lijialin");
user.setPassword("123");
userService.save(user);
}
}
输出结果:
后置通知:
与前置通知同理:
输出结果:
返回通知:
返回通知代码:
package com.rl.spring.aspect;
import org.aspectj.lang.JoinPoint;
import com.rl.spring.model.User;
public class PermAspect {
public void returnAdvice(JoinPoint jp, Object returnval) {
if(returnval instanceof User) {
User user = (User) returnval;
user.setUsername("lijialin");
}
System.out.println("返回通知..."+"返回的值: "+returnval);
}
}
配置文件:
<?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: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-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.2.xsd">
<!-- 配置切面bean -->
<bean id="permAspect" class="com.rl.spring.aspect.PermAspect"></bean>
<bean id="userService" class="com.rl.spring.service.impl.UserServiceImpl"></bean>
<!-- 配置aop -->
<aop:config>
<!-- 配置切点 -->
<aop:pointcut expression="execution(* com.rl.spring.service..*.*(..))" id="mycut"/>
<!-- 配置切面 -->
<aop:aspect ref="permAspect">
<!-- 指定切面中的方法为前置通知 -->
<aop:before method="preAdvice" pointcut-ref="mycut"/>
<aop:after method="afterAdvice" pointcut-ref="mycut"/>
<aop:after-returning method="returnAdvice" pointcut-ref="mycut" returning="returnval"/>
</aop:aspect>
</aop:config>
</beans>
测试代码:
package com.rl.spring.test;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.rl.spring.model.User;
import com.rl.spring.service.UserService;
@RunWith(value=SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations= {"classpath:ApplicationContext.xml"})
public class TestSpring {
@Autowired
UserService userService;
@Test
public void test1() {
User user = userService.queryById(1);
System.out.println(user);
}
}
输出结果:
例外通知:
例外通知代码:
package com.rl.spring.aspect;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import com.rl.spring.model.User;
public class PermAspect {
/**
* 无需注解配置了, 已经在配置文件中定义好了
*/
public void preAdvice(JoinPoint jp) {
Object[] args = jp.getArgs();
if(args.length>0)
System.out.println("执行前置通知..."+"参数: "+args[0]);
}
public void afterAdvice(JoinPoint jp) {
Object[] args = jp.getArgs();
if(args.length>0)
System.out.println("执行后置通知..."+"参数: "+args[0]);
}
public void returnAdvice(JoinPoint jp, Object returnval) {
if(returnval instanceof User) {
User user = (User) returnval;
user.setUsername("lijialin");
}
System.out.println("返回通知..."+"返回的值: "+returnval);
}
public void exceptionAdvice(JoinPoint jp, Exception ex) {
System.out.println("例外通知...");
ex.printStackTrace();
}
}
配置文件:
<?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: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-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.2.xsd">
<!-- 配置切面bean -->
<bean id="permAspect" class="com.rl.spring.aspect.PermAspect"></bean>
<bean id="userService" class="com.rl.spring.service.impl.UserServiceImpl"></bean>
<!-- 配置aop -->
<aop:config>
<!-- 配置切点 -->
<aop:pointcut expression="execution(* com.rl.spring.service..*.*(..))" id="mycut"/>
<!-- 配置切面 -->
<aop:aspect ref="permAspect">
<!-- 指定切面中的方法为前置通知 -->
<aop:before method="preAdvice" pointcut-ref="mycut"/>
<aop:after method="afterAdvice" pointcut-ref="mycut"/>
<aop:after-returning method="returnAdvice" pointcut-ref="mycut" returning="returnval"/>
<!--
throwing: 抛出的异常变量名, 需要跟切面类里面的变量匹配
-->
<aop:after-throwing method="exceptionAdvice" pointcut-ref="mycut" throwing="ex"/>
</aop:aspect>
</aop:config>
</beans>
结果输出:
环绕通知:
环绕通知代码:
package com.rl.spring.aspect;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import com.rl.spring.model.User;
public class PermAspect {
/**
* 无需注解配置了, 已经在配置文件中定义好了
*/
public void preAdvice(JoinPoint jp) {
Object[] args = jp.getArgs();
if(args.length>0)
System.out.println("执行前置通知..."+"参数: "+args[0]);
}
public void afterAdvice(JoinPoint jp) {
Object[] args = jp.getArgs();
if(args.length>0)
System.out.println("执行后置通知..."+"参数: "+args[0]);
}
public void returnAdvice(JoinPoint jp, Object returnval) {
if(returnval instanceof User) {
User user = (User) returnval;
user.setUsername("lijialin");
}
System.out.println("返回通知..."+"返回的值: "+returnval);
}
public void exceptionAdvice(JoinPoint jp, Exception ex) {
System.out.println("例外通知...");
ex.printStackTrace();
}
public Object aroundAdvice(ProceedingJoinPoint jp) {
Object[] objs = jp.getArgs();
Object obj = null;
System.out.println("环绕通知之前置通知...");
if(objs.length>0) {
System.out.println("执行环绕通知..."+"参数: "+objs[0]);
try {
obj = jp.proceed();
System.out.println("环绕通知之后置通知...");
} catch (Throwable e) {
e.printStackTrace();
}
}
return obj;
}
}
配置文件:
<?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: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-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.2.xsd">
<!-- 配置切面bean -->
<bean id="permAspect" class="com.rl.spring.aspect.PermAspect"></bean>
<bean id="userService" class="com.rl.spring.service.impl.UserServiceImpl"></bean>
<!-- 配置aop -->
<aop:config>
<!-- 配置切点 -->
<aop:pointcut expression="execution(* com.rl.spring.service..*.*(..))" id="mycut"/>
<!-- 配置切面 -->
<aop:aspect ref="permAspect">
<!-- 指定切面中的方法为前置通知 -->
<aop:before method="preAdvice" pointcut-ref="mycut"/>
<aop:after method="afterAdvice" pointcut-ref="mycut"/>
<aop:after-returning method="returnAdvice" pointcut-ref="mycut" returning="returnval"/>
<!--
throwing: 抛出的异常变量名, 需要跟切面类里面的变量匹配
-->
<aop:after-throwing method="exceptionAdvice" pointcut-ref="mycut" throwing="ex"/>
<aop:around method="aroundAdvice" pointcut-ref="mycut"/>
</aop:aspect>
</aop:config>
</beans>
结果输出: