spring-aop

理论知识

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注解的方法
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值