1.创建被增强类
package com.daijunyi.aopanno;
public class User {
public void add(){
System.out.println("打印add方法");
}
}
2.创建增强类
package com.daijunyi.aopanno;
public class UserProxy {
public void before(){
System.out.println("before打印");
}
}
3.进行通知的注解配置
(1)在Spring配置文件中,开启注解扫描
<?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.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
<!--开启组件扫描-->
<context:component-scan base-package="com.daijunyi.aopanno"></context:component-scan>
</beans>
(2)使用注解创建User和UserProxy对象
(3)在增强类上添加注解@Aspect
(4)在Spring配置文件中开启生成代理对象
<?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.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
<!--开启组件扫描-->
<context:component-scan base-package="com.daijunyi.aopanno"></context:component-scan>
<!--开启Aspect生成代理对象-->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>
此步骤也可使用 配置类来实现
package com.daijunyi;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
@Configuration
@ComponentScan(value = {"com.daijunyi.aopanno"})
@EnableAspectJAutoProxy(proxyTargetClass = true)//相当于自动开启@Aspect生成代理类
public class AopConfiguration {
}
4、配置不同类型的通知
(1)在增强类的里面,在作为通知方法上面添加通知类型注解,使用切入点表达式配置
package com.daijunyi.aopanno;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
@Component
@Aspect
public class UserProxy {
//@Before注解表示作为前置通知
@Before(value = "execution(* com.daijunyi.aopanno.User.add(..))")
public void before(){
System.out.println("before打印");
}
}
5、测试代码
@Test
public void testUserProxy(){
ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
User user = (User) context.getBean("user");
user.add();
}
输出结果
before打印
打印add方法
Process finished with exit code 0
6、再修改的方法多一点
package com.daijunyi.aopanno;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
@Component
@Aspect
public class UserProxy {
//@Before注解表示作为前置通知
@Before(value = "execution(* com.daijunyi.aopanno.User.add(..))")
public void before(){
System.out.println("Before....");
}
@Around(value = "execution(* com.daijunyi.aopanno.User.add(..))")
public Object around(ProceedingJoinPoint proceedingJoinPoint){
System.out.println("环绕之前。。。");
Object proceed = null;
try {
proceed = proceedingJoinPoint.proceed();
} catch (Throwable throwable) {
throwable.printStackTrace();
} finally {
System.out.println("环绕之后...");
}
return proceed;
}
@After(value = "execution(* com.daijunyi.aopanno.User.add(..))")
public void after(){
System.out.println("After....");
}
//当运行异常的时候执行
@AfterThrowing(value = "execution(* com.daijunyi.aopanno.User.add(..))")
public void afterThrowing(){
System.out.println("afterThrowing....");
}
//当add方法运行正常的时候执行
@AfterReturning(value = "execution(* com.daijunyi.aopanno.User.add(..))")
public void afterReturning(){
System.out.println("AfterReturning...");
}
}
当代码运行正常输出结果
环绕之前。。。
Before....
打印add方法
AfterReturning...
After....
环绕之后...
Process finished with exit code 0
当运行异常的时候
环绕之前。。。
Before....
afterThrowing....
After....
java.lang.ArithmeticException: / by zero
at com.daijunyi.aopanno.User.add(User.java:9)
at com.daijunyi.aopanno.User$$FastClassBySpringCGLIB$$fdb63a83.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:771)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749)
at org.springframework.aop.aspectj.AspectJAfterThrowingAdvice.invoke(AspectJAfterThrowingAdvice.java:62)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
错误省略。。。
环绕之后...
Process finished with exit code 0
从中我们可以知道,运行正常和异常唯一的区别就是正常执行会执行,AfterReturning方法,但是异常运行的时候是执行afterThrowing方法。
8、对相同切入点进行抽取。
使用注解@Pointcut进行抽取
package com.daijunyi.aopanno;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
@Component
@Aspect
public class UserProxy {
//相同切入点抽取
@Pointcut(value = "execution(* com.daijunyi.aopanno.User.add(..))")
public void point(){
}
//@Before注解表示作为前置通知
@Before(value = "point()")
public void before(){
System.out.println("Before....");
}
@Around(value = "point()")
public Object around(ProceedingJoinPoint proceedingJoinPoint){
System.out.println("环绕之前。。。");
Object proceed = null;
try {
proceed = proceedingJoinPoint.proceed();
} catch (Throwable throwable) {
throwable.printStackTrace();
} finally {
System.out.println("环绕之后...");
}
return proceed;
}
@After(value = "point()")
public void after(){
System.out.println("After....");
}
@AfterThrowing(value = "point()")
public void afterThrowing(){
System.out.println("afterThrowing....");
}
@AfterReturning(value = "point()")
public void afterReturning(){
System.out.println("AfterReturning...");
}
}
9、有多个增强类多同一个方法进行增强,设置增强类优先级
当我们有多个增强类的时候,可以使用注解@Order(数字)来设置方法优先级,数值越小优先级越前
package com.daijunyi.aopanno;
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 org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
@Component
@Aspect
@Order(1)
public class PersonProxy {
@Pointcut(value = "execution(* com.daijunyi.aopanno.User.add(..))")
public void point(){
}
@After(value = "point()")
public void after(){
System.out.println("PersonProxy.after......");
}
@Before(value = "point()")
public void before(){
System.out.println("PersonProxy.before......");
}
}
@Component
@Aspect
@Order(2)
public class UserProxy {
PersonProxy.before......
环绕之前。。。
Before....
打印add方法
AfterReturning...
After....
环绕之后...
PersonProxy.after......
Process finished with exit code 0