静态AOP

2018-07-28  本文已影响6人  黄二的NPE
  • 静态代理

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

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

//接口
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)来见识一下:

<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>
  1. file->settings->plugins->搜索aspectj,把搜出来的结果都打勾


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


    设置编译器
public class HelloService {
    public void sayHello(){
        System.out.println("hello world");
    }
}
@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了。

上一篇下一篇

猜你喜欢

热点阅读