有两种实现AOP的方式:xml配置文件的方式和注解的形式
我们知道通知Advice是指对拦截到的方法做什么事,可以细分为
前置通知:方法执行之前执行的行为。
后置通知:方法执行之后执行的行为。
异常通知:方法抛出异常时的行为。
最终通知:方法执行成功失败都会执行的行为,finally。
环绕通知:前后都要做,如事务
相关依赖:
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.3.7.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.7.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>4.3.7.RELEASE</version>
</dependency>
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>2.2.2</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.8.10</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.10</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
</dependencies>
需要加功能的类
public class UserService { public void saveUser() {
System.out.println("save a user...");
//throw new RuntimeException();
} }
要加的功能Advice
public class LogAdvice {
//前置通知
public void before() {
System.out.println("== before ==");
} //最终通知
public void after() {
System.out.println("== after ==");
} //后置通知
public void afterReturning() {
System.out.println("== afterReturning =="); }
//异常通知
public void afterThrowing() {
System.out.println("== afterThrowing ==");
} //环绕通知֪
public void around(ProceedingJoinPoint joinPoint) {
try {
System.out.println("== around start ==");
joinPoint.proceed(); // 执行原方法
System.out.println("== around end ==");
} catch (Throwable e) {
//这里是处理还是抛出,情况不一样,涉及到会不会调用afterThrowing
System.out.println("== around afterThrowing ==");
}
}
}
配置文件实现AOP功能
<?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:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-2.5.xsd "> <!-- 配置Service对象-->
<bean id="userService" class="com.winner.test.UserService"/> <!-- 配置一个通知对象 -->
<bean id="logAdvice" class="com.winner.test.LogAdvice"/> <!-- AOP有关的配置都 在aop:config中 -->
<aop:config>
<!-- 声明一个切面 ref对应的通知对象中有前置通知,后置通知等各种通知,各种通知的method属性的值
就是这个通知对中的方法名
-->
<aop:aspect ref="logAdvice">
<!-- 声明切入点 -->
<aop:pointcut id="myPointcut" expression="execution(public * *(..))"/>
<!-- 指定在某切入点执行某操作 -->
<!--指定before通知方法为,logAdvice.before(),引用切入点myPointcut -->
<aop:before method="before" pointcut-ref="myPointcut"/>
<!--指定before通知方法为,logAdvice.after(),引用切入点myPointcut -->
<aop:after method="after" pointcut-ref="myPointcut"/>
<!--指定before通知方法为,logAdvice.afterReturning(),引用切入点myPointcut -->
<aop:after-returning method="afterReturning" pointcut-ref="myPointcut"/>
<!--指定before通知方法为,logAdvice.afterThrowing(),引用切入点myPointcut -->
<aop:after-throwing method="afterThrowing" pointcut-ref="myPointcut"/>
<!--指定before通知方法为,logAdvice.around(),引用切入点myPointcut -->
<aop:around method="around" pointcut-ref="myPointcut" />
</aop:aspect>
</aop:config> </beans>
测试
public class MainTest { @Test
public void testUserService() throws Exception {
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
UserService userService = (UserService) ac.getBean("userService");
System.out.println(userService.getClass()); userService.saveUser();
System.out.println();
}
}
执行结果
没有异常的情况
== before ==
== around start ==
save a user...
== around end ==
== afterReturning ==
== after ==
有异常的情况
== before ==
== around start ==
save a user...
== around afterThrowing ==
== afterReturning ==
== after ==
切入点表达式
格式:
execution(修饰符? 返回值类型 类的全限定名? 方法名(参数))
这其中的问号后缀(?)表示可选的表达式元素。让我们来分析
execution(* com.winner.test.UserService.*(..))
表达式:星号*表示任何返回类型(ret- type-pattern,返回类型模式),后面跟着一个全限定类名(declaring-type-pattern,声明类型模式)。我们在这个类名后 又跟另一个星号*(..),这表示一个任意名称、任意数量(包括零)和任意参数类型的方法。
<!-- 声明切入点 -->
<!-- cn.itcast.oa.service包中所有类的所有public方法 -->
<aop:pointcut expression="execution(public * cn.winner.oa.service.*.*(..))" id="myPointcut" /> <!-- 所模块的service包中所有类的所有方法 -->
<aop:pointcut expression="execution(* cn.winner.oa.*.service.*.*(..))" id="myPointcut" /> <!-- cn.itcast.oa.service的所有子包中所有类的所有方法 -->
<aop:pointcut expression="execution(* cn.winner.oa.service.*.*.*(..))" id="myPointcut" /> <!-- 所有业务层的以save开头的方法 -->
<aop:pointcut expression="execution(* cn.winner.oa.service.*.save*(..))" id="myPointcut" /> <!-- 可以使用 && 与 || 与! 或是 and or not 进行多个表达式的组合 -->
<!-- 所有业务层的以save或delete开头的方法-->
<aop:pointcut expression="execution(* save*(..)) || execution(* delete*(..))" id="myPointcut" /> <!-- 所有业务层的以save或delete开头的方法-->
<aop:pointcut expression="execution(* save*(..)) or execution(* delete*(..))" id="myPointcut" /> <!-- 所有业务层的所有不是查询的方法-->
<aop:pointcut expression="execution(* *(..)) and !execution(* query*(..))" id="myPointcut" /> <!-- 所有业务层的所有不是查询的方法 -->
<aop:pointcut expression="execution(* *(..)) and not execution(* query*(..))" id="myPointcut" /> <aop:pointcut expression="!execution(* query*(..))" id="myPointcut" />
aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAr0AAADECAIAAAAd9A6vAAAgAElEQVR4nOyd+XNb13n3z/+UX9xp00HTmXRci02adNqmcZ3GjSRO08SWLKqMSFuqnU5UU5LVaDwROa5rSRFBSiCxERsJSNi4giBBUtiJSwIQdmIHV1Hk+8NjnffqbriASGLh+QyGA16ce+5z9u997jnnokMCgUAgEAgEcaBGG0AgEAgEAqFlILqBQCAQCASCWIhuIBAIBAKBIBaiGwgEAoFAIIilTt1wQCAQCAQCoZU5Xt3AecmXBAKBQCAQWo03kRHVdQNdIuy/4gWBQCAQCIRWBo/pdDHxRroBKwYsFPb29nZ3d3d3d3cIBAKBQCC0MjCg7+3tYRkhRj3w6gaGaNjd3d3e3t7c3KxUKuVyuVQqlUqlIoFAIBAIhFYDBvFyuVypVDY3N7e3t3d3d0VKByHd8PLlS/AxbG9vVyqVYrGYy+UymUwqlUq8Ik44UmLtQqMzkvAtja4IhG9pdEVoUkiGNwQ8gqdSqUwmk8vlisVipVLZ3t4G3wNIh9p0A/Y0gGgolUrZbDaRSEQiEYqigsGgz+fzer0ewhvgPn00OsvbnEYXL6FmGl1lTpRGZ7bbfcoyXBiv1+vz+YLBIEVRkUgkkUhks9lSqQTSAXsdxOoG/ITixYsXIBr4RAehPhirUfbbHcYMXjGZQ+CD1Kg2oKYW0cztolV6vDoy/FSxsrISDAaj0WgmkwHpgF0OnNnFrRugaHd3dyuVSjabPX6zTwv09rO/v9/2U03pk272WVN2T7SHa1PoC6tOQ41qdYRbBL2XaF2aqscTk+EEi8XidDp9Pl80Gs1ms5VKZXd3d5/f5cDUDbiYwdlQKBQSicSJWN7+4Lzd39/f29vb2dlhTzVtM+iTbnZ2drD7i8HJ33+0EzARGjritq9RrQ5fi6CPuy3aLtj39M3Q4wlneKPHhGZBLpebTKb5+flgMJhIJAqFgrDLgVs3QDFvbm7mcrloNHpSxrc5BzRHzvb2drlcLhQK2Ww2k8mk0+lUO5JOpzOZTDabLRQK5XIZmi593TC5P66P3deB7rhUKuXz+fauUa0Ou0XAjR193G25dsF3T4+T08Aejy/D+e6kTydfffWVXC63WCwrKyvRaDSXy21uboLGEqsbsDwsl8uZTIaiqJMyvp2hi4atra1isbixsZFIJKLR6Pr6OkVRq+0IRVHr6+vRaDSRSGxsbBQKBbzgZ2dnZ3t7m9wf10f5FZVKpVQqwVqndDodj8cjkUgb16hWh9EiisXi1tbWzisxDXJhp9X8Rpz39PjGoLE9HmeGE+nA4NatWw8ePNDr9U6nk6KoTCZTLpcFZkdy6wYo7HK5nEqlgsHgSRnfzkDGwvqUYrF4iNDp+Xg8ntXV1Wg0mk6n8/l8pVKBXqZUKrW9x+WYSKfTcCMFpFIpJLlGPq3ywS0ik8lg6YAVQ8t5Ijnv6fHjM+jxkETSwA8jw2HJANENmE8//bS/v1+hUMzMzASDwVQqVS6XoRBr1g2lUimRSPh8vpMyvm3BzoadnZ1yubyxsdHwsfwkP7Ozsy6Xy+fzhcPhVCqVzWbz+Ty+P25vj8sxEQqF4EYKWFtba/hYSD7iP9Ai/H4/Hsk2Nze3trYqlUqhUGg5TyT7nh67Fbe2tkql0sbGRmN1Az3DNzY2yuXyzs4OcTlgenp67ty5I5PJ7Ha7z+dLJBKlUqke3bCzswO6wev1npTx7Qn3VFOEDhGanJw0mUx6vV6r1ep0Or1ePz4+PjExYTQaTa2J0WicmJgYHx/X6/U6nQ6SaTKZJicnFxcXA4FAJBJJJpOpVOra4TXyqe9z9eDq1YOrV19eXV5ehlXpz549gwHJYrFMTEzodLq2qVGtDqNFQDGZTKbJyUmXy7W6uhqPx3O5HHj78/n8NXTYoh+6WxGeSG5tbW1ububz+UQiAeP3CfR4rAyXIImEnuFi5v2dNi5fvnz79u3h4WGbzeb1ekE3wOOzmnVDsViMx+NEN7whWDfAVNNsNhuNRvGAqtFolEqlQqFQqVRarRYaUuv28kajEVqsVqtVqVSQTI1GYzQap6enV1ZWVldXw+FwJBJp+Ojbuh+sGyYnJ6enp2dnZ+fm5mBA0uv1arVaLpfL5fL2qFGtDqNFQDFpNBqTyTQ7O+t2u8PhcDqdzuVy4IFr+PBf9wff00ciEXCiwOSMTCYTiUTw+H3cPR4rwyVIIsEZ7vF4YKkhzPsjugG4dOnSzZs3h4aGLBaL1+uNx+PFYvGNdIPH4zkp49sTvEQF9sPIZDJra2swoOr1eqVSOTo6qlAoxsbGDAaDyWQym81Wq9Vms9lsNnvrAAZbrVaz2WwymQwGw9jYGCRToVDodDqr1bqwsODz+UKhUCgUgiHQbrcbjcZ28rgcE/S7KK1We/Xg6if7n+j1eqPR+PTpU7PZDAOSSqUaHR2VyWRyuVytVrd0jWp1OFsEFJNSqdTr9TabbWlpKRQKgXs/nU4/f/4cxuAm90Qy7unBZtOre/pgMBiPx7PZbLFYLBQKqVSKoigYv4+1x+PJcAmSSCDD7Xb78vLy2tpaJpPBWxQQ3XB4eHjx4sWbN29KpVKz2ezxeIhuaDx03VAul9PpdCgUggFVq9UqFApoQuPj41ardXp62uFwOJ3OxdbE6XQ6HI7p6Wmr1To+Pg7JlMvlGo3m6dOnc3Nzz5498/v9Pp8PdIPRaBwbG2snj8sxQb+LUiqVoBug5uj1eoPBAAOSXC6XyWSjo6MgGtqgRrU6jBYBxaRQKLRardlsXlhYCAaDsVgslUolEon19XU8BjezJ5JxTw82050okUgEJkHncrlkMrm6ugrj9wn0eKwMlyCJBDLcYrEsLi6GQqF0Og3z/ohuAC5cuHDjxo3BwUGiG5oFrBtgykgqlVpdXYUBVafTqVSqsbExhBBCaH5+fmVlxev1BgIB9Iqqk5I4g4k8t47AwgQCAa/Xu7KyMj8/b7PZIJlKpVKr1T558mR2dnZ5ednj8aysrIBu0Ol0CoWiUR4XSLjwkTeJ7Q2BCNl3UWq1GnQDlggajQbrhtHRUZVKBaIB16hai/jNK9UbntUMHInljBaB3UI6nc5sNjudTpisl0gknj9/vrq6CmMwXPpI2kUd1VLgFM57erAZ39MvLS1RFJVMJrPZ7MbGRjweDwaDMH5Dj4crNr3Hq6842AdZGS5BEglkuMViWVhYWF1dTaVS8Pye6AaA6IamQ0A36PV6jUZjMBig9ns8HoqiotFoPB6HI2IWQbFDYs0h/nR2YPExAMlkMplMwvoIiqI8Ho/D4YBkjo2N6XQ60A1LS0tut3tpaQl0g0ajkcvljPsPxIJ9V8F3nDMYX0j2TyKj5QxM/7eq5XzwxU+/izIYDKAbHj9+LJPJ4JYU6walUqnT6Rg1Cv6FGaliqo*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" alt="" width="651" height="182" />
使用注解实现AOP
为了在Spring配置中使用@AspectJ切面,你首先必须启用Spring对@AspectJ切面配置的支持,并确保自动代理:
<!--启用Spring对@AspectJ的支持 -->
<!-- 使用基于注解的方式配置切面,需要有下面这个配置 -->
<aop:aspectj-autoproxy proxy-target-class="true"></aop:aspectj-autoproxy>
beans.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:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-2.5.xsd "> <!-- 配置Service对象-->
<bean id="userService" class="com.winner.test.UserService"/> <!-- 配置一个通知对象 -->
<bean id="logAdvice" class="com.winner.test.LogAdvice"/> <!--启用Spring对@AspectJ的支持 -->
<!-- 使用基于注解的方式配置切面,需要有下面这个配置 -->
<aop:aspectj-autoproxy proxy-target-class="true"></aop:aspectj-autoproxy> </beans>
切面:
@Aspect
public class LogAdvice { // 声明一个切入点。本方法不能有返回值与参数
@Pointcut("execution(* *(..))")
private void myPointcut() {
} // 前置通知,在原方法执行之前
@Before("myPointcut()")
public void before() {
System.out.println("== before ==");
} // 最终通知,在原方法执行之后
// 如果原方法有异常,也会执行
@After("myPointcut()")
public void after() {
System.out.println("== after ==");
} // 后置通知,在原方法执行之后
// 如果原方法有异常,则不执行。
// 方法一:@AfterReturning("myPointcut()")
// 方法二:@AfterReturning(pointcut = "myPointcut()")
// 可以使用returning参数指定返回值的对应的参数名,Spring就会在调用本方法时把返回值传给指定名称的参数
@AfterReturning(pointcut = "myPointcut()", returning = "returnValue")
public void afterReturning(Object returnValue) {
System.out.println("== afterReturning ==");
} // 异常通知,在出现异常之后
// @AfterThrowing("myPointcut()")
@AfterThrowing(pointcut = "myPointcut()", throwing = "ex" )
public void afterThrowing(Exception ex) {
System.out.println("== afterThrowing ==");
} // 环绕通知,在原方法调用的前后执行。
// 在原方法执行出异常后,环绕通知的后面部分不会执行。
// 一定要在执行完原方法后,从本方法中返回结果。
@Around("myPointcut()")
public void around(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("== 环绕通知(前) ==");
Object result = joinPoint.proceed(); // 执行原方法
System.out.println("== 环绕通知(后) ==");
}
}