好的,这个问题以前从未在网上被问过,所以这里有: 我正在学习Java(初级 - 中级),我决定通过尝试面向方面的编程来领先课程。
现在这个东西应该很容易学习(至少那是网络共识) 所以“方面”被认为是标准类的略微修改版本, 所以我的问题是:如果方面基本上是类,
为什么我们必须安装AspectJ才能在Java中执行AOP?
因为这只会增加额外的复杂性,使概念更难以掌握。
我想要的是能够在不使用AspectJ(或任何其他附加组件)的情况下编写方面,换句话说,我只想使用BASIC Java& amp;它的标准java类。是否可能,如果是这样,我该如何编写这些类?
答案 0 :(得分:7)
也就是说,拦截和包装方法调用的方面技术已经在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";
}
}
}