国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專(zhuān)欄INFORMATION COLUMN

【干貨】JDK動(dòng)態(tài)代理的實(shí)現(xiàn)原理以及如何手寫(xiě)一個(gè)JDK動(dòng)態(tài)代理

forsigner / 3495人閱讀

摘要:代理模式從類(lèi)型上來(lái)說(shuō),可以分為靜態(tài)代理和動(dòng)態(tài)代理兩種類(lèi)型。然而今天的重點(diǎn)是我們都知道牛逼轟轟的的實(shí)現(xiàn)的一種方式是使用的動(dòng)態(tài)代理另一種是,大部分人也會(huì)用的動(dòng)態(tài)代理,不過(guò)沒(méi)有研究過(guò)的動(dòng)態(tài)代理到底是怎么實(shí)現(xiàn)的。

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

代理模式是設(shè)計(jì)模式中非常重要的一種類(lèi)型,而設(shè)計(jì)模式又是編程中非常重要的知識(shí)點(diǎn),特別是在業(yè)務(wù)系統(tǒng)的重構(gòu)中,更是有舉足輕重的地位。代理模式從類(lèi)型上來(lái)說(shuō),可以分為靜態(tài)代理和動(dòng)態(tài)代理兩種類(lèi)型。

在解釋動(dòng)態(tài)代理之前我們先理解一下靜態(tài)代理:

首先你要明白靜態(tài)代理的作用

我們有一個(gè)字體提供類(lèi),有多種實(shí)現(xiàn)(從磁盤(pán),從網(wǎng)絡(luò),從系統(tǒng))

public interface FontProvider {
    Font getFont(String name);
}

public abstract class ProviderFactory {
    public static FontProvider getFontProvider() {
        return new FontProviderFromDisk();
    }
}

public class Main() {
    public static void main(String[] args) {
        FontProvider fontProvider = ProviderFactory.getFontProvider();
        Font font = fontProvider.getFont("微軟雅黑");
        ......
    }
}

現(xiàn)在我們希望給他加上一個(gè)緩存功能,我們可以用靜態(tài)代理來(lái)完成

public class CachedFontProvider implements FontProvider {
    private FontProvider fontProvider;
    private Map cached;

    public CachedFontProvider(FontProvider fontProvider) {
        this.fontProvider = fontProvider;
    }

    public Font getFont(String name) {
        Font font = cached.get(name);
        if (font == null) {
            font = fontProvider.getFont(name);
            cached.put(name, font);
        }
        return font;
    }
}


/* 對(duì)工廠類(lèi)進(jìn)行相應(yīng)修改,代碼使用處不必進(jìn)行任何修改。
   這也是面向接口編程以及工廠模式的一個(gè)好處 */
public abstract class ProviderFactory {
    public static FontProvider getFontProvider() {
        return new CachedFontProvider(new FontProviderFromDisk());
    }
}

當(dāng)然,我們直接修改FontProviderFromDisk類(lèi)也可以實(shí)現(xiàn)目的,但是我們還有FontProviderFromNet, FontProviderFromSystem等多種實(shí)現(xiàn)類(lèi),一一修改太過(guò)繁瑣且易出錯(cuò)。況且將來(lái)還可能添加日志,權(quán)限檢查,異常處理等功能顯然用代理類(lèi)更好一點(diǎn)。

然而今天的重點(diǎn)是:我們都知道牛逼轟轟的Spring AOP的實(shí)現(xiàn)的一種方式是使用JDK的動(dòng)態(tài)代理(另一種是cglib),大部分人也會(huì)用jdk的動(dòng)態(tài)代理,不過(guò)沒(méi)有研究過(guò)jdk的動(dòng)態(tài)代理到底是怎么實(shí)現(xiàn)的。今天就來(lái)揭開(kāi)他的神秘面紗;

1. 原理源碼剖析 首先我們先來(lái)講一下JDK動(dòng)態(tài)代理的實(shí)現(xiàn)原理

