分享一个自己写的最为简单的Spring AOP的应用,其实,本人也是学习Spring不久,只是把一些个人的理解分享下,供参考。可能很多人刚开始不太理解到底啥是AOP,其实它也是相对OOP来说的,类似OOP其实也是一种编程思想吧。本人暂且把Spring 中的AOP理解成一种方法的拦截器(可能有所片面,主要是方便理解)。
个人通俗理解,就好比你去自动取款机取钱,边上装了个摄像头在监视着。你取你的钱,不用管那摄像头干嘛,只是对于摄像头来说,已经把你取钱的这一过程记录了下来。你取钱的这一过程我们可以从OOP角度分析,而对于摄像头来说,就是从AOP角度去分析了。反映到我下面要讲的示例就是系统日志的记录。
我要讲的示例大致是这样的,从OOP角度分析,就是说现在有一个User对象,然后你要调用业务逻辑实现去保存(或者其他行为)这个User对象,或者说是做持久化操作,把User对象相关信息写进数据库。那么从AOP角度来看,就是在你进行保存对象这一行为发生的时候进行日志记录。就是说,你在进行业务操作的时候,不需要去关心系统背后到底做了啥,Spring AOP它已经帮你搞定了。
(图一、个人对于OOP与AOP在本人示例中的理解)
上图说表示的东西是个人的理解理解,纵向为主业务逻辑这里表现为对User对象的持久化操作,横向为AOP实现,这里表现为系统日志记录。
以下是代码具体实现:(采用Spring2.5,Myeclipse6.5)
- (一)、从AOP角度分析:
- package org.wiki.spring.aspect;
- import org.aspectj.lang.JoinPoint;
- /**
- * 定义切面类,将系统中的横切性关注点模块化
- *
- * @author Wiki.M
- *
- */
- public class Aspect {
- /**
- * 定义advice,即切面类中方法具体实现, 这里主要是用于记录日志,只做简单处理。
- *
- * @param joinPoint,可以取得被拦截方法的一些信息
- */
- public void logging(JoinPoint joinPoint) {
- //得到被拦截方法参数,并打印
- Object[] args = joinPoint.getArgs();
- for (int i = 0; i < args.length; i++) {
- System.out.println("method arg" + i + " -- " + args[i]);
- }
- //得到被拦截方法签名
- System.out.println(joinPoint.getSignature().getName());
- //记录系统日志具体实现
- System.out.println("----logging-----");
- }
- }
- (二)从DAO,数据持久化角度分析:
- package org.wiki.spring.dao;
- import org.wiki.spring.domain.User;
- /**
- * 定义IUserDAO接口,目的是为了灵活实现UserDAO不同的操作。
- * @author Wiki.M
- *
- */
- public interface IUserDAO {
- public void addUser(User user);
- public void deleteUser(int id);
- public void updateUser(int id);
- }
- //==================================================
- package org.wiki.spring.dao;
- import org.wiki.spring.domain.User;
- /**
- * IUserDAO接口的具体实现,这里只做简单处理
- * @author Wiki.M
- *
- */
- public class UserDAOImpl implements IUserDAO {
- @Override
- public void addUser(User user) {
- System.out.println("----addUser----");
- }
- @Override
- public void deleteUser(int id) {
- System.out.println("----deleteUser----");
- }
- @Override
- public void updateUser(int id) {
- System.out.println("----updateUser----");
- }
- }
- (三)域模型分析
- package org.wiki.spring.domain;
- /**
- * 领域模型User
- * @author Wiki.M
- *
- */
- public class User {
- private int id;
- private String name;
- private String password;
- public int getId() {
- return id;
- }
- public void setId(int id) {
- this.id = id;
- }
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- public String getPassword() {
- return password;
- }
- public void setPassword(String password) {
- this.password = password;
- }
- }
- (四)、从业务层分析:
- package org.wiki.spring.service;
- import org.wiki.spring.domain.User;
- /**
- * 定义User业务逻辑相关的一个接口,
- * 目的是为了在客户端自由调用接口实现
- * @author Wiki.M
- *
- */
- public interface IUserService {
- public void saveUser(User user);
- public void deleteUser(int id);
- public void updateUser(int id);
- }
- //=========================================
- package org.wiki.spring.service;
- import org.wiki.spring.dao.IUserDAO;
- import org.wiki.spring.domain.User;
- /**
- * 业务逻辑接口IUserService的具体实现
- * @author Wiki.M
- *
- */
- public class UserServiceImpl implements IUserService {
- private IUserDAO userDAO;
- public void setUserDAO(IUserDAO userDAO) {
- this.userDAO = userDAO;
- }
- @Override
- public void deleteUser(int id) {
- userDAO.deleteUser(id);
- }
- @Override
- public void saveUser(User user) {
- userDAO.addUser(user);
- }
- @Override
- public void updateUser(int id) {
- userDAO.updateUser(id);
- }
- }
- (五)从客户端调用分析:
- package org.wiki.spring.client;
- import org.springframework.beans.factory.BeanFactory;
- import org.springframework.context.support.ClassPathXmlApplicationContext;
- import org.wiki.spring.domain.User;
- import org.wiki.spring.service.IUserService;
- public class Client {
- /**
- * 客户端调用,用于测试
- * @param args
- */
- public static void main(String[] args){
- BeanFactory factory = new ClassPathXmlApplicationContext("*.xml");
- //得到UserService具体实现,用于操作业务逻辑
- IUserService userService = (IUserService)factory.getBean("userServiceImpl");
- User user = new User();
- user.setId(1);
- user.setName("Wiki");
- user.setPassword("123");
- //测试1,记录日志
- userService.saveUser(user);
- //测试2,记录日志
- userService.deleteUser(1);
- }
- }
(一)、从AOP角度分析:
package org.wiki.spring.aspect;
import org.aspectj.lang.JoinPoint;
/**
* 定义切面类,将系统中的横切性关注点模块化
*
* @author Wiki.M
*
*/
public class Aspect {
/**
* 定义advice,即切面类中方法具体实现,这里主要是用于记录日志,只做简单处理。
*
* @param joinPoint,可以取得被拦截方法的一些信息
*/
public void logging(JoinPoint joinPoint) {
//得到被拦截方法参数,并打印
Object[] args = joinPoint.getArgs();
for (int i = 0; i < args.length; i++) {
System.out.println("method arg" + i + " -- " +args[i]);
}
//得到被拦截方法签名
System.out.println(joinPoint.getSignature().getName());
//记录系统日志具体实现
System.out.println("----logging-----");
}
}
(二)从DAO,数据持久化角度分析:
packageorg.wiki.spring.dao;
importorg.wiki.spring.domain.User;
/**
* 定义IUserDAO接口,目的是为了灵活实现UserDAO不同的操作。
* @author Wiki.M
*
*/
public interface IUserDAO {
public void addUser(User user);
public void deleteUser(int id);
public void updateUser(int id);
}
//==================================================
packageorg.wiki.spring.dao;
importorg.wiki.spring.domain.User;
/**
* IUserDAO接口的具体实现,这里只做简单处理
* @author Wiki.M
*
*/
public class UserDAOImplimplements IUserDAO {
@Override
public void addUser(User user) {
System.out.println("----addUser----");
}
@Override
public void deleteUser(int id) {
System.out.println("----deleteUser----");
}
@Override
public void updateUser(int id) {
System.out.println("----updateUser----");
}
}
(三)域模型分析
packageorg.wiki.spring.domain;
/**
* 领域模型User
* @author Wiki.M
*
*/
public class User {
private int id;
private String name;
private String password;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
(四)、从业务层分析:
packageorg.wiki.spring.service;
importorg.wiki.spring.domain.User;
/**
* 定义User业务逻辑相关的一个接口,
* 目的是为了在客户端自由调用接口实现
* @author Wiki.M
*
*/
public interface IUserService {
public void saveUser(User user);
public void deleteUser(int id);
public void updateUser(int id);
}
//=========================================
packageorg.wiki.spring.service;
importorg.wiki.spring.dao.IUserDAO;
importorg.wiki.spring.domain.User;
/**
* 业务逻辑接口IUserService的具体实现
* @author Wiki.M
*
*/
public class UserServiceImplimplements IUserService {
private IUserDAO userDAO;
public void setUserDAO(IUserDAO userDAO) {
this.userDAO = userDAO;
}
@Override
public void deleteUser(int id) {
userDAO.deleteUser(id);
}
@Override
public void saveUser(User user) {
userDAO.addUser(user);
}
@Override
public void updateUser(int id) {
userDAO.updateUser(id);
}
}
(五)从客户端调用分析:
packageorg.wiki.spring.client;
importorg.springframework.beans.factory.BeanFactory;
import org.springframework.context.support.ClassPathXmlApplicationContext;
importorg.wiki.spring.domain.User;
importorg.wiki.spring.service.IUserService;
public class Client {
/**
* 客户端调用,用于测试
* @param args
*/
public static void main(String[] args){
BeanFactory factory = newClassPathXmlApplicationContext("*.xml");
//得到UserService具体实现,用于操作业务逻辑
IUserService userService =(IUserService)factory.getBean("userServiceImpl");
User user = new User();
user.setId(1);
user.setName("Wiki");
user.setPassword("123");
//测试1,记录日志
userService.saveUser(user);
//测试2,记录日志
userService.deleteUser(1);
}
}
Spring配置文件:
- <?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:aop="http://www.springframework.org/schema/aop"
- xmlns:tx="http://www.springframework.org/schema/tx"
- xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
- http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
- http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd">
- <!-- 配置UserDAOImpl -->
- <bean id="userDAO" class="org.wiki.spring.dao.UserDAOImpl"/>
- <!-- 配置UserServiceImpl -->
- <bean id="userServiceImpl"
- class="org.wiki.spring.service.UserServiceImpl">
- <!-- 注入userDAO,实际为UserDAOImpl,即对数据持久化的具体实现 -->
- <property name="userDAO" ref="userDAO" />
- </bean>
- <!-- 配置aspect切面类 -->
- <bean id="userAspect" class="org.wiki.spring.aspect.Aspect" />
- <!-- 配置AOP -->
- <aop:config>
- <!-- 配置aspect切面类 -->
- <aop:aspect ref="userAspect">
- <!-- 配置pointcut,即切入点,对哪些类的哪些方法起到AOP的作用 -->
- <aop:pointcut id="userServiceMethods"
- expression="execution(* org.wiki.spring.service.UserServiceImpl.*(..))" />
- <!-- 配置advice,即Aspect类中的logging()方法,这里采用在业务方法执行前进行拦截 -->
- <aop:before method="logging" pointcut-ref="userServiceMethods" />
- </aop:aspect>
- </aop:config>
- </beans>
<?xmlversion="1.0" encoding="UTF-8"?>
<beansxmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop-2.0.xsd
http://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx-2.0.xsd">
<!-- 配置UserDAOImpl -->
<bean id="userDAO"class="org.wiki.spring.dao.UserDAOImpl"/>
<!-- 配置UserServiceImpl -->
<bean id="userServiceImpl"
class="org.wiki.spring.service.UserServiceImpl">
<!-- 注入userDAO,实际为UserDAOImpl,即对数据持久化的具体实现 -->
<property name="userDAO" ref="userDAO" />
</bean>
<!-- 配置aspect切面类 -->
<bean id="userAspect"class="org.wiki.spring.aspect.Aspect" />
<!-- 配置AOP -->
<aop:config>
<!-- 配置aspect切面类 -->
<aop:aspect ref="userAspect">
<!-- 配置pointcut,即切入点,对哪些类的哪些方法起到AOP的作用 -->
<aop:pointcut id="userServiceMethods"
expression="execution(*org.wiki.spring.service.UserServiceImpl.*(..))" />
<!-- 配置advice,即Aspect类中的logging()方法,这里采用在业务方法执行前进行拦截 -->
<aop:before method="logging"pointcut-ref="userServiceMethods" />
</aop:aspect>
</aop:config>
</beans>
可能用到的Jar包: commons-logging.jar, log4j.jar,spring.jar, aspectjrt.jar, aspectjweaver.jar