欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Spring?AOP原理及動(dòng)態(tài)代理

 更新時(shí)間:2022年09月21日 09:41:57   作者:IT小郭.  
這篇文章主要介紹了Spring?AOP原理及動(dòng)態(tài)代理,文章通過圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下

一、什么是代理?

指為一個(gè)目標(biāo)對(duì)象提供一個(gè)代理對(duì)象, 并由代理對(duì)象控制對(duì)目標(biāo)對(duì)象的引用. 使用代理對(duì)象, 是為了在不修改目標(biāo)對(duì)象的基礎(chǔ)上,增強(qiáng)目標(biāo)對(duì)象的業(yè)務(wù)邏輯.

1、靜態(tài)代理

靜態(tài)代理的特點(diǎn)是, 為每一個(gè)業(yè)務(wù)增強(qiáng)都提供一個(gè)代理類, 由代理類來創(chuàng)建代理對(duì)象. 下面我們通過靜態(tài)代理來實(shí)現(xiàn)對(duì)轉(zhuǎn)賬業(yè)務(wù)進(jìn)行身份驗(yàn)證.

(1) 轉(zhuǎn)賬業(yè)務(wù)

public interface IAccountService {
    //主業(yè)務(wù)邏輯: 轉(zhuǎn)賬
    void transfer();
}

public class AccountServiceImpl implements IAccountService {
    @Override
    public void transfer() {
        System.out.println("調(diào)用dao層,完成轉(zhuǎn)賬主業(yè)務(wù).");
    }
}

(2) 代理類

public class AccountProxy implements IAccountService {
    //目標(biāo)對(duì)象
    private IAccountService target;
    public AccountProxy(IAccountService target) {
        this.target = target;
    }
    /**
     * 代理方法,實(shí)現(xiàn)對(duì)目標(biāo)方法的功能增強(qiáng)
     */
    @Override
    public void transfer() {
        before();
        target.transfer();
    }
    /**
     * 前置增強(qiáng)
     */
    private void before() {
        System.out.println("對(duì)轉(zhuǎn)賬人身份進(jìn)行驗(yàn)證.");
    }
}

(3) 測(cè)試

public class Client {
    public static void main(String[] args) {
        //創(chuàng)建目標(biāo)對(duì)象
        IAccountService target = new AccountServiceImpl();
        //創(chuàng)建代理對(duì)象
        AccountProxy proxy = new AccountProxy(target);
        proxy.transfer();
    }
}

結(jié)果: 對(duì)轉(zhuǎn)賬人身份進(jìn)行驗(yàn)證.調(diào)用dao層,完成轉(zhuǎn)賬主業(yè)務(wù).

2、動(dòng)態(tài)代理

靜態(tài)代理會(huì)為每一個(gè)業(yè)務(wù)增強(qiáng)都提供一個(gè)代理類, 由代理類來創(chuàng)建代理對(duì)象, 而動(dòng)態(tài)代理并不存在代理類, 代理對(duì)象直接由代理生成工具動(dòng)態(tài)生成.

2.1、JDK動(dòng)態(tài)代理

JDK動(dòng)態(tài)代理是使用 java.lang.reflect 包下的代理類來實(shí)現(xiàn). JDK動(dòng)態(tài)代理動(dòng)態(tài)代理必須要有接口.

(1) 轉(zhuǎn)賬業(yè)務(wù)

public interface IAccountService {
    //主業(yè)務(wù)邏輯: 轉(zhuǎn)賬
    void transfer();
}
public class AccountServiceImpl implements IAccountService {
    @Override
    public void transfer() {
        System.out.println("調(diào)用dao層,完成轉(zhuǎn)賬主業(yè)務(wù).");
    }
}

(2) 增強(qiáng)

因?yàn)檫@里沒有配置切入點(diǎn), 稱為切面會(huì)有點(diǎn)奇怪, 所以稱為增強(qiáng).

public class AccountAdvice implements InvocationHandler {
    //目標(biāo)對(duì)象
    private IAccountService target;

    public AccountAdvice(IAccountService target) {
        this.target = target;
    }

    /**
     * 代理方法, 每次調(diào)用目標(biāo)方法時(shí)都會(huì)進(jìn)到這里
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        before();
        return method.invoke(target, args);
    }

    /**
     * 前置增強(qiáng)
     */
    private void before() {
        System.out.println("對(duì)轉(zhuǎn)賬人身份進(jìn)行驗(yàn)證.");
    }
}

(3) 測(cè)試

public class Client {
    public static void main(String[] args) {
        //創(chuàng)建目標(biāo)對(duì)象
        IAccountService target = new AccountServiceImpl();
        //創(chuàng)建代理對(duì)象
        IAccountService proxy = (IAccountService) Proxy.newProxyInstance(target.getClass().getClassLoader(),
                target.getClass().getInterfaces(),
                new AccountAdvice(target)
        );
        proxy.transfer();
    }
}

結(jié)果: 對(duì)轉(zhuǎn)賬人身份進(jìn)行驗(yàn)證.調(diào)用dao層,完成轉(zhuǎn)賬主業(yè)務(wù).

2.2、 CGLIB動(dòng)態(tài)代理

JDK動(dòng)態(tài)代理必須要有接口, 但如果要代理一個(gè)沒有接口的類該怎么辦呢? 這時(shí)我們可以使用CGLIB動(dòng)態(tài)代理. CGLIB動(dòng)態(tài)代理的原理是生成目標(biāo)類的子類, 這個(gè)子類對(duì)象就是代理對(duì)象, 代理對(duì)象是被增強(qiáng)過的.

注意: 不管有沒有接口都可以使用CGLIB動(dòng)態(tài)代理, 而不是只有在無接口的情況下才能使用