1.拿到被代理對(duì)象的引用,然后獲取他的接口
2.JDK代理重新生成一個(gè)類(lèi),同時(shí)實(shí)現(xiàn)我們給的代理對(duì)象所實(shí)現(xiàn)的接口
3.把被代理對(duì)象的引用拿到了
4.重新動(dòng)態(tài)生成一個(gè)class字節(jié)碼
5.然后編譯

然后先實(shí)現(xiàn)一個(gè)動(dòng)態(tài)代理

代碼很簡(jiǎn)單了,就是實(shí)現(xiàn)
java.lang.reflect.InvocationHandler接口,并使用
java.lang.reflect.Proxy.newProxyInstance()方法生成代理對(duì)象

/**
 * @author mark
 * @date 2018/3/30
 */
public class JdkInvocationHandler implements InvocationHandler {

    private ProductService target;

    public Object getInstance(ProductService target){
        this.target = target;
        Class clazz = this.target.getClass();
        // 參數(shù)1:被代理類(lèi)的類(lèi)加載器 參數(shù)2:被代理類(lèi)的接口 參數(shù)3
        return Proxy.newProxyInstance(clazz.getClassLoader(),
                clazz.getInterfaces(),
                this);
    }

    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        String currentDate  = simpleDateFormat.format(new Date());
        System.out.println("日期【"+currentDate + "】添加了一款產(chǎn)品");

        return method.invoke(this.target,args);
    }
}

被代理接口和實(shí)現(xiàn)

/**
 * 模仿產(chǎn)品Service
 * @author mark
 * @date 2018-03-30
 */
public interface ProductService {
    /**
     * 添加產(chǎn)品
     * @param productName
     */
    void addProduct(String productName);
}

/**
 * @author mark
 * @date 2018/3/30
 */
public class ProductServiceImpl implements ProductService{
    public void addProduct(String productName) {
        System.out.println("正在添加"+productName);
    }
}

測(cè)試類(lèi)

public class Test {
    public static void main(String[] args) throws Exception {
        ProductService productService = new ProductServiceImpl();
        ProductService proxy = (ProductService) new JdkInvocationHandler().getInstance(productService);
        proxy.addProduct("iphone");

        // 這里我們將jdk生成的代理類(lèi)輸出了出來(lái),方便后面分析使用
        byte[] bytes = ProxyGenerator.generateProxyClass("$Proxy0",new Class[]{productService.getClass()});

        FileOutputStream os = new FileOutputStream("Proxy0.class");
        os.write(bytes);
        os.close();
    }
}

結(jié)果輸出

日期【2018-03-30】添加了一款產(chǎn)品
正在添加iphone

Process finished with exit code 0

上面我們實(shí)現(xiàn)動(dòng)態(tài)動(dòng)態(tài)代理的時(shí)候輸出了代理類(lèi)的字節(jié)碼文件,現(xiàn)在來(lái)看一下字節(jié)碼文件反編譯過(guò)后的內(nèi)容

import com.gwf.jdkproxy.ProductServiceImpl;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;

// 繼承了Proxy類(lèi)
public final class $Proxy0 extends Proxy implements ProductServiceImpl {
    private static Method m1;
    private static Method m8;
    private static Method m2;
    private static Method m3;
    private static Method m5;
    private static Method m4;
    private static Method m7;
    private static Method m9;
    private static Method m0;
    private static Method m6;

    public $Proxy0(InvocationHandler var1) throws  {
        super(var1);
    }

....
....

/**
* 這里是代理類(lèi)實(shí)現(xiàn)的被代理對(duì)象的接口的相同方法
*/
    public final void addProduct(String var1) throws  {
        try {
            // super.h 對(duì)應(yīng)的是父類(lèi)的h變量,他就是Proxy.nexInstance方法中的InvocationHandler參數(shù)
           // 所以這里實(shí)際上就是使用了我們自己寫(xiě)的InvocationHandler實(shí)現(xiàn)類(lèi)的invoke方法
            super.h.invoke(this, m3, new Object[]{var1});
        } catch (RuntimeException | Error var3) {
            throw var3;
        } catch (Throwable var4) {
            throw new UndeclaredThrowableException(var4);
        }
    }

   

