SpringAOP实现代理-5(通知)
-
通知分类
- 前置通知 before : 在业务方法执行之前执行, 前置通知不会影响连接点的执行,除非此处抛出异常。
- 后置通知 after : 在业务方法执行之后调用的通知,无论方法执行是否成功.
- 带返回值通知 after-returning : 可以拿到方法的返回值,仅当方法成功完成后执行的通知, 如果连接点抛出异常,则不会执行。
- 异常通知 after-throwing : 在方法抛出异常退出时执行的通知,若不抛出异常,则不执行,可以捕获业务方法中的异常对象
- 环绕通知 around : 同时在业务方法的前后执行
-
顺序
-
若是按照xml文件中通知按照before,after,around,after-returning,after-throwing的顺序书写的话
-
异常通知不执行的情况下 :
before>around before>业务方法 >after returning > around after >after
-
异常通知执行的情况下 :
before>around before>业务方法 >after throwing > after
-
-
使用注解的话是环绕通知proceed方法之前部分先执行,使用xml配置的话取决于aop:before和aop:around的配置顺序
-
-
目标类UserServiceImpl.java已实现接口
public class UserServiceImpl implements UserService {
@Override
public List getUser() {
System.out.println("getUser");
return null;
}
@Override
public boolean saveUser(Object user) {
System.out.println("saveUser");
return false;
}
@Override
public boolean deleteUser(int userId) {
System.out.println("deleteUser");
return false;
}
@Override
public boolean updataUser(Object user) {
System.out.println("updataUser");
return false;
}
}
- 定义切面类 Aspect.java
- JoinPoint对象封装了SpringAop中切面方法的信息,在切面方法中添加JoinPoint参数,就可以获取到封装了该方法信息的JoinPoint对象.
- getSignature();获取封装了署名信息的对象,在该对象中可以获取到目标方法名,所属类的Class等信息
- getArgs();获取传入目标方法的参数对象
- getTarget();获取被代理的对象
- getThis();获取代理对象
- 环绕通知 ProceedingJoinPoint 执行proceed方法的作用是让目标方法执行,这也是环绕通知和前置、后置通知方法的一个最大区别.
public class Aspect {
//前置通知
public void before(JoinPoint jp){
//JoinPoint对象封装了SpringAop中切面方法的信息,在切面方法中添加JoinPoint参数,就可以获取到封装了该方法信息的JoinPoint对象.
System.out.println("getTarget"+jp.getTarget());
System.out.println("getArgs"+ Arrays.toString(jp.getArgs()));
System.out.println("before");
}
//后置通知
public void after(){
System.out.println("after");
}
//环绕通知
public Object aroundTest(ProceedingJoinPoint pjp){ //环绕通知要有返回内容
//环绕通知 ProceedingJoinPoint 执行proceed方法的作用是让目标方法执行,这也是环绕通知和前置、后置通知方法的一个最大区别。
try {
System.out.println("around before");
Object obj = pjp.proceed();
System.out.println("around after");
return obj;
} catch (Throwable throwable) {
throwable.printStackTrace();
}
return null;
}
//带返回值的通知 ,配置文件的xml中,returning的属性值必须和返回值obj相同
public void returnTest(JoinPoint jp ,Object obj){
System.out.println("after returning");
System.out.println("after-returning的返回值: "+obj);
}
//带异常的通知,若是无异常,则不执行
public void throwsTest(JoinPoint jp,Throwable e){
System.out.println("after throwing");
System.out.println("after throwing打印异常信息: "+e.getMessage());
}
}
- 代理的.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"
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.xsd">
<!--创建目标类的实现-->
<bean id="us" class="com.aop.aop5.UserServiceImpl" />
<!--创建切面类-->
<bean id="asp" class="com.aop.aop5.Aspect" />
<!--proxy-target-class的属性设置成true,强制使用cglib方式实现代理对象-->
<aop:config proxy-target-class="true">
<aop:aspect ref="asp">
<!--切点-->
<aop:pointcut id="pt" expression="execution(* com.aop.aop5.*.*(..))"/>
<aop:before method="before" pointcut-ref="pt" /> <!--前置通知-->
<aop:after method="after" pointcut-ref="pt" /> <!--后置通知-->
<aop:around method="aroundTest" pointcut-ref="pt" /> <!--环绕通知-->
<aop:after-returning method="returnTest" pointcut-ref="pt" returning="obj" />
<!--返回通知需要有返回的obj,需要returning的属性值,且属性值与代理类的参数相同-->
<aop:after-throwing method="throwsTest" pointcut-ref="pt" throwing="e" />
<!--异常通知,需要throwing的属性值,且属性值与代理类的参数名相同-->
</aop:aspect>
</aop:config>
</beans>
- 单元测试AOPTest.java
public class AOPTest5 {
@Test
public void UserService(){
ApplicationContext ac=new ClassPathXmlApplicationContext("aop5/beans.xml");
UserService userService=ac.getBean("us", UserService.class);
userService.getUser();
userService.saveUser(new Object());
userService.deleteUser(3);
userService.updataUser(new Object());
}
}
网友评论