Spring-AOP之aspectj注解方式

来源:互联网 发布:方向余弦矩阵 编辑:程序博客网 时间:2024/05/23 11:47
一、简介
 1、AOP用在哪些方面:AOP能够将那些与业务无关,却为业务模块所共同调用的逻辑或责任,例如事务处理日志管理权限控制异常处理等,封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可操作性和可维护性。
 2、AOP中的概念:
    Aspect(切面):指横切性关注点的抽象即为切面,它与类相似,只是两者的关注点不一样,类是对物体特征的抽象,而切面是横切性关注点的抽象.
   joinpoint(连接点):所谓连接点是指那些被拦截到的点(可以是方法、属性、或者类的初始化时机(可以是Action层、Service层、dao层))。在spring中,这些点指的是方法,因为spring只支持方法类型的连接点,实际上joinpoint还可以是field或类构造器)
   Pointcut(切入点):所谓切入点是指我们要对那些joinpoint进行拦截的定义,也即joinpoint的集合.
   Advice(通知):所谓通知是指拦截到joinpoint之后所要做的事情就是通知.通知分为前置通知,后置通知,异常通知,最终通知,环绕通知
   Target(目标对象):代理的目标对象
   Weave(织入):指将aspects应用到target对象并导致proxy对象创建的过程称为织入.
   Introduction(引入):在不修改类代码的前提下, Introduction可以在运行期为类动态地添加一些方法或Field.

 3、AOP带来的好处::降低模块的耦合度;使系统容易扩展;更好的代码复用性

二、通过注解方式实现Spring的AOP

1.定义业务类

接口:

package cn.slimsmart.spring.demo.aop;public interface UserService {String save(String name);String update(String name);String delete(String name);}
实现:

package cn.slimsmart.spring.demo.aop;import org.springframework.stereotype.Service;@Service  <span style="font-family: Arial, Helvetica, sans-serif;">//使用自动注解的方式实例化并初始化该类</span>public class UserServiceImpl implements UserService{@Overridepublic String save(String name) {System.out.println("--------save");return "save";}@Overridepublic String update(String name) {System.out.println("--------update");System.out.println(1/0);return "update";}@Overridepublic String delete(String name) {System.out.println("--------delete");return "delete";}}
2.定义切面类

package cn.slimsmart.spring.demo.aop;import org.aspectj.lang.JoinPoint;import org.aspectj.lang.ProceedingJoinPoint;import org.aspectj.lang.annotation.After;import org.aspectj.lang.annotation.AfterReturning;import org.aspectj.lang.annotation.AfterThrowing;import org.aspectj.lang.annotation.Around;import org.aspectj.lang.annotation.Aspect;import org.aspectj.lang.annotation.Before;import org.aspectj.lang.annotation.Pointcut;import org.springframework.stereotype.Component;//@Aspect : 标记为切面类//@Pointcut : 指定匹配切点集合//@Before : 指定前置通知,value中指定切入点匹配//@AfterReturning :后置通知,具有可以指定返回值//@AfterThrowing :异常通知//@Around 环绕通知 环绕通知的方法中一定要有ProceedingJoinPoint 参数,与Filter中的  doFilter方法类似//注意:前置/后置/异常通知的函数都没有返回值,只有环绕通知有返回值@Component //使用自动注解的方式实例化并初始化该类@Aspectpublic class TestInterceptor {//如果要设置多个切点可以使用 || 拼接@Pointcut("execution(* cn.slimsmart.spring.demo.aop.UserServiceImpl.*(..))")private void anyMethod() {}// 定义一个切入点@Before(value="anyMethod()")public void doBefore(JoinPoint joinPoint) {System.out.println("前置通知");}@AfterReturning(value="anyMethod()",returning="result")public void doAfter(JoinPoint jp, String result) {System.out.println("后置通知");}@After("anyMethod()")public void after() {System.out.println("最终通知");}@AfterThrowing(value="execution(* cn.slimsmart.spring.demo.aop.*.*(..))",throwing="e")public void doAfterThrow(JoinPoint joinPoint, Throwable e) {System.out.println("异常通知");}@Around("execution(* cn.slimsmart.spring.demo.aop.*.*(..))")public Object doBasicProfiling(ProceedingJoinPoint joinPoint) throws Throwable {System.out.println("进入环绕通知");System.out.println("目标类名称:"+joinPoint.getTarget().getClass().getName());System.out.println("方法名称:"+joinPoint.getSignature().getName());System.out.println("方法参数:"+joinPoint.getArgs());System.out.println("staticPart:"+ joinPoint.getStaticPart().toShortString());System.out.println("kind:"+joinPoint.getKind());System.out.println("sourceLocation:"+joinPoint.getSourceLocation());Object object = joinPoint.proceed();// 执行该方法System.out.println("退出方法");return object;}}
3.applicationContext.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:aop="http://www.springframework.org/schema/aop"   xmlns:tx="http://www.springframework.org/schema/tx"   xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsdhttp://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsdhttp://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd"><context:component-scan base-package="cn.slimsmart.spring.demo" /> <!-- 打开aop 注解 -->    <aop:aspectj-autoproxy proxy-target-class="true"/></beans>
4.单元测试类
package cn.slimsmart.spring.demo;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 cn.slimsmart.spring.demo.aop.UserService;@RunWith(SpringJUnit4ClassRunner.class)//让junit工作在spring环境中@ContextConfiguration(locations={"classpath:applicationContext.xml"})public class SpringTest{@AutowiredUserService userService;@Testpublic void testStart(){System.out.println("启动服务");userService.delete("abc123");System.out.println("====================");userService.update("aaa");}}

