首先我們可以建立一個包,目錄結構如下:
User類:
package com.hqj.aop;
public class User {
@Override
public String toString() {
return "User [username=" + username + ", password=" + password + "]";
}
private String username;
private String password;
public String getUsername() {
return username;
public void setUsername(String username) {
this.username = username;
public String getPassword() {
return password;
public void setPassword(String password) {
this.password = password;
}
User類接口:
public interface UserDao {
public void save(User user);
User類接口類實作:
public class UserDaoImpl implements UserDao {
public void save(User user) {
System.out.println("User is saved successfully");
LogInterceptor類:
public class LogInterceptor {
public void before() {
System.out.println("method state");
public void after() {
System.out.println("method after");
public void AfterReturning() {
System.out.println("method AfterReturning");
public void AfterThrowing() {
System.out.println("method AfterThrowing");
AOP XML檔案:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.1.xsd
">
<bean id="user" class="com.hqj.aop.User">
<property name="username" value="Tim"></property>
<property name="password" value="123"></property>
</bean>
<!-- 配置Bean -->
<bean id="UserDaoImpl" class="com.hqj.aop.UserDaoImpl"></bean>
<!-- 配置切面的Bean -->
<!-- 也就是要記錄的資料的地方 (比如錯誤日志) -->
<bean id="logInterceptor" class="com.hqj.aop.LogInterceptor"></bean>
<!-- 配置AOP -->
<aop:config proxy-target-class="true">
<!-- 配置切點表達式 -->
<aop:pointcut expression="execution(* com.hqj.aop.UserDao.save(..))"
id="servicePointcut" />
<!-- 配置切面以及通知(指向切面,比如錯誤日志) -->
<aop:aspect id="logAspect" ref="logInterceptor">
<!-- method寫切面中(比如錯誤日志)的方法名稱 -->
<aop:before method="before" pointcut-ref="servicePointcut" />
<aop:after method="after" pointcut-ref="servicePointcut" />
</aop:aspect>
</aop:config>
</beans>
測試MAIN函數:
import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Main {
public static void main(String[] args) {
// TODO Auto-generated method stub
ApplicationContext ctx = new ClassPathXmlApplicationContext("aop.xml");
UserDaoImpl UDI = (UserDaoImpl) ctx.getBean("UserDaoImpl");
User user = (User) ctx.getBean("user");
UDI.save(user);
運作結果:
常見錯誤:
com.sun.proxy.$Proxy2 cannot be cast to com.hqj.aop.UserDaoImpl
at com.hqj.aop.Main.main(Main.java:12)
解決辦法:
<tx:annotation-driven transaction-manager="transactionManager"
proxy-target-class="true"/>
注意:proxy-target-class屬性值決定是基于接口的還是基于類的代理被建立。如果proxy-target-class 屬性值被設定為true,那麼基于類的代理将起作用(這時需要cglib庫)。如果proxy-target-class屬值被設定為false或者這個屬性被省略,那麼标準的JDK 基于接口的代理将起作用。
即使你未聲明 proxy-target-class="true" ,但運作類沒有繼承接口,spring也會自動使用CGLIB代理。高版本spring自動根據運作類選擇 JDK 或 CGLIB 代理package com.hqj.aop;