日期:2014-05-17  浏览次数:20894 次

Spring AOP 概念理解及@AspectJ支持

为了更好的理解Spring简介一文http://quicker.iteye.com/blog/670056中的概念,下面通过一些示例来加以说明。

首先要理解代理模式:有静态代理和动态代理

有关代理模式相关文章:

http://quicker.iteye.com/blog/571494

http://quicker.iteye.com/blog/571493

下面先给出静态代理的代码。

public interface UserManager {

	public void add(String name, String password);
	public void del(String id);
	public void modify(int id ,String name, String password);
}

?

public class UserManagerImpl implements UserManager {

	public void add(String name, String password) {

	}

	public void del(String id) {

	}

	public void modify(int id, String name, String password) {

	}

}

?

public class UserManagerProxy implements UserManager {

	private UserManager userManager ;
	public void add(String name, String password) {
		check();
		userManager.add(name, password);
	}

	public void del(String id) {
		check();
		userManager.del(id);
	}

	public void modify(int id, String name, String password) {
		check();
		userManager.modify(id, name, password);
	}
	
	public void check(){
		System.out.println("check security");
	}
	
	public void setUserManager(UserManager userManager){
		this.userManager = userManager;
	}

	public static void main(String[] args) {
		UserManagerProxy proxy = new UserManagerProxy();
		proxy.setUserManager(new UserManagerImpl());
		proxy.add("name","pwd");
	}
}

?

上例中代理类控制在UserManagerImpl进行操作前对用户进行检查即check()方法。

?

那么下面用Spring Aop来实现。

配置步骤:

通过示例,理解概念
一、创建普通JAVA项目,加入用户自定义的包:
包里有spring.jar,log4j-1.2.15.jar,commons-logging.jar
二、拷贝log4j.properties和applicationContext.xml到src目录
三、创建代码其中UserManager,UserManagerImpl类是用户管理接口及实现类
    MySecurityManager,MySecurityManagerImpl类是包含安全检查方法的接口及实现类。
四、要启用@AspectJ支持,@AspectJ使用了Java 5的注解,必须是Java 5及后的才能使用。
	在applicationContext.xml加入:<aop:aspectj-autoproxy/>启用@AspectJ支持。
	并在我们的用户自定义包中要加入aspectjrt.jar,aspectjweaver.jar,这两个包可以spring发布包
	的lib\aspectj下找到。
五、声明一个切面:
	在类的定义前加入@Aspect,并引入包 org.aspectj.lang.annotation.Aspect
	@Aspect我们把用Aspect注解的类就叫切面

?切面如:

package com.lwf.aop;

import org.aspectj.lang.annotation.Aspect;

@Aspect
public class MySecurityManagerImpl implements MySecurityManager {

	public void checkSecurity() {
		System.out.println("User security Check");
	}

}

?

六、声明一个切入点(pointcut)
在前面我们提到,切入点决定了连接点关注的内容,使得我们可以控制通知什么时候执行。
Spring AOP只支持Spring bean的方法执行连接点。所以你可以把切入点看做是Spring bean上方法执行的匹配。
一个切入点声明有两个部分:一个包含名字和任意参数的签名,还有一个切入点表达式,该表达式决定了我们关注那个方法的执行。
在@AspectJ注解风格的AOP中,一个切入点签名通过一个普通的方法定义来提供,
并且切入点表达式使用@Pointcut注解来表示(作为切入点签名的方法必须返回void 类型)。 

??如:

package com.lwf.aop;

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
/*
 * 定义切面
 */
@Aspect
public class MySecurityManagerImpl implements MySecurityManager {

	/*
	 * 定义切入点,该方法返回值为void,该方法只是一个标识,就象配置文件的id
	 * 切入点的内容是一个表达式,来描述切入哪些对象的哪些方法
	 * ("excute (*add*(..))")切入点表达表示将要切入所有以add开头的方法,该方法可带任意个数的参数
	 */
	@Pointcut ("execution (* add*(..))")
	public void addAllMethod(){};
	
	public void checkSecurity() {
		System.out.println("User security Check");
	}

}

?

七、声明通知
通知是跟一个切入点表达式关联起来的,并且在切入点匹配的方法执行之前或者之后或者前后运行。 
切入点表达式可能是指向已命名的切入点的简单引用或者是一个已经声明过的切入点表达式。
通知有:前置通知,后置通知,异常通知,最终通知,环绕通知

?如:我们声明一个前置通知

package com.lwf.aop;

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
/*
 * 定义切面
 */
@Aspect
public class MySecurityManagerImpl implements MySecurityManager {

	/*
	 * 定义切入点,该方法返回值为void,该方法只是一个标识,就象配置文件的id
	 * 切入点的内容是一个表达式,来描述切入哪些对象的哪些方法
	 * ("excute (*add*(..))")切入点表达表示将要切入所有以add开头的方法,该方法可带任意个数的参数
	 */
	@Pointcut ("execution (* add*(..))")
	public void addAllMethod