    public final Class getClass() throws  {
        try {
            return (Class)super.h.invoke(this, m7, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

....
....
// 在靜態(tài)構(gòu)造塊中,代理類(lèi)通過(guò)反射獲取了被代理類(lèi)的詳細(xì)信息,比如各種方法
    static {
        try {
            m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
            m8 = Class.forName("com.gwf.jdkproxy.ProductServiceImpl").getMethod("notify");
            m2 = Class.forName("java.lang.Object").getMethod("toString");
            m3 = Class.forName("com.gwf.jdkproxy.ProductServiceImpl").getMethod("addProduct", Class.forName("java.lang.String"));
            m5 = Class.forName("com.gwf.jdkproxy.ProductServiceImpl").getMethod("wait", Long.TYPE);
            m4 = Class.forName("com.gwf.jdkproxy.ProductServiceImpl").getMethod("wait", Long.TYPE, Integer.TYPE);
            m7 = Class.forName("com.gwf.jdkproxy.ProductServiceImpl").getMethod("getClass");
            m9 = Class.forName("com.gwf.jdkproxy.ProductServiceImpl").getMethod("notifyAll");
            m0 = Class.forName("java.lang.Object").getMethod("hashCode");
            m6 = Class.forName("com.gwf.jdkproxy.ProductServiceImpl").getMethod("wait");
        } catch (NoSuchMethodException var2) {
            throw new NoSuchMethodError(var2.getMessage());
        } catch (ClassNotFoundException var3) {
            throw new NoClassDefFoundError(var3.getMessage());
        }
    }
}

補(bǔ)充一下上面代母注釋中的super.h

protected InvocationHandler h;

protected Proxy(InvocationHandler h) {
        Objects.requireNonNull(h);
        this.h = h;
    }

// 這個(gè)方法是Proxy的newProxyInstance方法,主要就是生成了上面的動(dòng)態(tài)字節(jié)碼文件
public static Object newProxyInstance(ClassLoader loader,
                                          Class[] interfaces,
                                          InvocationHandler h)
        throws IllegalArgumentException
    {
        Objects.requireNonNull(h);

        final Class[] intfs = interfaces.clone();
        final SecurityManager sm = System.getSecurityManager();
        if (sm != null) {
            checkProxyAccess(Reflection.getCallerClass(), loader, intfs);
        }

        /*
         * Look up or generate the designated proxy class.
         */
        Class cl = getProxyClass0(loader, intfs);

        /*
         * Invoke its constructor with the designated invocation handler.
         */
        try {
            if (sm != null) {
                checkNewProxyPermission(Reflection.getCallerClass(), cl);
            }

            final Constructor cons = cl.getConstructor(constructorParams);
       
            final InvocationHandler ih = h;
            if (!Modifier.isPublic(cl.getModifiers())) {
                AccessController.doPrivileged(new PrivilegedAction() {
                    public Void run() {
                        cons.setAccessible(true);
                        return null;
                    }
                });
            }
// 重點(diǎn)看這里,將我們傳來(lái)的InvocationHandler參數(shù)穿給了構(gòu)造函數(shù)
            return cons.newInstance(new Object[]{h});
        } catch (IllegalAccessException|InstantiationException e) {
            throw new InternalError(e.toString(), e);
        } catch (InvocationTargetException e) {
            Throwable t = e.getCause();
            if (t instanceof RuntimeException) {
                throw (RuntimeException) t;
            } else {
                throw new InternalError(t.toString(), t);
            }
        } catch (NoSuchMethodException e) {
            throw new InternalError(e.toString(), e);
        }
    }
以上就是jdk動(dòng)態(tài)代理的內(nèi)部實(shí)現(xiàn)過(guò)程,最后再次將上面的原理聲明一遍,強(qiáng)化記憶

1.拿到被代理對(duì)象的引用,然后獲取他的接口 (Proxy.getInstance方法)
2.JDK代理重新生成一個(gè)類(lèi),同時(shí)實(shí)現(xiàn)我們給的代理對(duì)象所實(shí)現(xiàn)的接口 (上面的反編譯文件中實(shí)現(xiàn)了同樣的接口)
3.把被代理對(duì)象的引用拿到了(上面被代理對(duì)象中在靜態(tài)代碼塊中通過(guò)反射獲取到的信息,以及我們實(shí)現(xiàn)的JdkInvocationHandler中的target)
4.重新動(dòng)態(tài)生成一個(gè)class字節(jié)碼
5.然后編譯

2.自己手寫(xiě)一個(gè)動(dòng)態(tài)代理

(聲明:本代碼只用作實(shí)例,很多細(xì)節(jié)沒(méi)有考慮進(jìn)去,比如,多接口的代理類(lèi),Object類(lèi)的其他默認(rèn)方法的代理,為確保原汁原味,一些模板引擎和commons工具類(lèi)也沒(méi)有使用;覺(jué)得不足的老鐵們可以隨意完善,記得評(píng)論區(qū)留言完善方法哦)

我們使用jdk代理的類(lèi)名和方法名定義,已經(jīng)執(zhí)行思路,但是所有的實(shí)現(xiàn)都自己來(lái)寫(xiě);

首先先定義出類(lèi)結(jié)構(gòu)

/**
 * 自定義類(lèi)加載器
 * @author gaowenfeng
 * @date 2018/3/30
 */
public class MyClassLoader extends ClassLoader {

    /**
     * 通過(guò)類(lèi)名稱加載類(lèi)字節(jié)碼文件到JVM中
     * @param name 類(lèi)名
     * @return 類(lèi)的Class獨(dú)享
     * @throws ClassNotFoundException
     */
    @Override
    protected Class findClass(String name) throws ClassNotFoundException {
        return super.findClass(name);
    }
}
/**
 * @desc 自己實(shí)現(xiàn)的代理類(lèi),用來(lái)生成字節(jié)碼文件,并動(dòng)態(tài)加載到JVM中
 * @author gaowenfeng
 * @date 2018/3/30
 */
public class MyProxy {
    /**
     * 生成代理對(duì)象
     * @param loader 類(lèi)加載器,用于加載被代理類(lèi)的類(lèi)文件
     * @param interfaces 被代理類(lèi)的接口
     * @param h 自定義的InvocationHandler接口,用于具體代理方法的執(zhí)行
     * @return 返回被代理后的代理對(duì)象
     * @throws IllegalArgumentException
     */
    public static Object newProxyInstance(MyClassLoader loader,
                                          Class[] interfaces,
                                          MyInvocationHandler h)
            throws IllegalArgumentException{
        /**
         * 1.生成代理類(lèi)的源代碼
         * 2.將生成的源代碼輸出到磁盤(pán),保存為.java文件
         * 3.編譯源代碼,并生成.java文件
         * 4.將class文件中的內(nèi)容,動(dòng)態(tài)加載到JVM中
         * 5.返回被代理后的代理對(duì)象
         */

        return null;

    }
}
/**
 * 自定義類(lèi)加載器
 * @author gaowenfeng
 * @date 2018/3/30
 */
public class MyClassLoader extends ClassLoader {

    /**
     * 通過(guò)類(lèi)名稱加載類(lèi)字節(jié)碼文件到JVM中
     * @param name 類(lèi)名
     * @return 類(lèi)的Class獨(dú)享
     * @throws ClassNotFoundException
     */
    @Override
    protected Class findClass(String name) throws ClassNotFoundException {
        return super.findClass(name);
    }
}
/**
 * @author gaowenfeng
 * @date 2018/3/30
 */
public class CustomInvocationHandler implements MyInvocationHandler {
    private ProductService target;

    public Object getInstance(ProductService target){
        this.target = target;
        Class clazz = this.target.getClass();
        // 參數(shù)1:被代理類(lèi)的類(lèi)加載器 參數(shù)2:被代理類(lèi)的接口 參數(shù)3
        // 這里的MyClassLoader先用new的方式保證編譯不報(bào)錯(cuò),后面會(huì)修改
        return MyProxy.newProxyInstance(new MyClassLoader(),
                clazz.getInterfaces(),
                this);
    }
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        String currentDate  = simpleDateFormat.format(new Date());
        System.out.println("日期【"+currentDate + "】添加了一款產(chǎn)品");

        return method.invoke(this.target,args);
    }
}
接下來(lái)我們來(lái)按照步驟一步一步的完善我們的類(lèi)

生成代理類(lèi)的源文件

     * 生成代理類(lèi)的源代碼
     * @return
     */
    private static String genSesource(Class interfaces){
        StringBuilder src = new StringBuilder();
        src.append("package com.gwf.custom;").append(ln)
                .append("import java.lang.reflect.Method;").append(ln)
                .append("public class $Proxy0 implements ").append(interfaces.getName()).append("{").append(ln)
                .append("private MyInvocationHandler h;").append(ln)
                .append("public $Proxy0(MyInvocationHandler h){").append(ln)
                .append("this.h=h;").append(ln)
                .append("}").append(ln);

        for(Method method:interfaces.getMethods()){
            src.append("public ").append(method.getReturnType()).append(" ").append(method.getName()).append("() {").append(ln)
                    .append("try {").append(ln)
                    .append("Method m = ").append(interfaces.getName()).append(".class.getMethod("").append(method.getName()).append("");").append(ln)
                    .append("this.h.invoke(this, m, new Object[]{});").append(ln)
                    .append("}catch (Throwable e){").append(ln)
                    .append("e.printStackTrace();").append(ln)
                    .append("}").append(ln)
                    .append("}").append(ln);
        }
        src.append("}");

        return src.toString();

    }

2.將源文件保存到本地

// 1.生成代理類(lèi)的源代碼
            String src = genSesource(interfaces);
            // 2.將生成的源代碼輸出到磁盤(pán),保存為.java文件
            String path = MyProxy.class.getResource("").getPath();
            File file = new File(path+"$Proxy0.java");

            FileWriter fw = new FileWriter(file);
            fw.write(src);
            fw.close();

3.編譯源代碼,并生成.java文件

// 3.編譯源代碼,并生成.java文件
            // 獲取java編譯器
            JavaCompiler javaCompiler = ToolProvider.getSystemJavaCompiler();
            // 標(biāo)注java文件管理器,用來(lái)獲取java字節(jié)碼文件
            StandardJavaFileManager manager = javaCompiler.getStandardFileManager(null,null,null);
            Iterable iterable = manager.getJavaFileObjects(file);

            // 創(chuàng)建task,通過(guò)java字節(jié)碼文件將類(lèi)信息加載到JVM中
            JavaCompiler.CompilationTask task = javaCompiler.getTask(null,manager,null,null,null,iterable);
            // 開(kāi)始執(zhí)行task
            task.call();
            // 關(guān)閉管理器
            manager.close();

4.將class文件中的內(nèi)容,動(dòng)態(tài)加載到JVM中

public class MyClassLoader extends ClassLoader {

    private String baseDir;

    public MyClassLoader(){
        this.baseDir = MyClassLoader.class.getResource("").getPath();
    }

    /**
     * 通過(guò)類(lèi)名稱加載類(lèi)字節(jié)碼文件到JVM中
     * @param name 類(lèi)名
     * @return 類(lèi)的Class獨(dú)享
     * @throws ClassNotFoundException
     */
    @Override
    protected Class findClass(String name) throws ClassNotFoundException {
        // 獲取類(lèi)名
        String className = MyClassLoader.class.getPackage().getName()+"."+name;
        if(null == baseDir) {
            throw new ClassNotFoundException();
        }

        // 獲取類(lèi)文件
        File file = new File(baseDir,name+".class");
        if(!file.exists()){
            throw new ClassNotFoundException();
        }

        // 將類(lèi)文件轉(zhuǎn)換為字節(jié)數(shù)組
        try(
        FileInputStream in = new FileInputStream(file);
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        ){
            byte[] buffer = new byte[1024];
            int len;
            while ((len = in.read(buffer))!=-1){
                out.write(buffer,0,len);
            }

            // 調(diào)用父類(lèi)方法生成class實(shí)例
            return defineClass(className,out.toByteArray(),0,out.size());
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

5.返回被代理后的代理對(duì)象

Constructor c = proxyClass.getConstructor(MyInvocationHandler.class);
            return c.newInstance(h);

最后看一下總體的MyProxy類(lèi) 的 newProxyInstance方法

public static Object newProxyInstance(MyClassLoader loader,
                                          Class interfaces,
                                          MyInvocationHandler h)
            throws IllegalArgumentException{
        /**
         * 1.生成代理類(lèi)的源代碼
         * 2.將生成的源代碼輸出到磁盤(pán),保存為.java文件
         * 3.編譯源代碼,并生成.java文件
         * 4.將class文件中的內(nèi)容,動(dòng)態(tài)加載到JVM中
         * 5.返回被代理后的代理對(duì)象
         */
        try {
            // 1.生成代理類(lèi)的源代碼
            String src = genSesource(interfaces);
            // 2.將生成的源代碼輸出到磁盤(pán),保存為.java文件
            String path = MyProxy.class.getResource("").getPath();
            File file = new File(path+"$Proxy0.java");

            FileWriter fw = new FileWriter(file);
            fw.write(src);
            fw.close();

            // 3.編譯源代碼,并生成.java文件
            JavaCompiler javaCompiler = ToolProvider.getSystemJavaCompiler();
            StandardJavaFileManager manager = javaCompiler.getStandardFileManager(null,null,null);
            Iterable iterable = manager.getJavaFileObjects(file);

            JavaCompiler.CompilationTask task = javaCompiler.getTask(null,manager,null,null,null,iterable);
            task.call();
            manager.close();

            // 4.將class文件中的內(nèi)容,動(dòng)態(tài)加載到JVM中
            Class proxyClass = loader.findClass("$Proxy0");

            // 5.返回被代理后的代理對(duì)象
            Constructor c = proxyClass.getConstructor(MyInvocationHandler.class);
            return c.newInstance(h);
        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;

    }
激動(dòng)人心的時(shí)刻:測(cè)試運(yùn)行
public class CustomClient {
    public static void main(String[] args){
        ProductService productService = new ProductServiceImpl();
        ProductService proxy = (ProductService) new CustomInvocationHandler().getInstance(productService);
        proxy.addProduct();
    }
}

運(yùn)行結(jié)果

日期【2018-03-30】添加了一款產(chǎn)品
正在添加iphone

Process finished with exit code 0

總結(jié):以上通過(guò)理解jdk動(dòng)態(tài)代理的原理,自己手寫(xiě)了一個(gè)動(dòng)態(tài)代理,里面涉及到的重點(diǎn)主要是代理類(lèi)字節(jié)碼的生成(這里采用通過(guò)反射強(qiáng)行生成源文件并編譯的方法,其實(shí)應(yīng)該可以直接生成字節(jié)碼文件的,有興趣的同學(xué)可以嘗試)和將生成的類(lèi)動(dòng)態(tài)加載到JVM中(本次試驗(yàn)由于測(cè)試,比較簡(jiǎn)單,直接將類(lèi)名硬編碼到了系統(tǒng)里,正常應(yīng)該是自動(dòng)加載),雖然還不完善,但是對(duì)于理解原理應(yīng)該是有很多幫助了,歡迎同學(xué)們?cè)u(píng)論區(qū)留言評(píng)論給出更好的建議

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/71753.html

相關(guān)文章

  • 【好好面試】學(xué)完Aop,連動(dòng)態(tài)代理原理都不懂?

    摘要:總結(jié)動(dòng)態(tài)代理的相關(guān)原理已經(jīng)講解完畢,接下來(lái)讓我們回答以下幾個(gè)思考題。 【干貨點(diǎn)】 此處是【好好面試】系列文的第12篇文章。文章目標(biāo)主要是通過(guò)原理剖析的方式解答Aop動(dòng)態(tài)代理的面試熱點(diǎn)問(wèn)題,通過(guò)一步步提出問(wèn)題和了解原理的方式,我們可以記得更深更牢,進(jìn)而解決被面試官卡住喉嚨的情況。問(wèn)題如下 SpringBoot默認(rèn)代理類(lèi)型是什么 為什么不用靜態(tài)代理 JDK動(dòng)態(tài)代理原理 CGLIB動(dòng)態(tài)代理...

    Keven 評(píng)論0 收藏0
  • 從源碼入手,一文帶你讀懂Spring AOP面向切面編程

    摘要:,,面向切面編程。,切點(diǎn),切面匹配連接點(diǎn)的點(diǎn),一般與切點(diǎn)表達(dá)式相關(guān),就是切面如何切點(diǎn)。例子中,注解就是切點(diǎn)表達(dá)式,匹配對(duì)應(yīng)的連接點(diǎn),通知,指在切面的某個(gè)特定的連接點(diǎn)上執(zhí)行的動(dòng)作。,織入,將作用在的過(guò)程。因?yàn)樵创a都是英文寫(xiě)的。 之前《零基礎(chǔ)帶你看Spring源碼——IOC控制反轉(zhuǎn)》詳細(xì)講了Spring容器的初始化和加載的原理,后面《你真的完全了解Java動(dòng)態(tài)代理嗎?看這篇就夠了》介紹了下...

    wawor4827 評(píng)論0 收藏0
  • 【好好面試】手把手調(diào)試,教你分析Spring-Aop

    摘要:思考之所以會(huì)選擇為切入點(diǎn),是因?yàn)橥ㄟ^(guò)命名可以看出這是用來(lái)構(gòu)建代理強(qiáng)化對(duì)象的地方,并且由于是先將目標(biāo)類(lèi)加載到內(nèi)存中,之后通過(guò)修改字節(jié)碼生成目標(biāo)類(lèi)的子類(lèi),因此我猜測(cè)強(qiáng)化是在目標(biāo)類(lèi)實(shí)例化后觸發(fā)的時(shí)候進(jìn)行的。 【干貨點(diǎn)】 此處是【好好面試】系列文的第11篇文章。看完該篇文章,你就可以了解Spring中Aop的相關(guān)使用和原理,并且能夠輕松解答Aop相關(guān)的面試問(wèn)題。更重要的是,很多人其實(shí)一看源碼就...

    aervon 評(píng)論0 收藏0
  • Java動(dòng)態(tài)代理 jdk和cglib實(shí)現(xiàn)比較

    摘要:與靜態(tài)代理對(duì)比,動(dòng)態(tài)代理是在動(dòng)態(tài)生成代理類(lèi),由代理類(lèi)完成對(duì)具體方法的封裝,實(shí)現(xiàn)的功能。本文將分析中兩種動(dòng)態(tài)代理的實(shí)現(xiàn)方式,和,比較它們的異同。那如何動(dòng)態(tài)編譯呢你可以使用,這是一個(gè)封裝了的庫(kù),幫助你方便地實(shí)現(xiàn)動(dòng)態(tài)編譯源代碼。 發(fā)現(xiàn)Java面試很喜歡問(wèn)Spring AOP怎么實(shí)現(xiàn)的之類(lèi)的問(wèn)題,所以寫(xiě)一篇文章來(lái)整理一下。關(guān)于AOP和代理模式的概念這里并不做贅述,而是直奔主題,即AOP的實(shí)現(xiàn)方...

    h9911 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<