1. 程式人生 > 實用技巧 >Spring之AOP

Spring之AOP

Spring之AOP

面向切面程式設計(方面),利用 AOP 可以對業務邏輯的各個部分進行隔離,從而使得業務邏 輯各部分之間的耦合度降低,提高程式的可重用性,同時提高了開發的效率。 通俗描述:不通過修改原始碼方式,在主幹功能裡面新增新功能。

AOP底層原理

JDK動態代理

cglib動態代理

AOP(JDK 動態代理)

建立介面,定義方法

public interface UserDao {
    public int add(int a, int b);

    public String update(String id);

}

建立介面實現類,實現方法

public
class UserDaoImpl implements UserDao { @Override public int add(int a, int b) { return a + b; } @Override public String update(String id) { return id; } }

使用Proxy類建立介面代理物件

public class JDKProxy {
    public static void main(String[] args) {
        Class[] interfaces 
= {UserDao.class}; UserDaoImpl userDao = new UserDaoImpl(); UserDao dao = (UserDao) Proxy.newProxyInstance(JDKProxy.class.getClassLoader(), interfaces, new UserDaoProxy(userDao)); int add = dao.add(1, 2); System.out.println("result=" + add); } } class UserDaoProxy implements
InvocationHandler{ //建立的是誰的物件,把誰傳遞過來 private Object obj; public UserDaoProxy(Object obj) { this.obj = obj; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("方法執行之前---" + method.getName() + "---傳遞的引數:" + Arrays.toString(args)); Object invoke = method.invoke(obj, args); System.out.println("方法執行之後"); return invoke; } }

AOP術語

連線點

類裡面,哪些方法可以被增強,這些方法被稱為連線點。

切入點

實際被真正增強的方法,成為切入點。

通知(增強)

實際增強的邏輯部分稱為通知(增強)

通知有多種型別

前置通知

後置通知

環繞通知

異常通知

最終通知

切面

是動作,把通知應用到切入點的過程。

AOP操作

Spring框架一般都是基於AspectJ實現AOP操作。AspectJ不是Spring組成部分,獨立AOP框架,一般把AspectJ和Spirng框架一起使用,進行AOP操作。

AOP相關依賴

切入點表示式

切入點表示式作用:知道對哪個類裡面的哪個方法進行增強

語法結構: execution([許可權修飾符] [返回型別] [類全路徑] [方法名稱]([引數列表]) )

舉例 1

對cn.xupengzhuang.spring5.dao.UserDao類裡面的 add 進行增強

execution(* cn.xupengzhuang.spring5.dao.UserDao.add(..))

舉例 2

對cn.xupengzhuang.spring5.dao.UserDao類裡面的所有的方法進行增強

execution(* cn.xupengzhuang.spring5.dao.UserDao.* (..))

舉例 3

對 cn.xupengzhuang.spring5.dao.UserDao 包裡面所有類,類裡面所有方法進行增強

execution(* cn.xupengzhuang.spring5.dao.*.* (..))

AOP 操作(AspectJ 註解)

建立被增強類

@Component
public class UserDao {
    public void add(){
        System.out.println("dao add");
    }
}

建立增強類

@Component
@Aspect //生成代理物件
public class UserDaoProxy {

    //相同切入點抽取
    @Pointcut(value = "execution(* cn.xupengzhuang.spring5.aop.dao.UserDao.add(..))")
    public void pointdemo() {
    }


    //前置通知
    @Before(value = "pointdemo")
    public void before() {
        System.out.println("before.........");
    }

    //後置通知(返回通知)
    @AfterReturning(value = "pointdemo")
    public void afterReturning() {
        System.out.println("afterReturning.........");
    }

    //最終通知
    @After(value = "pointdemo")
    public void after() {
        System.out.println("after.........");
    }

    //異常通知
    @AfterThrowing(value = "pointdemo")
    public void afterThrowing() {
        System.out.println("afterThrowing.........");
    }

    //環繞通知
    @Around(value = "pointdemo")
    public void around(ProceedingJoinPoint proceedingJoinPoint) throws
            Throwable {
        System.out.println("環繞之前.........");
        //被增強的方法執行
        proceedingJoinPoint.proceed();
        System.out.println("環繞之後.........");
    }
}

xml配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:util="http://www.springframework.org/schema/util"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/util
        http://www.springframework.org/schema/util/spring-util.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd">

    <!-- 開啟註解掃描 -->
    <context:component-scan base-package="cn.xupengzhuang.spring5.aop"></context:component-scan>

    <!-- 開啟 Aspect 生成代理物件-->
    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>

</beans>

純註解方式

@Configuration
@ComponentScan(basePackages = {"cn.xupengzhuang.spring5"})
@EnableAspectJAutoProxy(proxyTargetClass = true)
public class ConfigAop {
}