AOP(面向切面編程)是編程思想,Spring AOP 只是其中一種實現。Java JDK 動態代理(java.lang.reflect.Proxy)基於接口生成代理類,運行時攔截方法調用,是輕量級 AOP 的基石。
public interface Animal {
void setName(String name);
String getName();
void say();
void getProperty();
}
public class Dog implements Animal {
private String name = "小黑";
@Override public void setName(String name) { this.name = name; }
@Override public String getName() { return name; }
@Override public void say() { System.out.println("小狗: 汪汪汪..."); }
@Override public void getProperty() { System.out.println("小狗是陸生動物,但會游泳"); }
}
public class AopHandler implements InvocationHandler {
private final Object target; // 被代理目標對象
public AopHandler(Object target) { this.target = target; }
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.err.println(">>> 方法執行前: " + method.getName());
Object result = method.invoke(target, args); // 反射調用目標方法
System.err.println("<<< 方法執行後: " + method.getName());
return result;
}
}
public class AnimalFactory {
@SuppressWarnings("unchecked")
public static <T> T getAnimal(Class<T> interfaceClass, Object target) {
return (T) Proxy.newProxyInstance(
interfaceClass.getClassLoader(),
new Class[]{interfaceClass},
new AopHandler(target)
);
}
}
public class AopTest {
public static void main(String[] args) {
Animal dog = AnimalFactory.getAnimal(Animal.class, new Dog());
dog.say();
System.out.println("名字: " + dog.getName());
dog.setName("二狗子");
System.out.println("新名字: " + dog.getName());
}
}
// 輸出:
// >>> 方法執行前: say
// 小狗: 汪汪汪...
// <<< 方法執行後: say
// >>> 方法執行前: getName
// <<< 方法執行後: getName
// 名字: 小黑
// >>> 方法執行前: setName
// <<< 方法執行後: setName
// >>> 方法執行前: getName
// <<< 方法執行後: getName
// 新名字: 二狗子
public interface Aspect {
void before(Object proxy, Method method, Object[] args);
void after(Object proxy, Method method, Object[] args);
}
public class AopHandler implements InvocationHandler {
private final Object target;
private final Aspect aspect;
public AopHandler(Object target, Aspect aspect) {
this.target = target;
this.aspect = aspect;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
aspect.before(proxy, method, args);
Object result = method.invoke(target, args);
aspect.after(proxy, method, args);
return result;
}
}
// 使用匿名內部類定義具體切面邏輯
Animal dog = AnimalFactory.getAnimal(Animal.class, new Dog(), new Aspect() {
@Override public void before(Object p, Method m, Object[] a) {
System.err.println("【切面前】" + m.getName());
}
@Override public void after(Object p, Method m, Object[] a) {
System.err.println("【切面後】" + m.getName());
}
});
Method 對象或改用字節碼生成(ByteBuddy/ASM)。before 中根據 method.getName() 判斷是否執行切面邏輯,實現方法級精準切入。JDK 動態代理通過 Proxy.newProxyInstance + InvocationHandler 實現無侵入式方法攔截,是理解 Spring AOP 底層原理的最佳切入點。掌握其機制後,可自行構建輕量級事務、日誌、權限、監控等橫切關注點框架。