Spring AOP 学习例子

工作忙,时间紧,不过事情再多,学习是必须的。记得以前的部门老大说过:“开发人员不可能一天到晚只有工作,肯定是需要自我学习。第一:为了更充实自己,保持进步状态。第二:为了提升技术,提高开发能力。第三:保持程序员对技术和学习的热情,工作的激情。程序员还是需要把基础打扎实,修炼自己的内功。” 所以赶紧把学习的东西总结一下,加深印象。之前有说了下AOP的原理 (http://www.cnblogs.com/yanbincn/archive/2012/06/01/2530377.html) 。基于代理模式,了解了jdk动态代理和cglib的用法。但是在真正的使用AOP的时候,不可能写这么厚重的方法。

Spring有两大核心,IOC和AOP。IOC在java web项目中无时无刻不在使用。然而AOP用的比较少,的确也是一般的项目用的场所不多。事务控制基本都用,但却是Spring封装的不需要我们再去实现,但Spring的AOP远不止这些,不能因为项目中没有使用,而不去学习及理解。我觉得这是作为一个java web软件开发人员必须具备的技能。业内很多将AOP应用在日志记录上,可惜我们项目没这么做,后面需要学习下。在这先把Spring AOP的基本用法,在脑子里理一边,做一次积累。

1、概念术语

在开始之前,需要理解Spring aop 的一些基本的概念术语(总结的个人理解,并非Spring官方定义):

  • 切面(aspect):用来切插业务方法的类。
  • 连接点(joinpoint):是切面类和业务类的连接点,其实就是封装了业务方法的一些基本属性,作为通知的参数来解析。
  • 通知(advice):在切面类中,声明对业务方法做额外处理的方法。
  • 切入点(pointcut):业务类中指定的方法,作为切面切入的点。其实就是指定某个方法作为切面切的地方。
  • 目标对象(target object):被代理对象。
  • AOP代理(aop proxy):代理对象。

AOP通知类型:

  • 前置通知(before advice):在切入点之前执行。
  • 后置通知(after returning advice):在切入点执行完成后,执行通知。
  • 环绕通知(around advice):包围切入点,调用方法前后完成自定义行为。
  • 异常通知(after throwing advice):在切入点抛出异常后,执行通知。

2、Spring AOP环境

要在项目中使用Spring AOP 则需要在项目中导入除了spring jar包之外,还有aspectjweaver.jar,aopalliance.jar ,asm.jar 和cglib.jar 。

好了,前提工作准备完成,Spring 提供了很多的实现AOP的方式,在学习过程中,循序渐进。进行Spring 接口方式,schema配置方式和注解的三种方式进行学习。好了废话不多说了,开始spring aop学习之旅:

3、看看下面例子

@Aspect
@Component("DataCRUDAspect")
public class DataCRUDAspect {
	Logger logger = Logger.getLogger(getClass());

	@Before("execution(* com.kimnote.service.*.create(..))")
	public void create(JoinPoint joinPoint) {
		logger.error("create() is running!");
		try {
			Object[] args = joinPoint.getArgs();
			for (Object o : args) {
				if (o instanceof BasicModel) {
					BasicModel model = (BasicModel) o;
					if (model.getId() != null) {
						throw new IllegalStateException(
								"id is not empty");
					} else if (!model.validateInsert()) {
						throw new IllegalStateException(
								model.getValidateMessage());
					}
				} else {
					throw new IllegalStateException("Unknown error!");
				}
			}
		} catch (Exception e) {
			logger.error("", e);
			throw new IllegalStateException("Unknown error!");
		}
	}

	@Before("execution(* com.kimnote.service.*.update(..))")
	public void update(JoinPoint joinPoint) {
		logger.error("update() is running!");
		try {
			Object[] args = joinPoint.getArgs();
			for (Object o : args) {
				if (o instanceof BasicModel) {
					BasicModel model = (BasicModel) o;
					if (model.getId() == null) {
						throw new IllegalStateException(
								"ID is Empty");
					} else if (!model.validateUpdate()) {
						throw new IllegalStateException(
								model.getValidateMessage());
					}
				} else {
					throw new IllegalStateException("Unknown error!");
				}
			}
		} catch (Exception e) {
			logger.error("", e);
			throw new IllegalStateException("Unknown error!");
		}
	}

	@After("execution(* com.kimnote.service.*.delete(..))")
	public void delete(JoinPoint joinPoint) {
		logger.error("delete() is running!");
		Object[] args = joinPoint.getArgs();
		if (args == null || args[0] == null) {
			throw new IllegalStateException("ID is Empty");
		}
	}

	@After("execution(* com.kimnote.service.*.read(..))")
	public void read(JoinPoint joinPoint) {
		logger.error("read() is running!");
		Object[] args = joinPoint.getArgs();
		if (args == null || args[0] == null) {
			throw new IllegalStateException("ID is Empty");
		}
	}

	@After("execution(* com.kimnote.service.*.getListByCond(..))")
	public void getListByCond(JoinPoint joinPoint) {
		logger.error("getListByCond() is running!");
		Object[] args = joinPoint.getArgs();
		if (args == null || args[0] == null) {
			throw new IllegalStateException("condition is empty!.");
		}
	}

	@After("execution(* com.kimnote.service.*.getListByCond(..))")
	public void getCountByCond(JoinPoint joinPoint) {
		logger.error("getCountByCond() is running!");
		Object[] args = joinPoint.getArgs();
		if (args == null || args[0] == null) {
			throw new IllegalStateException("condition is empty!.");
		}
	}
}

 

查看service接口

public interface ServiceKeyService extends BasicService {

	public boolean create(ServiceConfig serviceConfig);

	public ServiceConfig read(Integer id);

	public boolean update(ServiceConfig serviceConfig);

	public List getListByCond(Map<String, String> map);

	public Integer getCountByCond(Map<String, String> map);

}

这样就每个service执行之前做必要的检查,以免给dao层增加不必要的判断。

参考资料:

http://outofmemory.cn/code-snippet/3762/Spring-AOP-learn-example

http://blog.csdn.net/wangpeng047/article/details/8560694

发表评论

电子邮件地址不会被公开。 必填项已用 * 标注

您可以使用这些 HTML 标签和属性: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>