首先我们可以新建一个包,目录结构如下:
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类接口:
package com.hqj.aop;
public interface UserDao {
public void save(User user);
}
User类接口类实现:
package com.hqj.aop;
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函数:
package com.hqj.aop;
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;