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

資訊專欄INFORMATION COLUMN

從零開(kāi)始實(shí)現(xiàn)一個(gè)簡(jiǎn)易的Java MVC框架(五)--引入aspectj實(shí)現(xiàn)AOP切點(diǎn)

wupengyu / 1530人閱讀

摘要:接下來(lái)就可以把這個(gè)切點(diǎn)類加入到我們之前實(shí)現(xiàn)的功能中了。實(shí)現(xiàn)的切點(diǎn)功能首先改裝注解,把之前改成來(lái)存儲(chǔ)表達(dá)式。測(cè)試用例在上一篇文章從零開(kāi)始實(shí)現(xiàn)一個(gè)簡(jiǎn)易的框架四實(shí)現(xiàn)中的測(cè)試用例的基礎(chǔ)上修改測(cè)試用例。

前言

在上一節(jié)從零開(kāi)始實(shí)現(xiàn)一個(gè)簡(jiǎn)易的Java MVC框架(四)--實(shí)現(xiàn)AOP中我們實(shí)現(xiàn)了AOP的功能,已經(jīng)可以生成對(duì)應(yīng)的代理類了,但是對(duì)于代理對(duì)象的選擇只能通過(guò)指定的類,這樣確實(shí)不方便也不合理。這一節(jié)我們就利用aspectj來(lái)實(shí)現(xiàn)功能更強(qiáng)大的切點(diǎn)。

在spring初期的時(shí)候AOP功能使用起來(lái)也是很繁瑣麻煩的,到了后面整合了aspectj才有了現(xiàn)在這么方便的AOP功能,比如下面這樣的代碼,很簡(jiǎn)便并且直觀的定義了切點(diǎn)。

@Component
@Aspect
public class LogAspect {
    @Pointcut("execution(* com.zbw.*.service..*Impl.*(..)) && @annotation(Log)")
    public void logPointcut() {
    }

    @Before("logPointcut()")
    public void before()
    {System.out.println("Before");}
}

現(xiàn)在我們也來(lái)引入aspectj來(lái)實(shí)現(xiàn)AOP切點(diǎn)的功能

引入aspectj并實(shí)現(xiàn)aspectj的切點(diǎn)類

首先在pom.xml中加入aspectj的依賴


    ...
    1.8.13


    ...
    
    
        org.aspectj
        aspectjweaver
        ${aspectj.version}
    

接下來(lái)就可以開(kāi)始實(shí)現(xiàn)一個(gè)利用aspectj來(lái)判定的切點(diǎn)類,這個(gè)類主要是用于判斷aspectj表達(dá)式是否匹配一個(gè)指定類或者指定方法。

在zbw.aop包下創(chuàng)建一個(gè)類,起名叫ProxyPointcut

package com.zbw.aop;

import ...

/**
 * 代理切點(diǎn)類
 */
public class ProxyPointcut {
    /**
     * 切點(diǎn)解析器
     */
    private PointcutParser pointcutParser;

    /**
     * (AspectJ)表達(dá)式
     */
    private String expression;

    /**
     * 表達(dá)式解析器
     */
    private PointcutExpression pointcutExpression;

    /**
     * AspectJ語(yǔ)法集合
     */
    private static final Set DEFAULT_SUPPORTED_PRIMITIVES = new HashSet<>();

    static {
        DEFAULT_SUPPORTED_PRIMITIVES.add(PointcutPrimitive.EXECUTION);
        DEFAULT_SUPPORTED_PRIMITIVES.add(PointcutPrimitive.ARGS);
        DEFAULT_SUPPORTED_PRIMITIVES.add(PointcutPrimitive.REFERENCE);
        DEFAULT_SUPPORTED_PRIMITIVES.add(PointcutPrimitive.THIS);
        DEFAULT_SUPPORTED_PRIMITIVES.add(PointcutPrimitive.TARGET);
        DEFAULT_SUPPORTED_PRIMITIVES.add(PointcutPrimitive.WITHIN);
        DEFAULT_SUPPORTED_PRIMITIVES.add(PointcutPrimitive.AT_ANNOTATION);
        DEFAULT_SUPPORTED_PRIMITIVES.add(PointcutPrimitive.AT_WITHIN);
        DEFAULT_SUPPORTED_PRIMITIVES.add(PointcutPrimitive.AT_ARGS);
        DEFAULT_SUPPORTED_PRIMITIVES.add(PointcutPrimitive.AT_TARGET);
    }

    public ProxyPointcut() {
        this(DEFAULT_SUPPORTED_PRIMITIVES);
    }

    public ProxyPointcut(Set supportedPrimitives) {
        pointcutParser = PointcutParser
                .getPointcutParserSupportingSpecifiedPrimitivesAndUsingContextClassloaderForResolution(supportedPrimitives);
    }

