`

一步步的学习Spring(三)

阅读更多

这节来学习下AOP,常说的面向切面编程,面向切面编程能提取公用的业务组件做为切面,从而减少实际业务代码的工作量,AOP经常分离的几个切面有:日志管理模块,安全管理模块,事务管理模块。

 

下面来看下简单的一个日志记录切面(方法前置和后置通知):

 

先来定义下两个通知:

 

前置通知:

 

 

package aop;


import java.lang.reflect.Method;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.aop.MethodBeforeAdvice;

/**
* @ClassName: LogBeforeAdvice
* @Description: 日志通知
* @author sunrain  
* @date 2011-1-3
*/
public class LogBeforeAdvice implements MethodBeforeAdvice {
	private static final Log log = LogFactory.getLog(LogBeforeAdvice.class);
	/* (非 Javadoc)
	* <p>Title: before</p>
	* <p>Description:定义调用方法前的通知 </p>
	* @param method
	* @param arg1
	* @param target
	* @throws Throwable
	* @see org.springframework.aop.MethodBeforeAdvice#before(java.lang.reflect.Method, java.lang.Object[], java.lang.Object)
	*/
	public void before(Method method, Object[] arg1, Object target)
			throws Throwable {
		
		log.info(target.getClass().getName()+"’s "+method.getName()+" invoked");
	}

}

 

后置通知:

 

 

package aop;


import java.lang.reflect.Method;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.aop.AfterReturningAdvice;;


/**
* @ClassName: LogAfterAdvice
* @Description: 日志通知
* @author sunrain  
* @date 2011-1-3
*/
public class LogAfterAdvice implements  AfterReturningAdvice {
	private static final Log log = LogFactory.getLog(LogAfterAdvice.class);
	
	public void afterReturning(Object arg0, Method method, Object[] arg2,
			Object target) throws Throwable {
		log.info(target.getClass().getName()+"’s "+method.getName()+" invoked");
		
	}

}

 

 

来看看通知是怎么实现通知拦截的:

 

 

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">

<beans>
	<bean id="helloWorld" class="HelloWorldServiceImpl">
		<property name="name">
			<value>sunrain</value>
		</property>
	</bean>
	
	<bean id="personTask" class="ioc.TaskImpl">
		<constructor-arg>
			<value>sunrain</value>
		</constructor-arg>
		<property name="living"  ref="person"></property>
	</bean>
	
	<bean id="dogTask" class="ioc.TaskImpl">
		<constructor-arg>
			<value>tt</value>
		</constructor-arg>
		<property name="living" ref="dog"></property>
	</bean>
	
	<bean id="person" class="ioc.Person">
		
	</bean>
	
	<bean id="dog" class="ioc.Dog">
		
	</bean>
	
	<bean id="logBeforeAdvice"  class="aop.LogBeforeAdvice"></bean>
	
	<bean id="logAfterAdvice"  class="aop.LogAfterAdvice"></bean>
	
	<bean id="dogAdviceTask"  class="org.springframework.aop.framework.ProxyFactoryBean">
		<property name="proxyInterfaces">
			<list>
				<value>ioc.Task</value>
			</list>
		</property>
		<property name="interceptorNames">
			<list>
				<value>logBeforeAdvice</value>
				<value>logAfterAdvice</value>
			</list>
		</property>
		<property name="target">
			<ref bean="dogTask"/>
		</property>
	</bean>
</beans>

 

这里借助了代理bean ,来代理Task接口,下面写个测试类:

 

 

package aop;

import ioc.Task;

import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource;

public class AdviceTest {

	/**
	 * @Title: main
	 * @Description: AOP 方法前置通知测试类
	 * @param @param args    设定文件
	 * @return void    返回类型
	 * @throws
	 */
	public static void main(String[] args) {
		Resource res = new FileSystemResource("beans.xml");
		BeanFactory factory = new XmlBeanFactory(res);
		
		Task t = (Task)factory.getBean("dogAdviceTask");
		t.say();
	}

}
 

 

对AOP理解的还不够,会慢慢更新的,看下日志:

 

 

0103/16:44:17 <INFO > [org.springframework.core.CollectionFactory 66] JDK 1.4+ collections available
0103/16:44:17 <INFO > [org.springframework.core.CollectionFactory 71] Commons Collections 3.x available
0103/16:44:17 <INFO > [org.springframework.beans.factory.xml.XmlBeanDefinitionReader 163] Loading XML bean definitions from file [G:\workspace\SpringStudy\beans.xml]
0103/16:44:18 <INFO > [org.springframework.aop.framework.DefaultAopProxyFactory 64] CGLIB2 available: proxyTargetClass feature enabled
0103/16:44:18 <INFO > [aop.LogBeforeAdvice 30] ioc.TaskImpl’s say invoked
0103/16:44:18 <INFO > [ioc.TaskImpl 32] tt say :汪汪汪
0103/16:44:18 <INFO > [aop.LogAfterAdvice 22] ioc.TaskImpl’s say invoked
 

 

 

 

下面介绍下用另外一种方式来实现这个:MethodInterceptor

 

 

package aop;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
* @ClassName: LogAdvice
* @Description: 日志前后置通知模拟
* @author sunrain  
* @date 2011-1-3
*/
public class LogAdvice implements MethodInterceptor {
	private static final Log log = LogFactory.getLog(LogAdvice.class);
	public Object invoke(MethodInvocation invocation) throws Throwable {
		log.info(invocation.getThis().getClass().getName()+"’s  before "+invocation.getMethod().getName()+" invoked");
		invocation.proceed();
		log.info(invocation.getThis().getClass().getName()+"’s  after "+invocation.getMethod().getName()+" invoked");
		return null;
	}

}
 

 

改下xml配置:

 

 

<bean id="logAdvice"  class="aop.LogAdvice"></bean>
	<bean id="dogAdviceTask1"  class="org.springframework.aop.framework.ProxyFactoryBean">
		<property name="proxyInterfaces">
			<list>
				<value>ioc.Task</value>
			</list>
		</property>
		<property name="interceptorNames">
			<list>
				<value>logAdvice</value>
			</list>
		</property>
		<property name="target">
			<ref bean="dogTask"/>
		</property>
	</bean>
 

 

在测试类AdviceTest.java中加个调试吧

 

 

package aop;

import ioc.Task;

import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource;

public class AdviceTest {

	/**
	 * @Title: main
	 * @Description: AOP 方法前置通知测试类
	 * @param @param args    设定文件
	 * @return void    返回类型
	 * @throws
	 */
	public static void main(String[] args) {
		Resource res = new FileSystemResource("beans.xml");
		BeanFactory factory = new XmlBeanFactory(res);
		
		Task t = (Task)factory.getBean("dogAdviceTask");
		t.say();
		
		t = (Task)factory.getBean("dogAdviceTask1");
		t.say();
	}

}
 

 

看下日志:

 

 

0103/17:37:47 <INFO > [org.springframework.core.CollectionFactory 66] JDK 1.4+ collections available
0103/17:37:47 <INFO > [org.springframework.core.CollectionFactory 71] Commons Collections 3.x available
0103/17:37:47 <INFO > [org.springframework.beans.factory.xml.XmlBeanDefinitionReader 163] Loading XML bean definitions from file [G:\workspace\SpringStudy\beans.xml]
0103/17:37:47 <INFO > [org.springframework.aop.framework.DefaultAopProxyFactory 64] CGLIB2 available: proxyTargetClass feature enabled
0103/17:37:47 <INFO > [aop.LogBeforeAdvice 30] ioc.TaskImpl’s say invoked
0103/17:37:47 <INFO > [ioc.TaskImpl 32] tt say :汪汪汪
0103/17:37:47 <INFO > [aop.LogAfterAdvice 22] ioc.TaskImpl’s say invoked
0103/17:37:47 <INFO > [aop.LogAdvice 17] ioc.TaskImpl’s  before say invoked
0103/17:37:47 <INFO > [ioc.TaskImpl 32] tt say :汪汪汪
0103/17:37:47 <INFO > [aop.LogAdvice 19] ioc.TaskImpl’s  after say invoked

 

 

看效果差不多吧,呵呵

 

这样,我们就能拦截方法的调用了,做一些自己想做的限制或者业务了。比如实现每个用户只能买一个果酱(书上看的喽)

 

 

 

 

 

 

 

 

 

 

 

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics