spring AOP (8)

下面所有代码和示例仅仅是为了讲解spring aop,不能用于实际开发,因为实际没有这样用的,但是看看,理解下肯定是有好处的。

示例:对于更新或者删除用户来说,我们要进行事务管理,更新或删除之前要打开事务,之后要提交事务。

这里以更新来作为示例。

spring可以利用jdk或cglid来生成动态代理,我们直接利用cglib对类进行代理,不创建interface了。

UserService:

package spring3.aop.aop1;

public class UserService {

	public void updUser() {
		System.out.println("UserService updUser!");
	}
}

 创建前置增强 OpenTransaction:

package spring3.aop.aop1;

import java.lang.reflect.Method;

import org.springframework.aop.MethodBeforeAdvice;

public class OpenTransaction implements MethodBeforeAdvice {

	/**
	 * 前置增强
	 * 
	 * @param method    目标类方法
	 * @param args      目标类方法的入参
	 * @param obj       目标类实例
	 */
	@Override
	public void before(Method method, Object[] args, Object obj)
			throws Throwable {
		System.out.println("Open Transaction");
	}

}

 创建后置增强 CommitTransaction:

package spring3.aop.aop1;

import java.lang.reflect.Method;

import org.springframework.aop.AfterReturningAdvice;

public class CommitTransaction implements AfterReturningAdvice {

	/**
	 * 后置增强
	 * 
	 * @param returnObj    目标类方法返回的结果
	 * @param method       目标类方法
	 * @param args         目标类方法的入参
	 * @param obj          目标类实例
	 */
	@Override
	public void afterReturning(Object returnObj, Method method, Object[] args,
			Object obj) throws Throwable {
		System.out.println("Close Transaction");
	}

}

xml配置:

<?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:p="http://www.springframework.org/schema/p"
       xsi:schemaLocation="http://www.springframework.org/schema/beans 
                           http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

    <bean id="beforeAdvice" class="spring3.aop.aop1.OpenTransaction"/>
    <bean id="afterAdvice" class="spring3.aop.aop1.CommitTransaction"/>
    <bean id="target" class="spring3.aop.aop1.UserService"/>

    <bean id="userService" class="org.springframework.aop.framework.ProxyFactoryBean"
          p:interceptorNames="beforeAdvice, afterAdvice"
          p:target-ref="target"/>

</beans>

 我们可以通过编码方式和配置方式来完成织入,现在我们来写测试类 TestAdvice:

package spring3.aop.aop1;

import org.springframework.aop.AfterReturningAdvice;
import org.springframework.aop.BeforeAdvice;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestAdvice {

	public static void main(String[] args) {

		// 通过编码方式来织入增强 START

		UserService target = new UserService();
		BeforeAdvice beforeAdvice = new OpenTransaction();
		AfterReturningAdvice afterAdvice = new CommitTransaction();

		// Spring提供的代理工厂
		ProxyFactory pf = new ProxyFactory();
		// 设定代理目标类
		pf.setTarget(target);
		// 为代理目标类织入增强
		pf.addAdvice(beforeAdvice);
		pf.addAdvice(afterAdvice);
		// 生成代理实例
		target = (UserService) pf.getProxy();
		target.updUser();

		// 通过编码方式来织入增强 END

		System.out.println("");

		// 通过XML配置方式来织入增强 START
		ApplicationContext app = new ClassPathXmlApplicationContext(
				"spring3/aop/aop1/aop.xml");
		UserService userService = (UserService) app.getBean("userService");
		userService.updUser();
		// 通过XML配置方式来织入增强 START

	}
}

测试结果:

Open Transaction
UserService updUser!
Close Transaction

4 12, 2013 1:45:44 午後 org.springframework.context.support.AbstractApplicationContext prepareRefresh
情報: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@15ede11: startup date [Fri Apr 12 13:45:44 CST 2013]; root of context hierarchy
4 12, 2013 1:45:44 午後 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
情報: Loading XML bean definitions from class path resource [spring3/aop/aop1/aop.xml]
4 12, 2013 1:45:45 午後 org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons
情報: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@1a3eaa8: defining beans [beforeAdvice,afterAdvice,target,userService,aroundInterceptor,userService1]; root of factory hierarchy
Open Transaction
UserService updUser!
Close Transaction

上面测试类程序中使用了org.springframework.aop.framework.ProxyFactory,它利用cglib或者jdk技术来创建代理,如果利用ProxyFactory.setInterfaces(arg0)方法来对特定接口来实现代理的话,ProxyFactory会选择利用jdk技术生成代理;如果没有指定针对接口代理或者指定ProxyFactory.setOptimize(true)(启用优化)时,ProxyFactory会选择利用cglib技术生成代理。

注意,如果ProxyFactory.setOptimize(true)设定true时,即使指定对接口进行代理,也会利用cglib技术来生成代理。

环绕增强 AroundInterceptor:

package spring3.aop.aop1;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;

public class AroundInterceptor implements MethodInterceptor {

	@Override
	public Object invoke(MethodInvocation invocation) throws Throwable {
		System.out.println("Open Transaction");
		Object obj = invocation.proceed();
		System.out.println("Close Transaction");
		return obj;
	}

}

XML文件

<?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:p="http://www.springframework.org/schema/p"
       xsi:schemaLocation="http://www.springframework.org/schema/beans 
                           http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

    <bean id="target" class="spring3.aop.aop1.UserService"/>
    <bean id="aroundInterceptor" class="spring3.aop.aop1.AroundInterceptor"/>
    <bean id="userService1" class="org.springframework.aop.framework.ProxyFactoryBean"
          p:interceptorNames="aroundInterceptor"
          p:target-ref="target"/>

</beans>

测试类

package spring3.aop.aop1;

import org.springframework.aop.framework.ProxyFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestAdvice {

	public static void main(String[] args) {

		UserService target = new UserService();
		AroundInterceptor inteceptor = new AroundInterceptor();
		ProxyFactory pf = new ProxyFactory();
		pf.addAdvice(inteceptor);
		pf.setTarget(target);
		target = (UserService) pf.getProxy();
		target.updUser();

		System.out.println("");

		ApplicationContext app = new ClassPathXmlApplicationContext(
				"spring3/aop/aop1/aop.xml");
		UserService userService1 = (UserService) app.getBean("userService1");
		userService1.updUser();
	}
}

测试结果:

Open Transaction
UserService updUser!
Close Transaction

4 12, 2013 1:57:55 午後 org.springframework.context.support.AbstractApplicationContext prepareRefresh
情報: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@1565e9d: startup date [Fri Apr 12 13:57:55 CST 2013]; root of context hierarchy
4 12, 2013 1:57:55 午後 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
情報: Loading XML bean definitions from class path resource [spring3/aop/aop1/aop.xml]
4 12, 2013 1:57:55 午後 org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons
情報: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@196de7e: defining beans [target,aroundInterceptor,userService1]; root of factory hierarchy
Open Transaction
UserService updUser!
Close Transaction

猜你喜欢

转载自xieyan30.iteye.com/blog/1846311