静态AOP

  • 静态代理

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

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

//接口
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了。

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 180,596评论 25赞 708
  • 文/荞二熊 “咿呀~咿呀咿~” “君生我未生,我生君已老。君恨我生迟,我恨君生早。” 永生池里传来一阵咏诵,低沉,...
    荞二熊阅读 573评论 12赞 15
  • 今天来了兴趣,闺蜜三人约了一起做蛋黄酥。 中午吃完饭后,我就把咸鸭蛋上的土洗了干净,欣慰的是我家的两宝贝还帮忙洗了...
    做最好的me你懂的阅读 283评论 0赞 0
  • 这扇窗户里面有着陪伴我每一天的东西,一回到家,打开书,翻开铅笔盒,把文具如摆摊般的晾在铅笔盒上,今天在这扇窗里面,...
    lucky乖乖鱼阅读 210评论 0赞 0
  • 一日一签 “人们总以为幸福遥不可及,觉得幸福复杂、难得。不过,一些小事情就能让人感到幸福。比如下雨的时候有躲雨的地...
    爱画的饭饭阅读 558评论 0赞 0

友情链接更多精彩内容