Spring注解开发9 --- AOP注解

AOP方法上的注解有:

@Before():这个是前置调用,在方法之前掉调用

@After() 这个称为后置调用,不管方法执行是正常还是异常都会调用

@Around() 这个表示的是环绕 在调用方法之前和之后调用 一般用来记录日志,需要joinPoint.proceed()推动目标进行

@AfterReturning()这个表示的是正常运行后,返回数据的时候调用

@AfterThrowing()这个表示的是抛出异常的时候调用

@Aspect:告诉容器这是一个切面类

@Pointcut() :切入点表达式的位置

@EableAspectjAutoProxy:开启基于注解的aop模式,原来是在xml中配置

        他有一个属性 proxyTargetClass默认是false.

  • 即使用jdk默认代理模式,AspectJ代理模式是CGLIB代理模式
  • 如果目标对象实现了接口,默认情况下会采用JDK的动态代理实现AOP
  • 如果目标对象实现了接口,可以强制使用CGLIB实现AOP (此例子我们就是强制使用cglib实现aop) (设置proxyTargetClass属性为false)
  • 如果目标对象没有实现了接口,必须采用CGLIB库,spring会自动在JDK动态代理和CGLIB之间转换

注:jdk代理是重新在原来的类中动态插入代码生成新的代理类(.java文件),在重新编译成.class文件;而CGLIB代理是直接在class文件中插入二进制代码,不会生成新的代理类。所以CGLIB代理效率比jdk代理效率高。 操作字节码可以使用ASM框架技术实现。

例子:

1.需要导入包

 <dependency>
      <groupId>org.springframework</groupId>
       <artifactId>spring-aspects</artifactId>
      <version>5.0.8.RELEASE</version>
</dependency>

2.业务类

public class Caculator {

    public Integer cal(int a,int b) {
        System.out.println("Caculator ..cal");
        return  a/b;
    }
}

3.切面类

@Aspect
public class LogsAspects {

    @Pointcut("execution( * com.wusu.aop.Caculator.*(..))")
    public void pointcut(){};

    @Before("pointcut()")
    public void logStart(JoinPoint joinPoint){
        System.out.println("开始计算"+joinPoint.getSignature().getName()+": 参数是:"+ Arrays.asList(joinPoint.getArgs()).toString());
    }
    @After("pointcut()")
    public void logEnd(JoinPoint joinPoint){
        System.out.println("结束计算"+joinPoint.getSignature().getName());
    }
    //这个JoinPoint必须放在第一个才能使用
    @AfterReturning(value = "pointcut()",returning = "result")
    public void logReturn(JoinPoint joinPoint,Object result){
        System.out.println("开始返回"+joinPoint.getSignature().getName()+",return :"+ result);
    }
    @Around("pointcut()")  //这个必须要有返回值值,否则正常的有返回值的没有结果
    public Object logRound(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("环绕执行前。。。参数是:"+joinPoint.getArgs());
        Object object = joinPoint.proceed(joinPoint.getArgs());
        System.out.println("环绕执行后。。。参数是:"+joinPoint.getArgs());
        return object;
    }
    @AfterThrowing(value = "pointcut()",throwing = "exception")
    public void logThrowing(Exception exception){
        System.out.println("抛出异常"+exception);
    }
}

对于@PointCut里面的表达式解释:

定义切入点表达式

 1>:定义一个没有实现的方法

2>:在这个方法上 使用切入点表达式的注解Pointcut

execution ()你记成语法规则

 第一个 * 代表的是返回注入方法的返回数据的类型

第二个 * 代表的是UserDAO这个类里面的所有方法

“..” 代表的是注入方法里面的参数类型 这里因为可以是任意类型 所以使用 “..” ,这里是两个点

4. 配置类,业务类和切面类都需要放入IOC容器中

         需要使用@EnableAspectJAutoProxy开启自动代理

@EnableAspectJAutoProxy
@Configuration
public class MainConfig {
    @Bean
    public Caculator caculator(){
        return  new Caculator();
    }
    @Bean
    public LogsAspects logsAspects(){
        return new LogsAspects();
    }
}

5.测试类,需要从IOC容器中获取这个业务类才是被代理后的类

public class TestAop {

    public static void main(String[] args) {
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
        Caculator caculator = applicationContext.getBean(Caculator.class);
        int cal = caculator.cal(16, 0);

    }
}

结果显示:

开始计算cal: 参数是:[16, 0]
Caculator ..cal
结束计算cal
抛出异常java.lang.ArithmeticException: / by zero

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值