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

資訊專欄INFORMATION COLUMN

簡(jiǎn)單實(shí)現(xiàn)類似Spring的Aop原理實(shí)現(xiàn)

yanbingyun1990 / 910人閱讀

摘要:關(guān)于的這種,我感覺(jué)應(yīng)該是屬于編譯器織入,因?yàn)槭峭ㄟ^(guò)子類生成字節(jié)碼然后進(jìn)行調(diào)用。

關(guān)于的Aop:
用處:可以用在連接數(shù)據(jù)庫(kù)的方面,比如每一次在連接數(shù)據(jù)庫(kù)的時(shí)候都需要手動(dòng)新建一個(gè)連接,然后執(zhí)行數(shù)據(jù)庫(kù)操作,最后再來(lái)關(guān)閉數(shù)據(jù)庫(kù)的連接來(lái)避免資源的消耗。這時(shí)候有人就在想那么可不可以讓系統(tǒng)在我們每一次執(zhí)行數(shù)據(jù)庫(kù)操作的時(shí)候都自動(dòng)的新建一個(gè)連接然后當(dāng)我們執(zhí)行完數(shù)據(jù)庫(kù)的連接之后再自動(dòng)的關(guān)閉連接呢。
這里就需要一個(gè)數(shù)據(jù)庫(kù)

Aop的原理例子(會(huì)使用到cglib動(dòng)態(tài)代理):
例子:
首先新建三個(gè)注解

//定義在類上面標(biāo)明該類是一個(gè)切點(diǎn)
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAspect {
}
// 前置通知注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Before {
    String value();
}

//后置通知注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface After {
    String value();
}

新建一個(gè)歌曲類

public class Music {
    public void sing(String str){
        System.out.println(str+"唱歌");
    }
}

當(dāng)然,有人唱個(gè)歌就得有人做開(kāi)始前的準(zhǔn)備,例如唱歌前的準(zhǔn)備,于是新建一個(gè)類表示唱歌前的準(zhǔn)備:

@MyAspect // 表明這是一個(gè)切點(diǎn)類
public class Player {
    @Before("reflec.aop.cglibtest.Music.sing()")  // 前置通知,當(dāng)調(diào)用sing方法被調(diào)用的時(shí)候該方法會(huì)被在它之前調(diào)用
    public void beforeSing() {
        System.out.println("開(kāi)始唱歌前的準(zhǔn)備");
    }

    @After("reflec.aop.cglibtest.Music.sing()") // 同理,在調(diào)用sing方法之后再來(lái)調(diào)用該方法
    public void afterSing() {
        System.out.println("唱完之后開(kāi)始評(píng)分");
    }
}

那么當(dāng)調(diào)用sing方法的時(shí)候我們?cè)鯓诱{(diào)用這兩個(gè)方法呢,即怎樣織入這兩個(gè)方法
這里就得考慮Cglib動(dòng)態(tài)代理了,cglib依賴asm包,在目標(biāo)類的基礎(chǔ)上生成一個(gè)子類,然后通過(guò)子類來(lái)實(shí)現(xiàn)在目標(biāo)方法調(diào)用的時(shí)候?qū)崿F(xiàn)前置或者后置通知。。關(guān)于Cglib的這種,我感覺(jué)應(yīng)該是屬于編譯器織入,因?yàn)槭峭ㄟ^(guò)子類生成字節(jié)碼然后進(jìn)行調(diào)用。

建立代理類:
這個(gè)類的作用只要是通過(guò)動(dòng)態(tài)代理來(lái)實(shí)現(xiàn)那兩個(gè)方法的執(zhí)行

public class CGLIBProxy implements MethodInterceptor {
    private Object target;
    private ProxyUtil proxyUtil ;
    public CGLIBProxy(Object target) throws ClassNotFoundException {
        this.target = target;
        proxyUtil =new ProxyUtil();
    }

    public  T getProxy(){
        return (T) new Enhancer().create(this.target.getClass(),this);
    }
    public  T getProxy(Class clazz){
        return (T) new Enhancer().create(this.target.getClass(),this);
    }
    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        ProxyEntity proxyEntity =new ProxyEntity(proxy,this.target.getClass(),obj,method,args);
        return proxyUtil.generateEntity(proxyEntity);
    }

建立反射類:(即主要是通)

public class Reflect {
    Map map ;   //存入的是方法名以及其注解
    Map clazzMap;
    public Reflect() throws ClassNotFoundException {
        map=new HashMap<>();
        clazzMap =new HashMap<>();
        getAnnotationClass();
    }

