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

时间:2014-04-27 18:14:42

标签: java aop

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

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

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

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

我想要的是能够在不使用AspectJ(或任何其他附加组件)的情况下编写方面,换句话说,我只想使用BASIC Java& amp;它的标准java类。是否可能,如果是这样,我该如何编写这些类?

2 个答案:

答案 0 :(得分:7)

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

也就是说,拦截和包装方法调用的方面技术已经在Java中普遍存在。然而,这些趋向于针对特定目的的通用方面概念的专业化。

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

Java 1.5注释的到来打开了面向方面编程的这种增强概念。这并不是说你需要注释才能实现这一点,而只是让框架更容易使用,因为注释消除了外部元数据配置(使用XML文件)。

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

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

所以,要启用" generic" AOP,无处不在,你当然需要像AspectJ这样广泛的东西。但要获得它的许多好处,你不需要走那么远。简单的工厂类和接口可以轻松完成工作。

答案 1 :(得分:4)

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

AspectJ使用Java代理来设置编织类加载器(在加载时修改类文件),但您也可以手动使用自己的类加载器。如果您要修改的类都实现了接口,那么您可以使用Java Proxies进行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";
        }
    }

}