静态AOP

作者: 黄二的NPE | 来源:发表于2018-07-28 08:45 被阅读6次
  • 静态代理

代理分为静态代理和动态代理。静态代理由程序员创建或工具生成代理类的源码,再编译代理类,所谓静态也就是在程序运行前就已经存在代理类的字节码文件,代理类和委托类的关系在运行前就确定了;而动态代理是指在代码运行期间生成的代理类,他的字节码文件在程序运行之前是找不到的。

我们来看一个简单的静态代理的实现:

//接口
public interface CatService {
    void save();
}
//实现类(操作目标类)
public class CatServiceImpl implements CatService{
    @Override
    public void save() {
        System.out.println("保存了一只猫...");
    }
}
//代理类
public class CatServiceProxy implements  CatService {

    CatService catService;

    public CatServiceProxy(CatService catService) {
        this.catService = catService;
    }

    @Override
    public void save() {
        System.out.println("我是代理类,在操作之前");
        catService.save();
        System.out.println("我是代理类,在操作之后");
    }
}
//调用和测试
    public static void main(String[] args) {
        CatService catService = new CatServiceImpl();
        CatService catServiceProxy = new CatServiceProxy(catService);
        catServiceProxy.save();
    }

通过上面代码的几步操作,一个简单的静态代理类就完成了。在这个例子中,CatServiceProxy就是我们的静态代理类,它代理了CatServiceImpl。

  • Aspectj

说到静态Aop的鼻祖,那非aspectj莫属。编译的时候,aspectj早已把我们的通知织入到代码中。我们写个小小的demo(基于maven和idea)来见识一下:

  • pom.xml 引入相关的配置,在dependencies中引入aspectjrt,aspectjtools,aspectjweaver,在plugins中引入编译插件aspectj-maven-plugin。
<dependencies>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjrt</artifactId>
            <version>1.8.9</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjtools</artifactId>
            <version>1.8.9</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.7.4</version>
        </dependency>
</dependencies>
    <build>
        <plugins>
            <!-- AspectJ 编译插件 -->
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>aspectj-maven-plugin</artifactId>
                <version>1.8</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>compile</goal>       <!-- use this goal to weave all your main classes -->
                            <goal>test-compile</goal>  <!-- use this goal to weave all your test classes -->
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
  • 设置idea
  1. file->settings->plugins->搜索aspectj,把搜出来的结果都打勾


    idea设置
  2. 设置编译器,编译aj文件需要自己的编译器


    设置编译器
  • 编写一个很简单的Java类
public class HelloService {
    public void sayHello(){
        System.out.println("hello world");
    }
}
  • 编写aspectJ文件(HelloServiceAspectJ.aj 注意.aj做后缀)
    你会发现这语法跟spring aop差不多,其实spring aop也是从aspectj中借鉴
@Aspect
public aspect HelloServiceAspectj {
    @Before(value = "execution(* aspectj.HelloService.sayHello(..))")
    public void sayHelloBefore() {
        System.out.println("我是aspect");
    }
}
  • 编写运行类
public class AspectjMain {
    public static void main(String[] args) {
        HelloService helloService = new HelloService();
        helloService.sayHello();
    }
}

运行以后,我们想要的结果也出来了。但是这是怎么实现的呢?我们说aspectj是静态aop,也就是说运行前已经生成相应的aop文件了,那么编译后的文件是怎么样的呢?



HelloService.class

public class HelloService {
    public HelloService() {
    }

    public void sayHello() {
        HelloServiceAspectj.aspectOf().sayHelloBefore();
        System.out.println("hello world");
    }
}

我们可以看到输出hello world之前,先调用了HelloServiceAspectj.aspectOf().sayHelloBefore();我们先来看看这又是什么?

@Aspect
public class HelloServiceAspectj {
    static {
        try {
            ajc$postClinit();
        } catch (Throwable var1) {
            ajc$initFailureCause = var1;
        }

    }

    public HelloServiceAspectj() {
    }

    @Before("execution(* aspectj.HelloService.sayHello(..))")
    public void sayHelloBefore() {
        System.out.println("我是aspect");
    }

    public static HelloServiceAspectj aspectOf() {
        if(ajc$perSingletonInstance == null) {
            throw new NoAspectBoundException("aspectj_HelloServiceAspectj", ajc$initFailureCause);
        } else {
            return ajc$perSingletonInstance;
        }
    }

    public static boolean hasAspect() {
        return ajc$perSingletonInstance != null;
    }
}

可以看到实际上是调用了HelloServiceAspectj 的sayHelloBefore的方法。
在这里,我认为aspectj已经不是利用代理来实现aop了。

相关文章

  • 动态AOP

    动态AOP 上篇文章我们讲到,AOP分为静态AOP和动态AOP。静态AOP在代码编译之后,已经有代理类或者已经改变...

  • Spring AOP中的动态代理:JDK动态代理和CGLIB动态

    静态代理模式  所谓静态代理就是AOP框架会在编译阶段生成AOP代理类,因此也称为编译时增强。ApsectJ是静态...

  • spring aop 汇总

    静态代理、动态代理和cglib代理 aop 使用 Spring AOP - 注解方式使用介绍spring aop ...

  • 静态动态AOP

    静态AOP实现:AOP框架在编译阶段对程序进行修改,即实现对目标类的增强,生成静态的AOP代理类(生成的*.cla...

  • 5.2 AOP的类型

    静态AOP 优点:性能较好支持更多类型的连接点如果需要在spring使用静态AOP,就需要使用AspectJ 动态...

  • 静态AOP

    静态代理 代理分为静态代理和动态代理。静态代理由程序员创建或工具生成代理类的源码,再编译代理类,所谓静态也就是在程...

  • 2019-06-11

    四、Spring的AOP AOP实现可分为两类(按AOP框架修改源代码的时机): 静态AOP实现:AOP框架在编译...

  • Spring的AOP

    、Spring的AOP AOP实现可分为两类(按AOP框架修改源代码的时机): 静态AOP实现:AOP框架在编译阶...

  • Spring之代理模式

    九、代理模式 目录:静态代理、动态代理AOP的底层机制就是动态代理。代理模式分为静态代理和动态代理。接触aop之前...

  • 由浅入深带你搞定spring Aop

    概述 AOP实现可分为两类(按AOP框架修改源代码的时机): 静态AOP实现:AOP框架在编译阶段对程序进行修改,...

网友评论

      本文标题:静态AOP

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