    public Map getMap() {  // 這里返回的是已經(jīng)全部存好的map方面ProxyUtil使用
        return map;
    }
    @Test
    public  void getAnnotationClass() throws ClassNotFoundException {
        String clazzName="reflec.aop.cglibtest.Player";
        Class  clazz =Class.forName(clazzName,false,Thread.currentThread().getContextClassLoader());   // 這里為了省事直接動(dòng)態(tài)加載了該類
        if (clazz.isAnnotationPresent(MyAspect.class)) {  //假設(shè)是注解類
            Method[] methods =clazz.getDeclaredMethods();   //遍歷方法
            for (Method method :methods) {
                if (method.isAnnotationPresent(Before.class)) {  // 獲取注解
                   Before before =method.getAnnotation(Before.class); 
                    String beforeValue=before.value();  // 獲取注解的值以及當(dāng)前類的名字方面調(diào)用方法
                    map.put(method.getName()+ "-"+clazzName+"-"+"before",beforeValue.substring(0,beforeValue.length()-2));
                    // 存入的是方法名和注解名以及執(zhí)行的順序,這里為了省事直接就在后面寫了
                if (method.isAnnotationPresent(After.class)) {
                    After after =method.getAnnotation(After.class); /
                    String afterValue=after.value();
                    map.put(method.getName()+ "-"+clazzName+"-"+"after",afterValue.substring(0,afterValue.length()-2));
                }
            }
        }
    }

建立處理這個(gè)Cglib里面的MethodInterceptor接口中的intercept方法的具體類

public class ProxyUtil {

    Reflect reflect;

    public ProxyUtil() throws ClassNotFoundException {
        reflect = new Reflect();
    }

    public void getMethod(String name) {
        Map map = new HashMap<>();

    }

    //該方法負(fù)責(zé)代理
    public Object generateEntity(ProxyEntity proxyEntity) throws Throwable {
        String proxyMethodValue = proxyEntity.getMethod().toString().substring(proxyEntity.getMethod().toString().lastIndexOf(" ") + 1, proxyEntity.getMethod().toString().indexOf("("));
        Map methodMap = reflect.getMap();
        for (Map.Entry map : methodMap.entrySet()) {
            if (map.getValue().equals(proxyMethodValue)) {
                String[] str = mapKeyDivision(map.getKey());
                if (str[2].equals("before")) {
                    Class clazz = Class.forName(str[1], false, Thread.currentThread().getContextClassLoader()); // 加載該類
                    Method method = clazz.getDeclaredMethod(str[0]);
                    method.invoke(clazz.newInstance(), null); // 反射調(diào)用方法
                }
            }
        }
        return doAfter(proxyEntity,methodMap); // 處理后置通知
    }
    private Object  doAfter(ProxyEntity proxyEntity,Map map) throws Throwable {
        Object object = proxyEntity.getMethodProxy().invokeSuper(proxyEntity.getObject(), proxyEntity.getArgs());  // 調(diào)用方法
        String proxyMethodValue = proxyEntity.getMethod().toString().substring(proxyEntity.getMethod().toString().lastIndexOf(" ") + 1, proxyEntity.getMethod().toString().indexOf("("));
        for(Map.Entry aMap:map.entrySet()){
            if (aMap.getValue().equals(proxyMethodValue)){
                String[] str =mapKeyDivision(aMap.getKey());
                    if(str[2].equals("after")){
                        Class clazz = Class.forName(str[1], false, Thread.currentThread().getContextClassLoader()); // 加載該類
                        Method method = clazz.getDeclaredMethod(str[0]);
                        method.invoke(clazz.newInstance(), null); // 這一步需要原始的類
                    }
                }
            }
        return object;
    }
//分解map里面的鍵,因?yàn)槔锩娲嫒肓朔椒ê皖惷约皥?zhí)行順序
    private String[] mapKeyDivision(String value) {
        String[] str = new String[10];
        str[0] = value.substring(0, value.indexOf("-"));  //注解下面的方法
        str[1] = value.substring(value.indexOf("-") + 1, value.lastIndexOf("-")); //注解所在的類
        str[2]=value.substring(value.lastIndexOf("-")+1,value.length()); //是before還是after
        return str;
    }

最后是一個(gè)bean

public class ProxyEntity {
    private final MethodProxy methodProxy;
    private final Class clazz;
    private final Object object;
    private final Method method;
    private final Object[] args;

    public Object getObject() {
        return object;
    }

    public Object[] getArgs() {
        return args;
    }

    public Class getClazz() {
        return clazz;
    }

    public Method getMethod() {
        return method;
    }

    public ProxyEntity(MethodProxy methodProxy, Class clazz, Object object, Method method, Object[] args) {
        this.methodProxy = methodProxy;
        this.clazz = clazz;
        this.object = object;
        this.method = method;
        this.args = args;
    }

    public MethodProxy getMethodProxy() {
        return methodProxy;
    }
}

最后進(jìn)行測(cè)試:

public class CglibTest {

public static void main(String args[]) throws ClassNotFoundException {
    Music music = new Music();
    CGLIBProxy cglibProxy = new CGLIBProxy(music);
    ((Music)cglibProxy.getProxy()).sing("測(cè)試的人 ");
}
}

測(cè)試結(jié)果:
開(kāi)始唱歌前的準(zhǔn)備
唱歌測(cè)試的人
唱完之后開(kāi)始評(píng)分

在這個(gè)測(cè)試中并沒(méi)有調(diào)用Player類里面的方法卻在運(yùn)行的時(shí)候自動(dòng)的運(yùn)行了,這個(gè)例子執(zhí)行簡(jiǎn)單的模仿了下Spring的AOP,其實(shí)還有好多地方都沒(méi)有顧及到

這個(gè)類的思路就是先通過(guò)反射獲取到切點(diǎn)類,然后將用注解標(biāo)注的方法名以及注解里面的值存入一個(gè)map,最后在建立一個(gè)類用來(lái)處理map

Github地址:https://github.com/Somersames...

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

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

相關(guān)文章

  • Spring AOP實(shí)現(xiàn)原理

    摘要:使用與的靜態(tài)代理不同,使用的動(dòng)態(tài)代理,所謂的動(dòng)態(tài)代理就是說(shuō)框架不會(huì)去修改字節(jié)碼,而是在內(nèi)存中臨時(shí)為方法生成一個(gè)對(duì)象,這個(gè)對(duì)象包含了目標(biāo)對(duì)象的全部方法,并且在特定的切點(diǎn)做了增強(qiáng)處理,并回調(diào)原對(duì)象的方法。 AOP(Aspect Orient Programming),我們一般稱為面向方面(切面)編程,作為面向?qū)ο蟮囊环N補(bǔ)充,用于處理系統(tǒng)中分布于各個(gè)模塊的橫切關(guān)注點(diǎn),比如事務(wù)管理、日志、緩存...

    ephererid 評(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都是英文寫的。 之前《零基礎(chǔ)帶你看Spring源碼——IOC控制反轉(zhuǎn)》詳細(xì)講了Spring容器的初始化和加載的原理,后面《你真的完全了解Java動(dòng)態(tài)代理嗎?看這篇就夠了》介紹了下...

    wawor4827 評(píng)論0 收藏0
  • 仿照 Spring 實(shí)現(xiàn)簡(jiǎn)單 IOC 和 AOP - 下篇

    摘要:在上文中,我實(shí)現(xiàn)了一個(gè)很簡(jiǎn)單的和容器。比如,我們所熟悉的就是在這里將切面邏輯織入相關(guān)中的。初始化的工作算是結(jié)束了,此時(shí)處于就緒狀態(tài),等待外部程序的調(diào)用。其中動(dòng)態(tài)代理只能代理實(shí)現(xiàn)了接口的對(duì)象,而動(dòng)態(tài)代理則無(wú)此限制。 1. 背景 本文承接上文,來(lái)繼續(xù)說(shuō)說(shuō) IOC 和 AOP 的仿寫。在上文中,我實(shí)現(xiàn)了一個(gè)很簡(jiǎn)單的 IOC 和 AOP 容器。上文實(shí)現(xiàn)的 IOC 和 AOP 功能很單一,且 I...

    AlexTuan 評(píng)論0 收藏0
  • 學(xué)Aop?看這篇文章就夠了!!!

    摘要:又是什么其實(shí)就是一種實(shí)現(xiàn)動(dòng)態(tài)代理的技術(shù),利用了開(kāi)源包,先將代理對(duì)象類的文件加載進(jìn)來(lái),之后通過(guò)修改其字節(jié)碼并且生成子類。 在實(shí)際研發(fā)中,Spring是我們經(jīng)常會(huì)使用的框架,畢竟它們太火了,也因此Spring相關(guān)的知識(shí)點(diǎn)也是面試必問(wèn)點(diǎn),今天我們就大話Aop。特地在周末推文,因?yàn)樵撈恼麻喿x起來(lái)還是比較輕松詼諧的,當(dāng)然了,更主要的是周末的我也在充電學(xué)習(xí),希望有追求的朋友們也盡量不要放過(guò)周末時(shí)...

    boredream 評(píng)論0 收藏0
  • 15個(gè)經(jīng)典Spring面試常見(jiàn)問(wèn)題

    摘要:我自己總結(jié)的學(xué)習(xí)的系統(tǒng)知識(shí)點(diǎn)以及面試問(wèn)題,已經(jīng)開(kāi)源,目前已經(jīng)。目前最新的版本中模塊的組件已經(jīng)被廢棄掉,同時(shí)增加了用于異步響應(yīng)式處理的組件。每一次請(qǐng)求都會(huì)產(chǎn)生一個(gè)新的,該僅在當(dāng)前內(nèi)有效。顯而易見(jiàn),這種模式存在很多問(wèn)題。 我自己總結(jié)的Java學(xué)習(xí)的系統(tǒng)知識(shí)點(diǎn)以及面試問(wèn)題,已經(jīng)開(kāi)源,目前已經(jīng) 41k+ Star。會(huì)一直完善下去,歡迎建議和指導(dǎo),同時(shí)也歡迎Star: https://githu...

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

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

0條評(píng)論

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