spring学习--面向切面编程AOP和AspectJ

—AOP(面向切面编程)

1.代理模式

代理模式是指,为其他对象提供一种代理以控制对这个对象的访问.在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户类和目标对象之间起到中介的作用.作用是增强功能和控制访问.分为:

静态代理:在程序运行之前已经定义好代理类,代理类和目标类要实现相同的接口
动态代理:在程序运行时才确定代理类和目标类的关系,又分为

    a.JDK动态代理,要求目标对象必须实现接口
    b.CGLIB动态代理,要求目标类必须能够被继承,即不是final类.它的生成原理是生成目标类的子类,而子类是增强过的,这个子类对象就是代理类

2.AOP简介

AOP,即面向切面编程,是OOP的补充.利用AOP可以让业务逻辑和业务逻辑方法解耦合,提高了代码的可用性,大大提高了开发效率.
底层采用JDK和CGLIB动态代理实现的.

3.什么是AspectJ

AspectJ是一个面向切面的框架,它扩展了Java语言。AspectJ定义了AOP语法,它有一个专门的编译器用来生成遵守Java字节编码规范的Class文件。

4.基于Annotation的五种通知

a.@Before前置通知

package com.aspectj.demo1;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;

import com.aspectj.common.LoggerUtil;

@Aspect
// 定义切面类,就是对业务方法进行增强
public class MyAspect {

    // 前置通知
    // 在目标方法执行前执行前置通知
    @Before(value="execution(public * com.aspectj.demo1.SomeServiceImpl.run(..))")
    public void beforeExcute(JoinPoint point) throws Exception{
        System.out.println("前置通知被执行");

        // 得到切入点表达式
        // execution(void com.aspectj.demo1.SomeService.run())
        LoggerUtil.doLog(point);

        // 得到方法签名
        // void com.aspectj.demo1.SomeService.run()
        LoggerUtil.doLog(point.getSignature());

        // 得到目标对象
        // com.aspectj.demo1.SomeServiceImpl@4b5a5ed1
        LoggerUtil.doLog(point.getTarget());

        // 得到方法名字
        // run
        Signature signature = point.getSignature();
        String name = signature.getName();
        LoggerUtil.doLog(name);
    }
}

b.@AfterReturning后置通知

package com.aspectj.demo2;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;

@Aspect
// 定义切面类,就是对业务方法进行增强
public class MyAspect {

    // 后置通知
    // 因为是在业务方法结束后执行,所以有返回值
    // 但是增强后的值不会改变原来业务方法的返回值
    @AfterReturning(value="execution(* *..SomeServiceImpl.*(..))",returning="result")
    // result表示的是业务方法的返回值
    public void afterReturningExecute(JoinPoint point ,Object result){
        // 获取方法的名字
        String name = point.getSignature().getName();
        if("getName".equals(name)){
            result += " end";
        }
        System.out.println("后置通知增强后的返回值:" + result);

    }
}

c.@Around环绕通知

package com.aspectj.demo3;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;

@Aspect
@Component
// 定义切面类,就是对业务方法进行增强
public class MyAspect {

    // 环绕通知
    // 在目标方法执行前后都执行
    // 必须有返回值
    // 可以改变原目标方法的返回值
    @Around(value="execution(* *..SomeServiceImpl.getName(..))")
    public Object aroundExecute(ProceedingJoinPoint point) throws Throwable{

        // 得到目标方法的返回值
        String result = (String) point.proceed();
        result += " my";

        System.out.println("环绕通知的返回值:" + result);
        return result;

    }

}

d.@AfterThrowing异常通知

package com.aspectj.demo4;

import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;

import com.aspectj.common.LoggerUtil;

@Aspect
@Component
// 定义切面类,就是对业务方法进行增强
public class MyAspect {

    // 异常通知
    @AfterThrowing(value="execution(* *..SomeServiceImpl.run(..))",throwing="e")
    public void afterThrowingExecute(Throwable e) throws Exception{
        System.out.println("程序发生异常");
        LoggerUtil.doLog(e);
    }

}

e.@After最终通知

package com.aspectj.demo5;

import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;

@Aspect
@Component
// 定义切面类,就是对业务方法进行增强
public class MyAspect {

    // 最终通知
    // 无论目标对象是否抛出异常,该增强都会被执行
    @After(value="execution(* *..SomeServiceImpl.run(..))")
    public void afterExecute(){
        System.out.println("程序发生异常");
    }

}

f.xml文件

<context:component-scan base-package="com.aspectj.demo5"/>

<aop:aspectj-autoproxy />

5.基于XML的五种通知

只列举一个,其他都类似

<bean id="someService" class="com.aspectj.demo5.SomeServiceImpl"/>
<bean id="myAspect" class="com.aspectj.demo5.MyAspect"/>

<aop:config>
     <aop:pointcut expression="execution(* *..SomeServiceImpl.run(..))" id="afterPointCut"/>

     <aop:aspect ref="myAspect">
        <aop:after method="afterExecute" pointcut-ref="afterPointCut"/>
     aop:aspect>
 aop:config>

你可能感兴趣的:(spring)