后置通知
/**
* @After:将方法标注为后置通知
* 后置通知:作用于方法的finally语句块,即不管有没有异常都会执行
*
*/
@After(value = "execution(* com.atguigu.spring.aop.*.*(..))")
public void afterMethod(){
System.out.println("后置通知");
}
返回通知
/**
* @AfterReturning:将方法标注为返回通知
* 返回通知:作用于方法执行之后
* 可通过returning设置接收方法返回值的变量名
* 要想要在方法中使用,必须在方法的形参中设置和变量名相同的参数名的参数
*
*/
@AfterReturning(value = "execution(* com.atguigu.spring.aop.*.*(..))",returning="result")
public void afterReturningMethod(JoinPoint joinPoint,Object result){
String methodName = joinPoint.getSignature().getName();
System.out.println("method:"+methodName+",result:"+result);
}
//注意形参与返回值的变量名的参数相同!
异常通知
/**
* @AfterThrowing:将方法标注为异常通知(例外通知)
* 异常通知(例外通知):作用于方法抛出异常时
* 可通过throwing设置接收方法返回的异常信息
* 在参数列表中可通过具体的异常类型,来对指定的异常信息进行操作
*
*/
@AfterThrowing(value = "execution(* com.atguigu.spring.aop.*.*(..))",throwing="ex")
public void afterThrowingMethod(ArithmeticException ex){
System.out.println("有异常了,messages:"+ex);
}
//方法形参中exception的类型可以自己定义 这样在抛出异常时刻针对不同异常不同响应!
环绕通知(动态代理的具体结构)
发现在测试时会报错 原因:缺少返回值 目标对象返回值为int(不建议这样定义,按包装类来定义)
@Around(value="execution(* com.atguigu.spring.aop.*.*(..))")
public Object aroundMethod(ProceedingJoinPoint joinPoint){
Object result = null;
try {
//前置通知
System.out.println("前置通知");
result = joinPoint.proceed();//执行方法
//返回通知
System.out.println("返回 通知");
return result;
} catch (Throwable e) {
// TODO Auto-generated catch block
e.printStackTrace();
//异常通知
System.out.println("异常通知");
}finally{
//后置通知
System.out.println("后置通知");
}
return -1;
}
//定义公共切入点 其他通知直接使用
@Pointcut(value="execution(* com.atguigu.spring.aop.*.*(..))")
public void test(){}
//前置通知
@Before(value="test()")
public void beforeMethod(JoinPoint joinPoint){
Object[] args = joinPoint.getArgs();//获取方法的参数
String methodName = joinPoint.getSignature().getName();//获取方法名
System.out.println("method:"+methodName+",arguments:"+Arrays.toString(args));
}
设置切面的优先级
@Component
@Aspect
@Order(0)
public class TestAspect {
@Before(value="execution(* com.atguigu.spring.aop.*.*(..))")
public void before(){
System.out.println("TestAspect==>前置通知");
}
}
@Component
@Aspect
@Order(1)//定义切面作用的优先级,值越小优先级越高,默认值为int的最大值
public class MyloggerAspect {
.....
}
通过xml配置切面
1.编辑切面通知 使用组件注解
@Component
public class MyLogger {
public void before(){
System.out.println("前置通知");
}
}
2.配置xml 使用<context:component-scan>先扫描包结构
3.使用aop标签<aop:config>
4.使用切面标签<aop:aspect ref="">
5.使用通知标签<aop: 通知类型 method="方法名" pointcut="切入表达式">
也可设置<aop:pointcut expression="切入表达式" id="类名"> 在通知标签内快速调用
<context:component-scan base-package="com.atguigu.spring.aopxml"></context:component-scan>
<aop:config>
<aop:aspect ref="myLogger">
<aop:pointcut expression="execution(* com.atguigu.spring.aopxml.*.*(..))" id="cut"/>
<!-- <aop:before method="before" pointcut="execution(* com.atguigu.spring.aopxml.*.*(..))"/> -->
<aop:before method="before" pointcut-ref="cut"/>
</aop:aspect>
</aop:config>
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value=""></property>
<property name="url" value=""></property>
<property name="username" value=""></property>
<property name="password" value=""></property>
</bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean>