Man:目標物件,含 qq()、mm() 方法FBI:實現 MethodBeforeAdvice 的前置通知,記錄方法調用ProxyFactoryBean:代理工廠,攔截目標方法並委派給通知<bean id="man" class="Man">
<property name="name"><value>張三</value></property>
</bean>
<bean id="fbi" class="FBI"/>
<bean id="civilian" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="target"><ref bean="man"/></property>
<property name="interceptorNames"><list><value>fbi</value></list></property>
</bean>
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
Man man = (Man) ctx.getBean("civilian"); // 必須獲取代理 bean
man.qq(); man.mm();
輸出:FBI 發現張三正在進行 qq 活動。/ 我在聊QQ ...
ProxyFactoryBean,直接對原 bean 織入FBI 變為 POJO,無需實現介面,方法簽名自由man,容器自動代理public class FBI {
public void before(JoinPoint point) {
Man man = (Man) point.getTarget();
System.err.println("FBI 發現" + man.getName() + "正在進行 " + point.getSignature().getName() + " 活動。");
}
}
<beans xmlns:aop="https://www.springframework.org/schema/aop" ...>
<bean id="fbi" class="FBI"/>
<bean id="man" class="Man">...</bean>
<aop:config>
<aop:pointcut id="manPointcut" expression="execution(* Man.*(..))"/>
<aop:aspect id="beforeExample" ref="fbi">
<aop:before pointcut-ref="manPointcut" method="before"/>
</aop:aspect>
</aop:config>
</beans>
<aop:aspectj-autoproxy/>
<!-- 或 <bean class="org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator"/> -->
@Aspect
public class FBI {
@Before("execution(* Man.*(..))")
public void before(JoinPoint point) {
Man man = (Man) point.getTarget();
System.err.println("FBI 發現" + man.getName() + "正在進行 " + point.getSignature().getName() + " 活動。");
}
}
僅需保留 bean 定義與 <aop:aspectj-autoproxy/>,切面自動識別。
| 術語 | 說明 |
|---|---|
| Aspect(切面) | 橫切關注點模組化(如事務、日志) |
| Joinpoint(連接點) | 程序執行特定點(Spring 僅支援方法執行) |
| Advice(通知) | 切面在連接點執行的動作(Before/After/Around 等) |
| Pointcut(切入點) | 匹配連接點的斷言表達式 |
| Target Object(目標對象) | 被代理的對象 |
| AOP Proxy(AOP 代理 | 框架創建的代理物件(JDK 動態代理/CGLIB) |
| Weaving(織入) | 將切面應用到目標對象(Spring 執行期織入) |
@Before@AfterReturning@AfterThrowing@Around(最強大但最複雜)原則:能用簡單通知類型解決的,絕不使用 Around,減少 proceed() 忘調用等錯誤。
Spring 2.0 透過 Schema 與 @AspectJ 大幅簡化 AOP 配置,消除手動代理 Bean 定義,讓開發者專注於切面邏輯而非基礎設施。實際專案中建議統一採用 @AspectJ 風格,代碼與配置解耦度最高。