(1) 轉(zhuǎn)賬業(yè)務(wù)

public class AccountService {
    public void transfer() {
        System.out.println("調(diào)用dao層,完成轉(zhuǎn)賬主業(yè)務(wù).");
    }
}

(2) 增強(qiáng)

因?yàn)檫@里沒有配置切入點(diǎn), 稱為切面會(huì)有點(diǎn)奇怪, 所以稱為增強(qiáng).

public class AccountAdvice implements MethodInterceptor {
    /**
     * 代理方法, 每次調(diào)用目標(biāo)方法時(shí)都會(huì)進(jìn)到這里
     */
    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        before();
        return methodProxy.invokeSuper(obj, args);
        //        return method.invoke(obj, args);  這種也行
    }

    /**
     * 前置增強(qiáng)
     */
    private void before() {
        System.out.println("對(duì)轉(zhuǎn)賬人身份進(jìn)行驗(yàn)證.");
    }
}

(3) 測(cè)試

public class Client {
    public static void main(String[] args) {
        //創(chuàng)建目標(biāo)對(duì)象
        AccountService target = new AccountService();
        //
        //創(chuàng)建代理對(duì)象
        AccountService proxy = (AccountService) Enhancer.create(target.getClass(),
                new AccountAdvice());
        proxy.transfer();
    }
}

結(jié)果: 對(duì)轉(zhuǎn)賬人身份進(jìn)行驗(yàn)證.調(diào)用dao層,完成轉(zhuǎn)賬主業(yè)務(wù).

二、模擬Spring AOP場(chǎng)景

了解了動(dòng)態(tài)代理后, 我們就可以自己來實(shí)現(xiàn)Spring AOP功能了, 所以下面我們來模擬下Spring AOP場(chǎng)景.

(1) 轉(zhuǎn)賬業(yè)務(wù)

public interface IAccountService {
    //主業(yè)務(wù)邏輯: 轉(zhuǎn)賬
    void transfer();
}
public class AccountServiceImpl implements IAccountService {
    @Override
    public void transfer() {
        System.out.println("調(diào)用dao層,完成轉(zhuǎn)賬主業(yè)務(wù).");
    }
}

(2) 切面抽象類

定義一個(gè)切面抽象類, 該類使用了模板方法的設(shè)計(jì)模式, 為開始, 結(jié)束, 異常, 前置增強(qiáng), 后置增強(qiáng)提供了默認(rèn)實(shí)現(xiàn), 當(dāng)我們定義切面類時(shí)只需要按需重寫它們就行. isIntercept() 方法用來判斷切入點(diǎn)是否正確, 切面類需要重寫這個(gè)方法.

public abstract class BaseAspect implements MethodInterceptor {
    private static final Logger logger = LoggerFactory.getLogger(BaseAspect.class);

    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        Object result = null;

        begin();
        try {
            if (isIntercept(method, args)) {
                before();
                result = methodProxy.invokeSuper(obj, args);
                after();
            } else {
                result = methodProxy.invokeSuper(obj,args);
            }
        } catch (Exception e) {
            logger.error("proxy failure", e);
            error(e);
            throw e;
        } finally {
            end();
        }
        return result;
    }
    /**
     * 開始增強(qiáng)
     */
    public void begin() {
    }
    /**
     * 切入點(diǎn)判斷
     */
    public boolean isIntercept(Method method, Object[] args) throws Throwable {
        return true;
    }
    /**
     * 前置增強(qiáng)
     */
    public void before() throws Throwable {
    }

    /**
     * 后置增強(qiáng)
     */
    public void after() throws Throwable {
    }

    /**
     * 異常增強(qiáng)
     */
    public void error(Throwable e) {
    }

    /**
     * 最終增強(qiáng)
     */
    public void end() {
    }
}

(3) 切面類

創(chuàng)建一個(gè)切面類, 類中配置切入點(diǎn)和增強(qiáng).

public class AccountAspect extends BaseAspect {
    /**
     * 切入點(diǎn)
     */
    public boolean isIntercept(Method method, Object[] args) throws Throwable {
        return method.getName().equals("transfer");
    }

    /**
     * 前置增強(qiáng)
     */
    public void before() throws Throwable {
        System.out.println("對(duì)轉(zhuǎn)賬人身份進(jìn)行驗(yàn)證.");
    }
}

(4) 代理工廠類

定義一個(gè)工廠類來創(chuàng)建代理, 其實(shí)不創(chuàng)建這個(gè)類也行, 但為了模仿Spring還是創(chuàng)建了. @SuppressWarnings是為了抑制警告, 就是編譯器上面的黃線.

public class ProxyFactory {

    @SuppressWarnings("unchecked")
    public static <T> T createProxy(final Class<?> targetClass, final MethodInterceptor methodInterceptor) {
        return (T) Enhancer.create(targetClass,methodInterceptor);
    }
}

(5) 測(cè)試

public class Client {
    public static void main(String[] args) {
        //創(chuàng)建目標(biāo)對(duì)象
        IAccountService target = new AccountServiceImpl();
        //切面
        BaseAspect accountAspect = new AccountAspect();
        //創(chuàng)建代理對(duì)象
        IAccountService proxy = (IAccountService) ProxyFactory.createProxy(target.getClass(), accountAspect);
        proxy.transfer();
    }
}

結(jié)果:對(duì)轉(zhuǎn)賬人身份進(jìn)行驗(yàn)證.調(diào)用dao層,完成轉(zhuǎn)賬主業(yè)務(wù).

到此這篇關(guān)于Spring AOP原理及動(dòng)態(tài)代理的文章就介紹到這了,更多相關(guān)Spring AOP 內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論