    /**
     * Class是否匹配切點(diǎn)表達(dá)式
     */
    public boolean matches(Class targetClass) {
        checkReadyToMatch();
        return pointcutExpression.couldMatchJoinPointsInType(targetClass);
    }

    /**
     * Method是否匹配切點(diǎn)表達(dá)式
     */
    public boolean matches(Method method) {
        checkReadyToMatch();
        ShadowMatch shadowMatch = pointcutExpression.matchesMethodExecution(method);
        if (shadowMatch.alwaysMatches()) {
            return true;
        } else if (shadowMatch.neverMatches()) {
            return false;
        }
        return false;
    }

    /**
     * 初始化切點(diǎn)解析器
     */
    private void checkReadyToMatch() {
        if (null == pointcutExpression) {
            pointcutExpression = pointcutParser.parsePointcutExpression(expression);
        }
    }

    public void setExpression(String expression) {
        this.expression = expression;
    }

    public String getExpression() {
        return expression;
    }

這個(gè)類中有三個(gè)變量:pointcutParser,expression,pointcutExpression

其中expression是String類型,用于存放我們要設(shè)定的aspectj表達(dá)式,比如execution(* com.zbw.*.service..*Impl.*(..))這樣的。

pointcutParserpointcutExpression就是aspectj里面的類了,pointcutParser用于根據(jù)expression中的表達(dá)式創(chuàng)建pointcutExpression表達(dá)式解析器。而pointcutExpression可以用來(lái)判斷方法或者類是否匹配表達(dá)式。

這個(gè)類中最主要的兩個(gè)方法就matches(Class targetClass)matches(Method method),這兩個(gè)方法分別用于判定目標(biāo)的類和方法是否匹配expression中的aspectj表達(dá)式。

接下來(lái)就可以把ProxyPointcut這個(gè)切點(diǎn)類加入到我們之前實(shí)現(xiàn)的AOP功能中了。

實(shí)現(xiàn)AOP的切點(diǎn)功能

首先改裝Aspect注解,把之前target()改成pointcut()來(lái)存儲(chǔ)aspectj表達(dá)式。

package com.zbw.aop.annotation;
import ...;

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Aspect {
    /**
     * 切點(diǎn)表達(dá)式
     */
    String pointcut() default "";
}
    

然后改裝ProxyAdvisor這個(gè)類,把切點(diǎn)表達(dá)式匹配器放入其中,并且使用匹配器來(lái)判定目標(biāo)類是否要被增強(qiáng)。

...

public class ProxyAdvisor {

    ...

    /**
     * AspectJ表達(dá)式切點(diǎn)匹配器
     */
    private ProxyPointcut pointcut;

    /**
     * 執(zhí)行代理方法
     */
    public Object doProxy(Object target, Class targetClass, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        if (!pointcut.matches(method)) {
            return proxy.invokeSuper(target, args);
        }

        ...
    }
}

doProxy()這個(gè)方法的最前面通過(guò)pointcut.matches()來(lái)判定目標(biāo)方法是否匹配這個(gè)表達(dá)式,如果匹配的話就往下執(zhí)行之前編寫(xiě)的各種通知,如果不匹配那么就直接執(zhí)行目標(biāo)方法。通過(guò)這種方式來(lái)使aspectj表達(dá)式控制目標(biāo)類的增強(qiáng)。

接下來(lái)改裝Aop類,由于改變了匹配目標(biāo)類的規(guī)則,所以要重寫(xiě)之前的doAop()方法。

...

public class Aop {
    ...

    public void doAop() {
        beanContainer.getClassesBySuper(Advice.class)
                .stream()
                .filter(clz -> clz.isAnnotationPresent(Aspect.class))
                .map(this::createProxyAdvisor)
                .forEach(proxyAdvisor -> beanContainer.getClasses()
                        .stream()
                        .filter(target -> !Advice.class.isAssignableFrom(target))
                        .filter(target -> !target.isAnnotationPresent(Aspect.class))
                        .forEach(target -> {
                            if (proxyAdvisor.getPointcut().matches(target)) {
                                Object proxyBean = ProxyCreator.createProxy(target, proxyAdvisor);
                                beanContainer.addBean(target, proxyBean);
                            }
                        }));
    }

