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

SpringAOP中的動(dòng)態(tài)代理技術(shù)深入解析

 更新時(shí)間:2024年01月26日 10:24:33   作者:ThinkPet  
這篇文章主要介紹了SpringAOP中的動(dòng)態(tài)代理技術(shù)深入解析,spring默認(rèn)使用JDK動(dòng)態(tài)代理實(shí)現(xiàn)AOP,類如果實(shí)現(xiàn)了接口,spring就會(huì)用JDK動(dòng)態(tài)代理實(shí)現(xiàn)AOP,如果目標(biāo)類沒(méi)有實(shí)現(xiàn)接口,spring則使用Cglib動(dòng)態(tài)代理來(lái)實(shí)現(xiàn)AOP,需要的朋友可以參考下

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

Spring的aop實(shí)現(xiàn)主要應(yīng)用了JDK動(dòng)態(tài)代理和Cglib動(dòng)態(tài)代理 這2種代理。

org.springframework.aop.framework.JdkDynamicAopProxy
org.springframework.aop.framework.CglibAopProxy

spring默認(rèn)使用JDK動(dòng)態(tài)代理實(shí)現(xiàn)AOP,類如果實(shí)現(xiàn)了接口,spring就會(huì)用JDK動(dòng)態(tài)代理實(shí)現(xiàn)AOP. 如果目標(biāo)類沒(méi)有實(shí)現(xiàn)接口,spring則使用Cglib動(dòng)態(tài)代理來(lái)實(shí)現(xiàn)AOP.

  • jdk動(dòng)態(tài)代理的優(yōu)勢(shì):jdk自身支持,減少依賴,可隨jdk平滑升級(jí),代碼實(shí)現(xiàn)簡(jiǎn)單
  • cglib動(dòng)態(tài)代理的優(yōu)勢(shì):無(wú)需實(shí)現(xiàn)接口,達(dá)到無(wú)侵入,只操作我們關(guān)系的類,而不必為其他相關(guān)類增加工作量

spring事務(wù)便是基于spring aop實(shí)現(xiàn)的, spring事務(wù)的一些失效場(chǎng)景,如

1.使用了private方法,導(dǎo)致事務(wù)失效(被動(dòng)態(tài)代理的方法必須是public)

2.使用了final方法,導(dǎo)致事務(wù)失效(如果方法定義為final,JDK動(dòng)態(tài)代理和cglib動(dòng)態(tài)代理無(wú)法重寫(xiě)該方法)

3.同一類內(nèi)部方法調(diào)用:直接使用this對(duì)象調(diào)用方法,無(wú)法生成代理方法,導(dǎo)致事務(wù)失效

測(cè)試使用Cglib動(dòng)態(tài)代理

定義被代理的方法

package cn.demo.cglib;
public class OrderService {
    /**
     * 被動(dòng)態(tài)代理的方法應(yīng)該是public公共的
     * @param orderNo
     */
    public void order(String orderNo){
        System.out.println("order something...");
    }
}

定義cglib動(dòng)態(tài)代理時(shí)觸發(fā)的攔截器

package cn.demo.cglib;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

/**
 * 動(dòng)態(tài)代理類,實(shí)現(xiàn)方法攔截器MethodInterceptor接口
 */
public class LogInterceptor implements MethodInterceptor {


    //cglib動(dòng)態(tài)代理,基于ASM機(jī)制實(shí)現(xiàn),通過(guò)生成目標(biāo)類的子類作為代理類
    //使用cglib中的Enhancer來(lái)生成代理對(duì)象子類,
    public Object getProxyInstance(Class targetClass){
        //1.工具類
        Enhancer enhancer = new Enhancer();
        //2.設(shè)置父類
        enhancer.setSuperclass(targetClass);
        //3.設(shè)置回調(diào)函數(shù)
        enhancer.setCallback(this);
        //4.創(chuàng)建子類(代理對(duì)象)
        return enhancer.create();


    }

    //并實(shí)現(xiàn)MethodInterceptor的intercept方法來(lái)實(shí)現(xiàn)增強(qiáng)功能
    @Override
    public Object intercept(Object o, Method method,
                            Object[] objects,
                            MethodProxy methodProxy) throws Throwable {

        System.out.println("LogInterceptor: Before invoke---");

        Object obj = methodProxy.invokeSuper(o,objects);

        System.out.println("LogInterceptor: After invoke---");

        return obj;
    }
}

使用cglib動(dòng)態(tài)代理出的實(shí)例

package cn.demo.cglib;
public class CglibTest {
    public static void main(String[] args) {
        //Cglib動(dòng)態(tài)代理特點(diǎn)
        //1.需要引入cglib依賴jar (一般spring的核心包已經(jīng)有了cglib依賴)
        //2.被代理的類不需要接口信息,Cglib動(dòng)態(tài)代理可以攔截并包裝被代理類的所有方法
        //3.代理類要實(shí)現(xiàn)MethodInterceptor接口
        //4.代理類使用cglib中的Enhancer來(lái)生成目標(biāo)對(duì)象子類
        //5.目標(biāo)類不能為final,因?yàn)閒inal類不能創(chuàng)建子類
        OrderService orderService = (OrderService)
                new LogInterceptor()
                        .getProxyInstance(OrderService.class);
        orderService.order("123");
    }
}

測(cè)試使用jdk動(dòng)態(tài)代理

定義被代理的方法及其接口

package cn.demo.proxy;

public interface UserService {
    void login(String username, String password);
}

package cn.demo.proxy;
//jdk動(dòng)態(tài)代理的致命缺點(diǎn)就是目標(biāo)類必須實(shí)現(xiàn)某個(gè)接口
public class UserServiceImpl implements UserService{
    @Override
    public void login(String username, String password) {
        System.out.println("User Login Service!");
    }
}

定義jdk動(dòng)態(tài)代理時(shí)觸發(fā)的攔截器

package cn.demo.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
//通過(guò)實(shí)現(xiàn)InvocationHandler接口完成代理邏輯
public class LogHandler implements InvocationHandler {
    /**
     * 被代理的對(duì)象,實(shí)際的方法執(zhí)行者
     */
    Object target;
    public LogHandler(Object target) {
        this.target = target;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //在函數(shù)invoke之前之后,可以進(jìn)行一些自定義操作
        //如 日志、事務(wù)、攔截器、權(quán)限控制等
        System.out.println("Before Login ---");
        Object result = method.invoke(target,args);
        System.out.println("After Login ---");
        return result;
    }
}

使用jdk動(dòng)態(tài)代理出的實(shí)例

package cn.demo.proxy;
import java.lang.reflect.Proxy;
public class JdkProxyTest {
    public static void main(String[] args) {
        //創(chuàng)建被代理的對(duì)象, UserService接口的實(shí)現(xiàn)類
        UserServiceImpl userService = new UserServiceImpl();
        //創(chuàng)建代理對(duì)象,包含3個(gè)參數(shù) ClassLoader 、 目標(biāo)類實(shí)現(xiàn)接口數(shù)組、 事件處理器
        UserService userProxy = (UserService)
                Proxy.newProxyInstance(
                        userService.getClass().getClassLoader(),
                        userService.getClass().getInterfaces(),
                        new LogHandler(userService)
                );
         //用代理出的實(shí)例調(diào)用login方法
        userProxy.login("admin", "123456");
}

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

相關(guān)文章

最新評(píng)論