面向方面的Java编程没有AspectJ?

2022-09-04 21:24:16

好吧,这个问题以前从未在网络上被问过,所以这里是:我正在学习Java(初级中级水平),我决定通过尝试面向方面的编程来提前上课。

现在这个东西应该很容易学习(至少这是网络共识),以至于“方面”被认为是标准类的略微修改版本,所以我的问题是:如果方面基本上是类,

为什么我们必须安装AspectJ才能在Java中执行AOP?

因为这只会增加一层额外的复杂性,使概念更难掌握。

我想要的是能够在不使用AspectJ(或任何其他附加组件)的情况下编写一个方面,换句话说,我想只使用BASIC Java及其标准java类来做AOP。这是可能的,如果是这样,我必须如何编写这些类?


答案 1

AspectJ是一个,由于缺乏更好的词,“纯”Aspect框架。标准是它可以在各种情况下广泛使用。任何方面,任何课堂,任何时间。

也就是说,拦截和包装方法调用的方面技术在Java中无处不在。然而,这些趋势是将通用方面概念专门用于特定目的。

一个非常早期的“方面”是通过早期的EJB功能完成的。这需要使用 XML 文件来扩充类和接口,以便容器可以创建代理对象,这些对象将方法调用包装到事务上下文中。这些方法的这种包装是一个方面概念,但早期的 EJB 规范只在事务管理的非常具体的用例上提供了功能。

Java 1.5 中注释的到来开启了面向方面的编程的这种增强概念。这并不是说你需要注释来启用它,而只是使框架更易于使用,因为注释消除了外部元数据配置(也许使用XML文件)。

因此,现在,许多Java系统使用面向方面的编程概念,通常通过反射和注释来实现某些功能。这是否是实例注入,围绕方法,验证等。

这一切的关键组成部分是某种拦截方法调用的机制。AspectJ 的工作原理是动态更改目标类,而不是插入中间人。EJB 的工作原理是在接口上创建代理(在 Java 中可以开箱即用),然后当程序请求容器提供实例时,它会提供由实际实例支持的代理。

因此,要实现“通用”AOP,无论何时何地,您当然都需要像AspectJ这样广泛的东西。但是要从中获得很多好处,你不需要走那么远。一个简单的工厂类和一个接口可以很容易地完成这项工作。


答案 2

Java不支持开箱即用的AOP,我不建议自己实现它,因为您必须在加载类文件时修改它们。或者,您也可以修改编译的类文件,但这会更加复杂。

AspectJ 使用 Java 代理来设置编织类装入器(它在装入时修改类文件),但您也可以手动使用自己的类装入器。如果要修改的类都实现了接口,则可以使用 Java 代理进行 AOP。否则,您将不得不使用CGLib,Javassist或ASM等外部库(或了解Java字节码的工作原理)。

一些进一步的信息:

代理示例:

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class ProxyExample {

    public static void main(String[] args) {
        AnInterface obj = new AClass();
        AnInterface proxyObj = createProxy(obj);
        System.out.println(obj.aMethod());
        System.out.println(proxyObj.aMethod());
    }

    private static AnInterface createProxy(AnInterface obj) {
        return (AnInterface) Proxy.newProxyInstance(ProxyExample.class.getClassLoader(),
                new Class<?>[] {AnInterface.class},
                new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                return "proxy: " + method.invoke(obj);
            }
        });
    }

    static interface AnInterface {
        public String aMethod();
    }

    static class AClass implements AnInterface {
        @Override
        public String aMethod() {
            return "string";
        }
    }

}

推荐