    /**
     * 通過(guò)Aspect切面類創(chuàng)建代理通知類
     */
    private ProxyAdvisor createProxyAdvisor(Class aspectClass) {
        String expression = aspectClass.getAnnotation(Aspect.class).pointcut();
        ProxyPointcut proxyPointcut = new ProxyPointcut();
        proxyPointcut.setExpression(expression);
        Advice advice = (Advice) beanContainer.getBean(aspectClass);
        return new ProxyAdvisor(advice, proxyPointcut);
    }
}

雖然重寫(xiě)了doAop()方法,但是實(shí)現(xiàn)原理依舊是相同的。只不過(guò)現(xiàn)在把創(chuàng)建ProxyAdvisor的過(guò)程分離出來(lái)多帶帶寫(xiě)了一個(gè)方法createProxyAdvisor()
然后再遍歷Bean容器中的除了切面類的所有Bean,如果這個(gè)Bean匹配ProxyAdvisor中的切點(diǎn)表達(dá)式,那么就會(huì)生成對(duì)應(yīng)的代理類。

引入aspectj實(shí)現(xiàn)AOP切點(diǎn)完成了,又到測(cè)試用例來(lái)測(cè)試功能是否成功的時(shí)候了。

測(cè)試用例

在上一篇文章從零開(kāi)始實(shí)現(xiàn)一個(gè)簡(jiǎn)易的Java MVC框架(四)--實(shí)現(xiàn)AOP中的測(cè)試用例的基礎(chǔ)上修改測(cè)試用例。

先修改切面類DoodleAspect上的Aspect注解

package com.zbw.bean;
import ...

@Slf4j
@Aspect(pointcut = "execution(* com.zbw.bean.DoodleController.helloForAspect(..))")
public class DoodleAspect implements AroundAdvice {

    ...

}

這個(gè)Aspect@pointcut()中的值會(huì)讓其只匹配DoodleController中的helloForAspect()方法。

接下來(lái)在DoodleController添加helloForAspect()方法

...

public class DoodleController {
       ...

    public void helloForAspect() {
        log.info("Hello Aspectj");
    }
}

最后再重新編寫(xiě)AopTest的測(cè)試用例。

package com.zbw.aop;
import ...

@Slf4j
public class AopTest {
    @Test
    public void doAop() {
        BeanContainer beanContainer = BeanContainer.getInstance();
        beanContainer.loadBeans("com.zbw");
        new Aop().doAop();
        new Ioc().doIoc();
        DoodleController controller = (DoodleController) beanContainer.getBean(DoodleController.class);
        controller.hello();
        controller.helloForAspect();
    }
}

從結(jié)果的圖中可以看到在DoodleControllerhello()前后沒(méi)有打印多余的日志,而在helloForAspect()方法的前面和后面都打印了DoodleAspect中的通知方法里的內(nèi)容,說(shuō)明我們的AOP已經(jīng)精準(zhǔn)的匹配到了想要的目標(biāo)。

從零開(kāi)始實(shí)現(xiàn)一個(gè)簡(jiǎn)易的Java MVC框架(一)--前言

從零開(kāi)始實(shí)現(xiàn)一個(gè)簡(jiǎn)易的Java MVC框架(二)--實(shí)現(xiàn)Bean容器

從零開(kāi)始實(shí)現(xiàn)一個(gè)簡(jiǎn)易的Java MVC框架(三)--實(shí)現(xiàn)IOC

從零開(kāi)始實(shí)現(xiàn)一個(gè)簡(jiǎn)易的Java MVC框架(四)--實(shí)現(xiàn)AOP

從零開(kāi)始實(shí)現(xiàn)一個(gè)簡(jiǎn)易的Java MVC框架(五)--引入aspectj實(shí)現(xiàn)AOP切點(diǎn)

從零開(kāi)始實(shí)現(xiàn)一個(gè)簡(jiǎn)易的Java MVC框架(六)--加強(qiáng)AOP功能

從零開(kāi)始實(shí)現(xiàn)一個(gè)簡(jiǎn)易的Java MVC框架(七)--實(shí)現(xiàn)MVC

從零開(kāi)始實(shí)現(xiàn)一個(gè)簡(jiǎn)易的Java MVC框架(八)--制作Starter

從零開(kāi)始實(shí)現(xiàn)一個(gè)簡(jiǎn)易的Java MVC框架(九)--優(yōu)化MVC代碼

源碼地址:doodle

原文地址:從零開(kāi)始實(shí)現(xiàn)一個(gè)簡(jiǎn)易的Java MVC框架(五)--引入aspectj實(shí)現(xiàn)AOP切點(diǎn)

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

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

相關(guān)文章

  • 從零開(kāi)始實(shí)現(xiàn)一個(gè)簡(jiǎn)易Java MVC框架(六)--加強(qiáng)AOP功能

