spring-aop

来源:互联网 发布:知茵女装 编辑:程序博客网 时间:2024/05/16 13:00

理论知识

1.切面(aspset):一个关注点的模块化。这个关注点横切多个对象

关注点:事务,数据库连接池,权限控制,日志分析,安全性的处理

2.连接点(Joinponit):程序执行过程中某个特定的点

代理对象调用的方法(完成额外的操作)

3.通知(Advice):在切面某个特定点上的执行的动作

切面中的方法(实现额外操作)

4.切入点(Ponitcut):匹配连接点的断言。

一种匹配规则,满足规则才执行通知

5.目标对象(target):被一个或多个切面通知的对象

真实对象,真实对象的方法—目标方法

不使用注解

在spring-mvc.xml文件中

    <!-- aop -->    <bean  id="operateLogger" class="aspect.OperateLogger" />    <aop:config>    <!-- <aop:aspect ref="operateLogger">            <aop:before method="log1" pointcut="within(spring.controller..*)"/>        </aop:aspect> -->        <!-- <aop:aspect ref="operateLogger">            <aop:around method="log2" pointcut="within(spring.controller..*)"/>        </aop:aspect> -->        <aop:aspect ref="operateLogger">            <aop:after-throwing method="log3" throwing="e" pointcut="within(spring.controller..*)"/>        </aop:aspect>    </aop:config>

>
- before 前置通知
- around 坏绕通知
- after-throwing 异常通知

throwing=”e” 和形参绑定,e的名字不能随意定,和方法中的形参名一样

在OperateLogger类中

    public class OperateLogger {        private Logger logger = Logger.getLogger(this.getClass());         //前置通知方法        public void log1(){            logger.info("--记录用户操作记录");        }        //可加参数        public void log1(JoinPoint p){            logger.info("--记录用户操作记录");        }        //坏绕通知方法        public Object log2(ProceedingJoinPoint p) throws Throwable{            //目标组件的类名            String className = p.getTarget().getClass().getName();            //调用的方法名            String method = p.getSignature().getName();            //获取目标方法            Signature signature = p.getSignature();                MethodSignature methodSignature = (MethodSignature)signature;                Method targetMethod = methodSignature.getMethod();              //当前时间            String date = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").                    format(new Date());            //拼写日志            String msg = "-->用户在"+date+",执行了"+className+"."+method+"()";            //记录日志            logger.info(msg);            //执行目标组件的方法            Object obj = p.proceed();            //调用目标组件后也可以处理一些任务            logger.info("-->调用目标组件后的业务方法");            return obj;        }        //异常通知方法        public void log3(Exception e){            StackTraceElement[]  elems = e.getStackTrace();            logger.info("-->"+elems[0].toString());        }        //参数变更,JoinPoint必须为第一位参数        public void log3(JoinPoint p,Throwable e){            StackTraceElement[]  elems = e.getStackTrace();            logger.info("-->"+elems[0].toString());        }    }
  • 前置后置可以接收参数JoinPoint
  • 异常通知可以接收JoinPoint,Throwable
    <aop:after-returning method="testAfter" pointcut-ref="pc" returning="name" />       //通过后置通知获取返回值,参数名称必须匹配    public void testAfter(String name){        System.out.println("后置通知的获得方法的返回值是"+name);    }    //后置通知    @AfterReturning(value="pointCut()",returning="name")    public void testAfter(String name){        System.out.println("后置通知的获得方法的返回值是"+name);    }    //异常通知    @AfterThrowing(value="pointCut()" , throwing="e" )    public void doException(JoinPoint p,Exception e){    }

注解方式

@Aspect 标注为方面组件

@Before 前置通知

@Around 坏绕通知

@AfterThrowing 异常通知

@AfterReturning 后置通知

@After 最终通知

5大通知只有坏绕通知才能控制目标方法的执行,坏绕通知最强大

开启注解:

    <!-- 开启aop组件 -->    <aop:aspectj-autoproxy proxy-target-class="true" />

proxy-target-class=”true”,强制使用cglib创建对象

声明方面组件

    @Component    @Aspect    public class OperateLogger {        private Logger logger = Logger.getLogger(this.getClass());         @Before("within(spring.controller..*)")        public void log1(){            logger.info("--记录用户操作记录");        }        //通过空方法定义切入点表达式        @Pointcut(value="within(service..*)")        public void pointCut(){}        @Before("pointCut()")        public void testBefore(){            System.out.println("调用方法前");        }    }

含有注解的切入点

    @Around("pointCut() && @annotation(tran)")    public Object transaction(ProceedingJoinPoint p,Transactional tran) throws Throwable{        System.out.println("事务开启");        Object result = p.proceed();        System.out.println("事务提交");        return result;    }

方法上的注解必须是Transactional类型才能被匹配成功,如果没有被匹配成功,这个切入点不被匹配,则不会执行这个切入方法

切入点(pointcut):

1.within(spring.controller..*):表示匹配spring.controller下的所有包

2.execution( 返回值类型 包名 类名 方法名(参数类型1,参数类型2 …) )

  • execution(* cn.tarena.ht.service..(..))
  • @java.lang.Deprecated * *(..) :任何持有@java.lang.Deprecated注解的方法
原创粉丝点击