Spring 入门 AOP
通过一个小例子演视怎么使用 Spring 现实面向切面编程。
导入 Spring 所需要的包
spring-framework-2.5.6 版需要导入以下包:
1.----- spring.jar
2.----- commons-logging.jar
3.----- aspectjrt.jar
4.----- aspectjweaver.jar
5.----- cglib-nodep-2.1_3.jar
spring-framework-3.2.4 版需要导入以下包:
1.----- spring-core-3.2.4.RELEASE.jar
2.----- spring-beans-3.2.4.RELEASE.jar
3.----- spring-context-3.2.4.RELEASE.jar
4.----- spring-expression-3.2.4.RELEASE.jar
5.----- commons-logging.jar
6.----- aspectjweaver.jar
7.----- aspectjrt.jar
8.----- aopalliance.jar(spring项目里不提供,要到网上下)
代码:
Book.java:
public class Book { private int id; private String name; //省略get set方法.... }
BookService.java:
public class BookService { public void save(Book book){ System.out.println("save:"+book.getName()); } }
main方法:
public static void main(String[] args) { ApplicationContext appctx = new ClassPathXmlApplicationContext("applicationContext.xml"); Book b = (Book)appctx.getBean("book"); b.setName("j2ee"); BookService bs = (BookService)appctx.getBean("bookService"); //调用BookService的save方法。 bs.save(b); ((ClassPathXmlApplicationContext)appctx).close(); }
通过使用Spring AOP 在调用BookService的save方法前后各加上一些业务(如记录日志,时间等等)方便起见,这里简单输出两句话。
使用配置文件配置AOP(Schema)
添加切面类 Log.java :
public class Log { //在目标方法执行前调用此方法,JoinPoint:封装了目标方法的一些信息(如类名,参数等等) public void before(JoinPoint jp){ System.out.println(jp.getSignature().getName()+":开始执行----------"); // 获取被代理对象 System.out.println("被代理对象:"+jp.getTarget().getClass()); // 获取被代理方法 System.out.println("被代理方法:"+jp.getSignature()); // 获取方法参数 System.out.println("方法参数:"+jp.getArgs()); } //在目标方法执行完后调用此方法,Object rn:目标方法的返回值(void为null) public void afterreturning(JoinPoint jp,Object rn){ System.out.println(jp.getSignature().getName()+":执行完毕----------"); System.out.println(rn); } }
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" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd"> <bean id="book" class="com.startspring.Book" /> <bean id="bookService" class="com.startspring.BookService" /> <bean id="log" class="com.startspring.aop.Log" /> <aop:config> <!-- 指定切入点 --> <aop:pointcut id="bookSave" expression="execution(public void com.startspring.BookService.save(com.startspring.Book))" /> <!-- 指定切面 --> <aop:aspect id="aspect" ref="log"> <!-- 前置通知(增强):指明切入点方法执行前执行 “before”方法--> <aop:before method="before" pointcut-ref="bookSave"/> <!-- 后置通知(增强):指明切入点方法完成后执行 “afterreturning”方法,参数rn是目标方法的返回值--> <aop:after-returning method="afterreturning" pointcut-ref="bookSave" returning="rn"/> </aop:aspect> </aop:config> </beans>
注:要使用aop:标签要先引入aop命名空间(第4、7、8行)
使注解配置AOP(Annotation)
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: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-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd"> <context:component-scan base-package="com.startspring" /> <!-- 要使用aspect的注解,先要在配置文件中添加如下代码:启动自动匹配注解类--> <aop:aspectj-autoproxy /> </beans>
添加切面类 Log.java :
@Component @Aspect //声明该类为切面类 public class Log { //前置通知(增强):指明切入点方法执行前执行该方法 //后面参数指定了插入点 @Before("execution(public void com.startspring.BookService.save(com.startspring.Book))") public void before(JoinPoint jp){ System.out.println(jp.getSignature().getName()+":开始执行----------"); // 获取被代理对象 System.out.println("被代理对象:"+jp.getTarget().getClass()); // 获取被代理方法 System.out.println("被代理方法:"+jp.getSignature()); // 获取方法参数 System.out.println("方法参数:"+jp.getArgs()); } //后置通知(增强):指明切入点方法执行完毕执行该方法 //returning="rn" :声明参数rn是目标方法的返回值(void为null) @AfterReturning(returning="rn",value="execution(public void com.startspring.BookService.save(com.startspring.Book))") public void afterreturning(JoinPoint jp,Object rn){ System.out.println(jp.getSignature().getName()+":开始完毕----------"); System.out.println(rn); } }
这里Bean的声明也采用了注解,要在Book.java和BookService.java里添加相应的注解。或在配置文件中写<bean>也是可以的。
通过现实接口配置AOP
添加切面类 Log.java :
/* * 通过实现 MethodBeforeAdvice 实现前置处理。AfterReturningAdvice:后置处理。 * 分别重写方法:before,afterReturning */ public class Log implements MethodBeforeAdvice,AfterReturningAdvice{ //method:表示切入点方法.args:切入点方法的参数.target:目标对象 public void before(Method method, Object[] args, Object target)throws Throwable { System.out.println(method.getName()+":开始执行----------"); // 获取被代理对象 System.out.println("被代理对象:"+target); // 获取被代理方法 System.out.println("被代理方法:"+method); // 获取方法参数 System.out.println("方法参数:"+args); } //result表示目标方法的返回值 public void afterReturning(Object result, Method method, Object[] args,Object target) throws Throwable { System.out.println(method.getName()+":执行完毕----------"); System.out.println(result); } }
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" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd"> <bean id="book" class="com.startspring.Book" /> <bean id="bookService" class="com.startspring.BookService" /> <bean id="log" class="com.startspring.aop.Log" /> <aop:config> <!-- 指定切入点 --> <aop:pointcut id="bookSave" expression="execution(public void com.startspring.BookService.save(com.startspring.Book))" /> <!-- advice-ref:指定切面 pointcut-ref:指定切入点--> <aop:advisor advice-ref="log" pointcut-ref="bookSave"/> </aop:config> </beans>