`

Spring AOP——轻松实现代理

阅读更多

本文依然参考夏昕的Spring开发指南(下载自满江红)。

这里,我想先说下“满江红开源”(http://wiki.redsaga.com/)。这是我见识过国内最好的开源组织。满江红的页面非常简洁,但是提供的东西都是非常实用的。在主页下端还提供了到JavaEye的连接。因为本身我觉着JavaEye就是一个很好的社区,所以进一步说明满江红是一个很不错的组织。

转入正题,昨天写了关于Java动态代理的东东,但是从实现过程来看,稍显复杂。从原始类得到代理类的过程,很容易让人迷惑。使用Spring的AOP可以很简单的实现动态代理,并且得到代理对象的过程完全由Spring完成,我们做的只是写xml配置。还有另外一点,就是如果使用JDK的动态代理,那么被代理类必须实现接口。但是Spring的AOP没有这样的限制,它的代理实现有两种方式,JDK的动态代理和CGLIB(在后面的文章中有介绍)。下面是个Spring的AOP的例子,有JDK的动态代理和CGLIB两个版本,用AOP记录函数的执行时间。

 

首先是JDK动态代理版本。

 

接口test.quqtalk.spring.aop. ITest

 

package test.quqtalk.spring.aop;

public interface ITest {
	public abstract void doTest();

	public abstract void executeTest();
}

  接口的实现类:

 

 

package test.quqtalk.spring.aop;

public class Test implements ITest {
	public void doTest() {
		for (int i = 0; i < 10000; i++) {
		}
	}

	public void executeTest() {
		for (int i = 0; i < 25000; i++) {
		}
	}
}

 

  AOP的逻辑处理类:

 

package test.quqtalk.spring.aop;

import java.io.Serializable;

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

public class MethodTimeCostInterceptor implements MethodInterceptor,
		Serializable {
	/**
	 * 
	 */
	private static final long serialVersionUID = 5916297666638680535L;
	protected static final Log logger = LogFactory
			.getLog(MethodTimeCostInterceptor.class);

	public Object invoke(MethodInvocation invocation) throws Throwable {
		long time = System.currentTimeMillis();
		Object rval = invocation.proceed();
		time = System.currentTimeMillis() - time;
		System.out.println("Method Cost Time => " + time + " ms");
		return rval;
	}

}

 

Spring配置文件:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
<beans>
	<bean id="myPointcutAdvisor"
		class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
		<property name="advice">
			<ref local="MyInterceptor"/>
		</property>
		<property name="patterns">
			<list>
				<value>.*do.*</value>
				<value>.*execute.*</value>
			</list>
		</property>
	</bean>
	<bean id="MyInterceptor"
		class="test.quqtalk.spring.aop.MethodTimeCostInterceptor"/>
	
	<bean id="myAOPProxy"
		class="org.springframework.aop.framework.ProxyFactoryBean">
		<property name="proxyInterfaces">
			<value>test.quqtalk.spring.aop.ITest</value>
		</property>
		
		<property name="target">
			<ref local="test"/>
		</property>
		
		<property name="interceptorNames">
			<value>myPointcutAdvisor</value>
		</property>
	</bean>
	
	<bean id="test" class="test.quqtalk.spring.aop.Test"/>
</beans>

  测试类:

package test.quqtalk.spring.aop;

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main {
	public static void main(String[] args) {
		ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext(
				"test/quqtalk/spring/aop/app.xml");
		//这里强制转换成ITest
		ITest test = (ITest) ctx.getBean("myAOPProxy");

		test.doTest();
		test.executeTest();
	}
}

 

然后,是CGLIB版本。

 

  被代理类test.quqtalk.spring.aop.Test,注意这里没有实现任何接口:

 

package test.quqtalk.spring.aop;

public class Test{
	public void doTest() {
		for (int i = 0; i < 10000; i++) {
		}
	}

	public void executeTest() {
		for (int i = 0; i < 25000; i++) {
		}
	}
}

 

  处理逻辑跟JDK动态代理版本相同:

package test.quqtalk.spring.aop;

import java.io.Serializable;

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

public class MethodTimeCostInterceptor implements MethodInterceptor,
		Serializable {
	/**
	 * 
	 */
	private static final long serialVersionUID = 5916297666638680535L;
	protected static final Log logger = LogFactory
			.getLog(MethodTimeCostInterceptor.class);

	public Object invoke(MethodInvocation invocation) throws Throwable {
		long time = System.currentTimeMillis();
		Object rval = invocation.proceed();
		time = System.currentTimeMillis() - time;
		System.out.println("Method Cost Time => " + time + " ms");
		return rval;
	}

}

  配置文件:

 

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
<beans>
	<bean id="myPointcutAdvisor"
		class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
		<property name="advice">
			<ref local="MyInterceptor"/>
		</property>
		<property name="patterns">
			<list>
				<value>.*do.*</value>
				<value>.*execute.*</value>
			</list>
		</property>
	</bean>
	<bean id="MyInterceptor"
		class="test.quqtalk.spring.aop.MethodTimeCostInterceptor"/>
	
	<bean id="myAOPProxy"
		class="org.springframework.aop.framework.ProxyFactoryBean">
		
		<property name="proxyTargetClass">
			<value>true</value>
		</property>
		
		<property name="target">
			<ref local="test"/>
		</property>
		
		<property name="interceptorNames">
			<value>myPointcutAdvisor</value>
		</property>
	</bean>
	
	<bean id="test" class="test.quqtalk.spring.aop.Test"/>
</beans>

 

  测试程序:

 

package test.quqtalk.spring.aop;

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main {
	public static void main(String[] args) {
		ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext(
				"test/quqtalk/spring/aop/app.xml");
		//这里强制转换成Test
		Test test = (Test) ctx.getBean("myAOPProxy");

		test.doTest();
		test.executeTest();
	}
}

 

运行后控制台都会打出:

Method Cost Time => 0 ms

Method Cost Time => 0 ms

 

 

 

分享到:
评论

相关推荐

    spring之AOP(动态代理)

    在Spring中,AOP主要通过两种动态代理技术实现:JDK动态代理和CGLIB动态代理。 首先,让我们详细了解一下JDK动态代理。JDK动态代理基于Java的接口实现,它适用于目标对象实现了至少一个接口的情况。在运行时,JDK...

    spring-aop.jar

    《深入解析Spring AOP框架——以spring-aop.jar为例》 Spring AOP,全称Aspect Oriented Programming(面向切面编程),是Spring框架的核心部分之一,它为Java开发者提供了强大的面向切面的编程能力。本文将围绕...

    spring AOP myeclipse 完整代码

    而AOP通过将这些关注点抽取到单独的模块——切面(Aspect)中,实现了代码的解耦和复用。 在MyEclipse中集成Spring AOP,首先需要创建一个Spring项目,并在项目中引入Spring的相关库,包括`spring-aop.jar`和`...

    Java动态代理(Spring Aop原理)

    - Spring AOP是基于动态代理实现的,它可以在不修改原有代码的情况下,为方法添加日志、事务管理等横切关注点。Spring支持两种类型的代理:JDK动态代理和CGLIB代理。 - JDK动态代理适用于目标对象实现了至少一个...

    spring-aop

    2. **org.springframework.aop.framework**:这个包包含了AOP的代理实现,包括JDK动态代理和CGLIB代理。JDK代理用于实现接口的类,而CGLIB代理则用于没有实现接口但需要进行AOP处理的类。Spring会根据目标对象是否...

    Spring boot——@DeclareParents例子

    在Spring Boot框架中,`@DeclareParents`注解是AOP(面向切面编程)的一部分,主要用于实现动态代理。AOP允许我们在不修改原有代码的情况下,通过“切面”来增强或修改程序的行为,这对于日志记录、事务管理等横切...

    java开发常用jar包之spring--aop.rar

    本资源"java开发常用jar包之spring--aop.rar"聚焦于Spring框架的一个重要组件——Aspect Oriented Programming(面向切面编程,简称AOP)。AOP是Spring框架的核心特性之一,它允许开发者将关注点从核心业务逻辑中...

    aopalliance-1.0、aspectjweaver-1.8.10、spring-aop-4.3.6.RELEASE、spring-aspects-4.3

    aopalliance-1.0提供了标准化的接口,aspectjweaver-1.8.10提供了强大的字节码织入能力,而spring-aop和spring-aspects则让开发者在Spring框架中轻松地应用AOP。通过这些工具,开发者可以更好地组织代码,将业务逻辑...

    三、Spring源码分析——ApplicationContext

    虽然ApplicationContext本身不直接处理AOP,但它通过配合AOP代理(如DefaultListableBeanFactory中的ProxyFactoryBean)和Advisor,实现了AOP的配置和应用。 8. **其他功能**: ApplicationContext还支持Bean的懒...

    spring-aspects

    Spring AOP有两种实现方式:代理模式(Proxy-based)和基于织入(Weaving-based)。代理模式是在运行时动态创建目标对象的代理,而织入是在类加载时或者运行时将切面代码插入到目标类中。`spring-aspects`主要涉及...

    spring--5.1.5.RELEASE.jar.rar

    例如,在一个基于Spring的系统中,通过AOP可以轻松实现事务管理,只需在需要的地方定义事务切面,Spring就会自动处理事务的开启、提交或回滚。同时,通过 Beans 的依赖注入,可以方便地在对象间传递依赖,减少代码间...

    spring事务与数据库操作

    除了事务管理外,Spring还提供了一种强大的机制——面向切面编程(AOP),用于实现诸如日志记录、性能监控、事务管理等横切关注点。 ##### 2.1 Spring AOP简介 面向切面编程是一种编程范式,旨在通过将程序中的横...

    Spring有关资料 源码

    5. **AOP代理**:Spring提供了两种AOP代理——JDK动态代理和CGLIB代理。前者用于接口实现类,后者用于无接口类。代理允许在方法调用前后插入额外的行为。 6. **数据访问集成**:Spring提供了对各种数据库访问技术的...

    spring5学习笔记

    "10、代理模式.md"阐述了Spring AOP实现的基础——代理模式。Spring支持JDK动态代理和CGLIB代理,根据目标对象是否实现了接口,选择合适的代理方式进行增强。 八、IOC理论推导 "2、IOC理论推导.md"深入解析了控制...

    spring核心包

    Spring AOP通过代理模式实现了切面,可以在不修改原有代码的情况下增强功能。在2.0版本中,Spring引入了基于注解的AOP,使得切面的定义更加直观和简洁,降低了学习和使用AOP的门槛。 最后,`acegi-security-1.0.3....

    Spring从入门到精通

    Spring AOP通过动态代理技术实现,提供了注解和XML配置两种方式来定义切面。 数据库操作是企业级应用不可或缺的一部分。Spring JDBC和MyBatis集成使得数据库访问更加简单。Spring JDBC提供了一种模板化的JDBC抽象层...

    sping AOP 权限管理方案浅析

    Spring AOP(Aspect Oriented Programming)是Spring框架的重要组成部分,它允许开发者定义“切面”——即跨越多个对象的关心点,如日志、事务管理或权限控制。在权限管理中,AOP可以帮助我们在不改变业务逻辑的情况...

Global site tag (gtag.js) - Google Analytics