    摘要:在前面的文章中實(shí)現(xiàn)的功能時(shí),目標(biāo)類都只能被一個(gè)切面代理,如果想要生成第二個(gè)代理類,就會(huì)把之前的代理類覆蓋。改裝原有功能現(xiàn)在要改裝原來(lái)的的實(shí)現(xiàn)代碼,讓的功能加入到框架中為了讓切面能夠排序,先添加一個(gè)注解,用于標(biāo)記排序。 前言 在前面從零開(kāi)始實(shí)現(xiàn)一個(gè)簡(jiǎn)易的Java MVC框架(四)--實(shí)現(xiàn)AOP和從零開(kāi)始實(shí)現(xiàn)一個(gè)簡(jiǎn)易的Java MVC框架(五)--引入aspectj實(shí)現(xiàn)AOP切點(diǎn)這兩節(jié)文章...

    Loong_T 評(píng)論0 收藏0
  • 從零開(kāi)始實(shí)現(xiàn)一個(gè)簡(jiǎn)易Java MVC框架

    摘要:不過(guò)仔細(xì)了解了一段時(shí)候發(fā)現(xiàn),其實(shí)他的原理是很簡(jiǎn)單的,所以想要自己也動(dòng)手實(shí)現(xiàn)一個(gè)功能類似的框架。原文地址從零開(kāi)始實(shí)現(xiàn)一個(gè)簡(jiǎn)易的框架 前言 最近在看spring-boot框架的源碼,看了源碼之后更是讓我感受到了spring-boot功能的強(qiáng)大。而且使用了很多的設(shè)計(jì)模式,讓人在看的時(shí)候覺(jué)得有點(diǎn)難以下手。 不過(guò)仔細(xì)了解了一段時(shí)候發(fā)現(xiàn),其實(shí)他的原理是很簡(jiǎn)單的,所以想要自己也動(dòng)手實(shí)現(xiàn)一個(gè)功能類似的...

    neuSnail 評(píng)論0 收藏0
  • 從零開(kāi)始實(shí)現(xiàn)一個(gè)簡(jiǎn)易Java MVC框架(八)--制作Starter

    摘要:服務(wù)器相關(guān)配置啟動(dòng)類資源目錄目錄靜態(tài)文件目錄端口號(hào)目錄目錄實(shí)現(xiàn)內(nèi)嵌服務(wù)器在上一章文章從零開(kāi)始實(shí)現(xiàn)一個(gè)簡(jiǎn)易的框架七實(shí)現(xiàn)已經(jīng)在文件中引入了依賴,所以這里就不用引用了。 spring-boot的Starter 一個(gè)項(xiàng)目總是要有一個(gè)啟動(dòng)的地方,當(dāng)項(xiàng)目部署在tomcat中的時(shí)候,經(jīng)常就會(huì)用tomcat的startup.sh(startup.bat)的啟動(dòng)腳本來(lái)啟動(dòng)web項(xiàng)目 而在spring-b...

    AprilJ 評(píng)論0 收藏0
  • 從零開(kāi)始實(shí)現(xiàn)一個(gè)簡(jiǎn)易Java MVC框架(九)--優(yōu)化MVC代碼

    摘要:前言在從零開(kāi)始實(shí)現(xiàn)一個(gè)簡(jiǎn)易的框架七實(shí)現(xiàn)中實(shí)現(xiàn)了框架的的功能,不過(guò)最后指出代碼的邏輯不是很好,在這一章節(jié)就將這一部分代碼進(jìn)行優(yōu)化。 前言 在從零開(kāi)始實(shí)現(xiàn)一個(gè)簡(jiǎn)易的Java MVC框架(七)--實(shí)現(xiàn)MVC中實(shí)現(xiàn)了doodle框架的MVC的功能,不過(guò)最后指出代碼的邏輯不是很好,在這一章節(jié)就將這一部分代碼進(jìn)行優(yōu)化。 優(yōu)化的目標(biāo)是1.去除DispatcherServlet請(qǐng)求分發(fā)器中的http邏...

    ruicbAndroid 評(píng)論0 收藏0
  • Spring之旅第七站:面向切面編程(AOP)

    摘要:面向切面的本章主要內(nèi)容面向切面編程的基本原理通過(guò)創(chuàng)建切面使用注解為切面注入依賴。什么是面向切面編程切面能夠幫我們模塊化橫切關(guān)注點(diǎn)。在使用面向切面編程時(shí),我們?nèi)匀辉谝粋€(gè)地方定義通知功能,而無(wú)需修改受影響的類。切面切面是通知和切點(diǎn)的結(jié)合。 面向切面的Spring 本章主要內(nèi)容: 面向切面編程的基本原理 通過(guò)POJO創(chuàng)建切面 使用@Aspect注解 為AspectJ切面注入依賴。 說(shuō)明 ...

    趙連江 評(píng)論0 收藏0

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

0條評(píng)論

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