美文网首页
静态代理之AspectJ编译织入

静态代理之AspectJ编译织入

作者: 雨中独奏 | 来源:发表于2018-07-14 17:06 被阅读0次

前面两篇文章都是说的在代码运行时动态的生成class文件达到动态代理的目的,那我们现在回到静态代理,静态代理唯一的缺点就是我们需要对每一个方法编写我们的代理逻辑,造成了工作的繁琐和复杂。AspectJ就是为了解决这个问题,在编译成class字节码的时候在方法周围加上业务逻辑。复杂的工作由特定的编译器帮我们做。

AOP有切面(Aspect)、连接点(joinpoint)、通知(advice)、切入点(Pointcut)、目标对象(target)等概念,这里不详细介绍这些概念.

AspectJ的使用

如何做ASpectj开发,这里使用的是maven插件:

<plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>aspectj-maven-plugin</artifactId>
                <version>1.5</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>compile</goal>
                            <goal>test-compile</goal>
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <source>1.6</source>
                    <target>1.6</target>
                    <encoding>UTF-8</encoding>
                    <complianceLevel>1.6</complianceLevel>
                    <verbose>true</verbose>
                    <showWeaveInfo>true</showWeaveInfo>
                </configuration>
            </plugin>

然后编写Aspectj的文件.可以编写.ajc文件,或者使用java文件也可以:

//表示对实现了Mtrace接口的类,并且参数数Integer 同时方法中有@RequestMapping 注解的方法插入代理
    @Pointcut("execution(* com.meituan.deploy.Mtrace+.*(java.lang.Integer)) && @annotation(org.springframework.web.bind.annotation.RequestMapping)")
    public void zhiru2() {
 
    }
    @Before(value = "zhiru2()")//前面植入
    public void doBeforeTask2(JoinPoint point) {
        //方法调用前植入
        System.out.println("=========BEFORE=========");
    }
 
    @After("zhiru2()")//后面植入
    public void after(JoinPoint point) {
    //方法调用后植入
        System.out.println("===========AFTER=======");
    }
        @AfterThrowing("zhiru2()")
    public void afterthrowing(JoinPoint point) {
        System.out.println("===========throwing=======");
    }
    @AfterReturning("zhiru2()")
    public void afterRutuen(JoinPoint point) {
        System.out.println("===========return=======");
    }

AspectJ的原理分析

反编译过后得到的java代码如下:

@RequestMapping({"/hello"})
    public ModelAndView helloMyMethodName(Integer name) throws SQLException {
        JoinPoint var2 = Factory.makeJP(ajc$tjp_0, this, this, name);
 
        Object var7;
        try {
            Object var5;
            try {
                //调用before
                Aspectj.aspectOf().doBeforeTask2(var2);
                System.out.println(name);
                Util.report("xiezhaodong");
                var5 = null;
            } catch (Throwable var8) {
                Aspectj.aspectOf().after(var2);
                throw var8;
            }
            //调用after
            Aspectj.aspectOf().after(var2);
            var7 = var5;
        } catch (Throwable var9) {
            //调用抛出异常
            Aspectj.aspectOf().afterthrowing(var2);
            throw var9;
        }
        //调用return
        Aspectj.aspectOf().afterRutuen(var2);
        return (ModelAndView)var7;
    }
 
    @RequestMapping({"/hello2"})
    public ModelAndView helloMyMethodName222(String name) throws SQLException {
        return new ModelAndView("hello", "name", name);
}

上面两个方法都实现了@ RequestMapping注解,类也实现类Mtrace接口。但是因为传入参数的类型不同,所以只有第一个方法被织入了代理的方法,在真正的方法快周围分表调用了beforeafterafterThrowingafterRutnrn等方法。Aspectj简单的原理就是这样.更加深入的原理解析暂时就不做了。

小结

  • Aspectj并不是动态的在运行时生成代理类,而是在编译的时候就植入代码到class文件
  • 由于是静态织入的,所以性能相对来说比较好
  • Aspectj不受类的特殊限制,不管方法是private、或者static、或者final的,都可以代理
  • Aspectj不会代理除了限定方法之外任何其他诸如toString(),clone()等方法

相关文章

  • 静态代理之AspectJ编译织入

    前面两篇文章都是说的在代码运行时动态的生成class文件达到动态代理的目的,那我们现在回到静态代理,静态代理唯一的...

  • 动态代理反射

    动态代理 分类AspectJ编译-静态编译-AspectJ编译编译器JDK动态代理-接口cglib动态代理-子类(...

  • Java JDK Proxy和CGLib动态代理示例讲解

    简介 代理模式在Java中有很多应用场景,而代理又分静态代码和动态代理。静态代理是编写、编译或加载时织入代码实现,...

  • Spring AOP原理

    1,设计:代理模式,责任连模式2,实现:JDK实现,cglib实现3,织入的时机:1)编译期:AspectJ2)类...

  • 2018-09-27 aop相关

    1. 静态织入,需要使用aspectj专用的compiler maven工程可以采用:https://www.mo...

  • spring AOP 编程式应用

    一、spring AOP 和 AspectJ spirng AOP: 是基于对象代理模式进行织入逻辑代码,但对于s...

  • Spring AOP实现方式

    AOP主要是它以横切面的方式,将增强的代码插入到主流程中。 切面织入的方法:1、编译期织入---->Aspectj...

  • Spring AOP底层实现- JDK动态代理和CGLIB动态代

    Spring AOP是运行时织入的,那么运行时织入到底是怎么实现的呢?答案就是代理对象。 代理又可以分为静态代理和...

  • 设计模式之代理模式

    代理分为静态代理和动态代理。 动态代理又包括基于JDK的动态代理、基于CGlib 的动态代理、基于Aspectj实...

  • 基于注解的“零配置”方式

    Spring依然采用运行时生成动态代理的方式来增强目标对象,所以它不需要增加额外的编译,也不需要AspectJ的织...

网友评论

      本文标题:静态代理之AspectJ编译织入

      本文链接:https://www.haomeiwen.com/subject/sbuypftx.html