运行结果:执行update抛异常:/ by zero

启动服务进入环绕通知目标类名称:cn.slimsmart.spring.demo.aop.UserServiceImpl方法名称:delete方法参数:[Ljava.lang.Object;@2de1c3f9staticPart:execution(UserServiceImpl.delete(..))kind:method-executionsourceLocation:org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint$SourceLocationImpl@6ed745c2前置通知--------delete退出方法最终通知后置通知====================进入环绕通知目标类名称:cn.slimsmart.spring.demo.aop.UserServiceImpl方法名称:update方法参数:[Ljava.lang.Object;@1d370b4dstaticPart:execution(UserServiceImpl.update(..))kind:method-executionsourceLocation:org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint$SourceLocationImpl@8c6fb37前置通知--------update最终通知异常通知
注:pom.xml引入的jar包

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>cn.slimsmart.spring.demo</groupId><artifactId>spring-demo</artifactId><version>0.0.1-SNAPSHOT</version><dependencies><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>4.1.4.RELEASE</version></dependency><!-- <dependency> --><!-- <groupId>org.springframework</groupId> --><!-- <artifactId>spring-tx</artifactId> --><!-- <version>4.1.4.RELEASE</version> --><!-- </dependency> --><!-- <dependency> --><!-- <groupId>org.springframework</groupId> --><!-- <artifactId>spring-jdbc</artifactId> --><!-- <version>4.1.4.RELEASE</version> --><!-- </dependency> --><dependency><groupId>org.springframework</groupId><artifactId>spring-test</artifactId><version>4.1.4.RELEASE</version></dependency><dependency><groupId>aspectj</groupId><artifactId>aspectjrt</artifactId><version>1.5.4</version></dependency><dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.8.4</version></dependency><dependency><groupId>cglib</groupId><artifactId>cglib</artifactId><version>3.1</version></dependency><dependency><groupId>cglib</groupId><artifactId>cglib-nodep</artifactId><version>3.1</version></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version></dependency></dependencies></project>

若不使用注解的方式,使用schema xml配置(也可以基于spring接口方式实现)的方式,如下参考:

 <aop:config>        <aop:aspect id="businessAspect" ref="testInterceptor">            <!-- 配置指定切入的对象 -->            <aop:pointcut id="point_cut" expression="execution(* cn.slimsmart.spring.demo.aop.UserServiceImpl.*(..))" />            <!-- 前置通知 -->            <aop:before method="doBefore" pointcut-ref="point_cut" />            <!-- 后置通知 returning指定返回参数 -->            <aop:after-returning method="doAfter"                pointcut-ref="point_cut" returning="result" />            <aop:around method="doAround" pointcut-ref="point_cut"/>            <aop:after-throwing method="doThrow" pointcut-ref="point_cut" throwing="e"/>        </aop:aspect>    </aop:config>

0 0
原创粉丝点击