1. 程式人生 > >Spring --11.Spring的AOP入門

Spring --11.Spring的AOP入門

1、AOP 概述

AOP概述

AOP為Aspect Oriented Programming的縮寫。意為面向切面程式設計。通過預編譯方式和老實巴交行期動態代理實現程式

功能的統一維護的一種技術。AOP是OOP的延續、AOP:面向切面程式設計。AOP是OOP的擴充套件和延伸,解決OOP開發遇到問題。

AOP作用

在不修改原始碼的情況下、可以實現功能的增強

傳統程式碼是縱向體系程式碼複用、

AOP是橫向抽取機制、基於代理思想、對原來目標物件、建立代理物件、在不修改原物件程式碼情況下、通過對代理物件、

呼叫增強功能的程式碼、從而對原有業務方法進行增強

AOP應用場景

場景一:記錄日誌

場景二:監控方法執行時間

場景三:許可權抑制

場景四:快取優化(第一呼叫查詢資料庫、將查詢結果放入記憶體物件、第二次呼叫、直接從記憶體物件返回、不需要查詢資料庫)

場景五:事務管理(呼叫方法前開啟事務、呼叫方法後提交關閉事務)

AOP原理

Spring中AOP有二種實現方式:

(1)、JDK動態代理 、只能對實現了介面的類產生代理。

(2)、Cglib動態代理、(類似於Javassist第三方代理技術):對沒有實現介面的類產生代理物件。生成子類物件

2、Spring的AOP底層實現

(1)、JDK動態代理

UserDao.java介面

package com.day03.dao;

/**
 * @ Author     :ShaoWei Sun.
 * @ Date       :Created in 21:48 2018/11/11
 */
public interface UserDao {
    public abstract void save();
    public abstract void delete();
    public abstract void update();
    public abstract void select();
}

UserDaoImpl.java實現類

package com.day03.dao.Impl;

import com.day03.dao.UserDao;

/**
 * @ Author     :ShaoWei Sun.
 * @ Date       :Created in 21:48 2018/11/11
 */
public class UserDaoImpl implements UserDao {

    @Override
    public void save() {
        System.out.println("save方法。。。。。。。。。。。");
    }

    @Override
    public void delete() {
        System.out.println("delete方法。。。。。。。。。。。");
    }

    @Override
    public void update() {
        System.out.println("update......................");
    }

    @Override
    public void select() {
        System.out.println("select...........................");
    }
}

代理類:TestProxy.java

package com.day03.test;
import com.day03.dao.UserDao;
import org.junit.Test;
import org.springframework.cglib.proxy.InvocationHandler;
import org.springframework.cglib.proxy.Proxy;
import java.lang.reflect.Method;


/**
 * @ Author     :ShaoWei Sun.
 * @ Date       :Created in 11:47 2018/11/11
 */
public class TestProxy implements InvocationHandler {
    private UserDao userDao;

    public TestProxy(UserDao userDao) {
        this.userDao = userDao;
    }

    @Test
    public UserDao createProxy(){
        UserDao proxy = (UserDao) Proxy.newProxyInstance(userDao.getClass().getClassLoader(), userDao.getClass().getInterfaces(),this);
        return proxy;
    }
    //回撥方法
    @Override
    public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
        if ("save".equals(method.getName())){
            //增強
            System.out.println("增強許可權。。。。。");
            return method.invoke(userDao,objects);
        }
        return method.invoke(userDao,objects);
    }
}

testDemo.java測試類

package com.day03.test;

import com.day03.dao.Impl.UserDaoImpl;
import com.day03.dao.UserDao;
import org.junit.Test;

/**
 * @ Author     :ShaoWei Sun.
 * @ Date       :Created in 21:51 2018/11/11
 */
public class TestDemo {
    @Test
    public void test1() {
        UserDao userDao = new UserDaoImpl();
        UserDao proxy = new TestProxy(userDao).createProxy();
        proxy.save();
        //userDao.save();
        proxy.delete();
        proxy.update();
        proxy.select();
    }
}

(2)、Cglib動態代理

UserDao.java介面

package com.day03.dao;

/**
 * @ Author     :ShaoWei Sun.
 * @ Date       :Created in 21:48 2018/11/11
 */
public interface UserDao {
    public abstract void save();
    public abstract void delete();
    public abstract void update();
    public abstract void select();
}

UserDaoImpl.java實現類

package com.day03.dao.Impl;

import com.day03.dao.UserDao;

/**
 * @ Author     :ShaoWei Sun.
 * @ Date       :Created in 21:48 2018/11/11
 */
public class UserDaoImpl implements UserDao {

    @Override
    public void save() {
        System.out.println("save方法。。。。。。。。。。。");
    }

    @Override
    public void delete() {
        System.out.println("delete方法。。。。。。。。。。。");
    }

    @Override
    public void update() {
        System.out.println("update......................");
    }

    @Override
    public void select() {
        System.out.println("select...........................");
    }
}

CglibProxy.java動態代理

package com.day03.test;

import com.day03.dao.UserDao;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

/**
 * @ Author     :ShaoWei Sun.
 * @ Date       :Created in 14:57 2018/11/12
 */
public class CglibProxy implements MethodInterceptor {
    private UserDao userDao;

    public CglibProxy(UserDao userDao) {
        this.userDao = userDao;
    }

    public UserDao createProxy(){
        //1、建立cglib的核心類物件
        Enhancer enhancer = new Enhancer();
        //2、設定父類
        enhancer.setSuperclass(userDao.getClass());
        //3、設定回撥(類似InvocationHandler物件)
        enhancer.setCallback(this);
        //4、建立代理物件
        UserDao proxy = (UserDao) enhancer.create();
        return proxy;
    }

    @Override
    public Object intercept(Object proxy, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        //判斷方法是否為save;
        if ("save".equals(method.getName())){
            //增強
            System.out.println("許可權核驗。。。。。。。。。。。");

            return methodProxy.invokeSuper(proxy,objects);
        }
        return methodProxy.invokeSuper(proxy,objects);
    }
}

TestDemo.java測試類

package com.day03.test;

import com.day03.dao.Impl.UserDaoImpl;
import com.day03.dao.UserDao;
import org.junit.Test;

/**
 * @ Author     :ShaoWei Sun.
 * @ Date       :Created in 21:51 2018/11/11
 */
public class TestDemo {
    @Test
    public void test1() {
        UserDao userDao = new UserDaoImpl();
        UserDao proxy = new CglibProxy(userDao).createProxy();
        proxy.save();
        //userDao.save();
        proxy.delete();
        proxy.update();
        proxy.select();
    }
}

3、AOP相關術語

Joinpoint (連線點)

連線點是指那些被攔截到的點、在spring中、這些點指的是方法、spring只支援方法型別的連線點

Pointcut(切入點)

指的是我們要對哪些Joinpoint進行攔截

Advice(通知/增強)

通知是指攔截到Joinpoint之後所要做的事情就是通知、通知分為前置通知、後置通知、異常通知、最終通知、環繞通知(切面要完成的功能)

Introduction(引介)

引介是一種特殊的通知、在不修改程式碼的前提下、Introduction可以在執行期為類動態地新增一些方法或Field

Target(目標物件)

代理的目標物件

Weaving(織入)

是指把增強應用到目標物件來建立新的代理物件的過程、spring採用動態代理織入、而Asp

Proxy(代理)

一個類被AOP織入增強後、就產生一個結果代理類

Aspect(切面)

是切入紅開和通知(引介)的結合