Spring04——环绕通知、注解实现AOP

环绕通知

执行目标方法之前,之后,异常,最终等各个地方都可以进行的通知,

1、编写实现接口 MethodInterceptor 的类 LogAround 重写  public Object invoke(MethodInvocation methodInvocation) throws Throwable  方法.

i.使用环绕通知时,目标方法的一切信息都可以用 methodInvocation 参数来获取

ii.环绕通知可以获取目标对象的一切控制权。

package com.demo.aop;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;

public class LogAround implements MethodInterceptor {

    @Override
    public Object invoke(MethodInvocation methodInvocation) throws Throwable {
        Object result = null;
        try{
            System.out.println("环绕的前置通知。。。。。");     //在 methodInvocation.proceed() 前的就是前置通知
            result = methodInvocation.proceed(); //控制目标方是否执行,写了这就就会执行 add|()方法,不写就不会执行该方法
//        result目标方法的返回值  add()的返回值
            System.out.println("环绕的后置通知。。。。。");     //在 methodInvocation.proceed() 后的就是后置通知
        }catch (Exception e){
            System.out.println("环绕的在catch的异常通知.....");
        }


        return result;
    }
}

业务类

package dao.entity;

import org.springframework.stereotype.Component;


/**
 * @Component("studentdao")相当于
 *  <bean id="studentdao" class="dao.entity.serviceImpl">
 */
@Component("studentdao")
public class serviceImpl {
    public void add(){
        System.out.println("zengjia ...............");
    }
    public void delete(){
        System.out.println("删除了。。。。。。。。。。");
    }
}

2、application.xml中配置

    <!--    环绕通知-->
    <bean id="LogAround" class="com.demo.aop.LogAround"></bean>
    <aop:config>
        <aop:pointcut id="pointcut3" expression="execution(public void dao.entity.serviceImpl.add())"/>
        <aop:advisor advice-ref="LogAround" pointcut-ref="pointcut3"/>
    </aop:config>

3、测试Test类

package demo;

import com.entity.Course;
import com.entity.Student;
import dao.entity.serviceImpl;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;


public class Test {

    public static void test1(){
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        Student s = (Student)context.getBean("student");
        context.getBean("teacher");
        Course c = (Course)context.getBean("course");
        System.out.println(c);
    }
    public static void test2(){
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        serviceImpl s = (serviceImpl)context.getBean("studentdao");
        s.add();
        s.delete();
    }

    public static void main(String[] args){
        test2();
    }
}

二、注解实现AOP

1、jar包

2、配置

  将业务类,通知 纳入到IOC容器中,开启注解对AOP的支持 

<context:component-scan base-package="dao.entity,com.zhujie.aop"></context:component-scan>   
 <aop:aspectj-autoproxy> </aop:aspectj-autoproxy>

3、编写业务类

package com.zhujie.aop;

import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;

@Component("LogAnnotation") //<bean id="LogAnnotation" class="com.zhujie.aop.LogBefore"><bean>
@Aspect     //此类是一个通知
public class LogBefore {
    @Before("execution(public void dao.entity.serviceImpl.add())")   //定义切点
    public void myBefore(){
        System.out.println("注解形式的前置通知。。。。。。。");
    }
    @AfterReturning("execution(public void dao.entity.serviceImpl.add())")
    public void myAfter(){
        System.out.println("注解形式的后置通知.........");
    }

}

如何获取自定义函数的参数,返回值??

 需要使用一个对象,JoinPoint 

package com.zhujie.aop;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;

import java.lang.reflect.Array;
import java.util.Arrays;

@Component("LogAnnotation") //<bean id="LogAnnotation" class="com.zhujie.aop.LogBefore"><bean>
@Aspect     //此类是一个通知
public class LogBefore {
    @Before("execution(public void dao.entity.serviceImpl.add())")   //定义切点
    public void myBefore(JoinPoint jp){
        System.out.println("注解形式的前置通知。。。。。。。"+"目标对象"+jp.getTarget()+"调用的方法名"+jp.getSignature().getName()
                +"方法的参数"+ Arrays.toString(jp.getArgs()));

    }

    //returning = "returningValue" 指明这个方法的返回值是 returningValue
    @AfterReturning(pointcut="execution(public void dao.entity.serviceImpl.add())",returning = "returningValue")
    public void myAfter(JoinPoint jp,Object returningValue){
        System.out.println("注解形式的前置通知。。。。。。。"+"目标对象"+jp.getTarget()+",调用的方法名"+jp.getSignature().getName()
                +"方法的参数"+ Arrays.toString(jp.getArgs())+",返回值"+returningValue);
    }

}

 各种异常示例:

package com.zhujie.aop;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

import java.lang.reflect.Array;
import java.util.Arrays;

@Component("LogAnnotation") //<bean id="LogAnnotation" class="com.zhujie.aop.LogBefore"><bean>
@Aspect     //此类是一个通知
public class LogBefore {
//    前置通知
    @Before("execution(public void dao.entity.serviceImpl.add())")   //定义切点
    public void myBefore(JoinPoint jp){
        System.out.println("注解形式的前置通知。。。。。。。"+"目标对象"+jp.getTarget()+"调用的方法名"+jp.getSignature().getName()
                +"方法的参数"+ Arrays.toString(jp.getArgs()));

    }
    //后置通知
    //returning = "returningValue" 指明这个方法的返回值是 returningValue
    @AfterReturning(pointcut="execution(public void dao.entity.serviceImpl.add())",returning = "returningValue")
    public void myAfter(JoinPoint jp,Object returningValue){
        System.out.println("注解形式的前置通知。。。。。。。"+"目标对象"+jp.getTarget()+",调用的方法名"+jp.getSignature().getName()
                +"方法的参数"+ Arrays.toString(jp.getArgs())+",返回值"+returningValue);
    }
//    环绕通知
    @Around("execution(public void dao.entity.serviceImpl.add())")
    public void myAround(ProceedingJoinPoint pjp){      //环绕通知方法的参数是 ProceedingJoinPoint pjp
        //前置通知
        System.out.println("前置通知........");
        try{
            pjp.proceed();  //执行方法
//            方法执行之后
            System.out.println("后置通知........");
        }catch (Throwable e){
//        发生异常时
            System.out.println("发生异常时,异常通知");
        }finally {
            System.out.println("最终通知,最终通知可以单独写");
        }
    }
//    异常通知
    @AfterThrowing("execution(public void dao.entity.serviceImpl.add())")
    public void myException(){
    System.out.println("异常通知、、");
}
//    最终通知
    @After("execution(public void dao.entity.serviceImpl.add())")
    public void myAfter(){
        System.out.println("单独写的最终通知");
    }
}

三、基于 Schema形式的AOP

类似于实现接口的方式,

i .编写一个普通类
ii.

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值