`
log_cd
  • 浏览: 1100240 次
  • 性别: Icon_minigender_1
  • 来自: 成都
社区版块
存档分类
最新评论

Spring2.0 AOP AspectJ 注释实现

阅读更多
一、AOP基本概念
  • 切面(Aspect): 一个关注点的模块化,这个关注点可能会横切多个对象。事务管理是J2EE应用中一个关于横切关注点的很好的例子。 在Spring AOP中,切面可以使用通用类(基于模式的风格) 或者在普通类中以 @Aspect 注解(@AspectJ风格)来实现。
  • 连接点(Joinpoint): 在程序执行过程中某个特定的点,比如某方法调用的时候或者处理异常的时候。 在Spring AOP中,一个连接点 总是 代表一个方法的执行。 通过声明一个org.aspectj.lang.JoinPoint类型的参数可以使通知(Advice)的主体部分获得连接点信息。
  • 通知(Advice): 在切面的某个特定的连接点(Joinpoint)上执行的动作。通知有各种类型,其中包括“around”、“before”和“after”等通知。 通知的类型将在后面部分进行讨论。许多AOP框架,包括Spring,都是以拦截器做通知模型, 并维护一个以连接点为中心的拦截器链。
  • 切入点(Pointcut): 匹配连接点(Joinpoint)的断言。通知和一个切入点表达式关联,并在满足这个切入点的连接点上运行(例如,当执行某个特定名称的方法时)。 切入点表达式如何和连接点匹配是AOP的核心:Spring缺省使用AspectJ切入点语法。
  • 引入(Introduction): (也被称为内部类型声明(inter-type declaration))。声明额外的方法或者某个类型的字段。 Spring允许引入新的接口(以及一个对应的实现)到任何被代理的对象。 例如,你可以使用一个引入来使bean实现 IsModified 接口,以便简化缓存机制。
  • 目标对象(Target Object): 被一个或者多个切面(aspect)所通知(advise)的对象。也有人把它叫做 被通知(advised) 对象。 既然Spring AOP是通过运行时代理实现的,这个对象永远是一个 被代理(proxied) 对象。
  • AOP代理(AOP Proxy): AOP框架创建的对象,用来实现切面契约(aspect contract)(包括通知方法执行等功能)。 在Spring中,AOP代理可以是JDK动态代理或者CGLIB代理。 注意:Spring 2.0最新引入的基于模式(schema-based)风格和@AspectJ注解风格的切面声明,对于使用这些风格的用户来说,代理的创建是透明的。
  • 织入(Weaving): 把切面(aspect)连接到其它的应用程序类型或者对象上,并创建一个被通知(advised)的对象。 这些可以在编译时(例如使用AspectJ编译器),类加载时和运行时完成。 Spring和其他纯Java AOP框架一样,在运行时完成织入。

二、通知的类型
  • 前置通知(Before advice): 在某连接点(join point)之前执行的通知,但这个通知不能阻止连接点前的执行(除非它抛出一个异常)。
  • 返回后通知(After returning advice): 在某连接点(join point)正常完成后执行的通知:例如,一个方法没有抛出任何异常,正常返回。
  • 抛出异常后通知(After throwing advice): 在方法抛出异常退出时执行的通知。
  • 后通知(After (finally) advice): 当某连接点退出的时候执行的通知(不论是正常返回还是异常退出)。
  • 环绕通知(Around Advice): 包围一个连接点(join point)的通知,如方法调用。这是最强大的一种通知类型。 环绕通知可以在方法调用前后完成自定义的行为。它也会选择是否继续执行连接点或直接返回它们自己的返回值或抛出异常来结束执行。

三、例子
(1)beans.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:aop="http://www.springframework.org/schema/aop"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">

	<aop:aspectj-autoproxy />

	<bean id="person" class="quickstart.aspectj.Person"
		scope="prototype">
		<property name="name" value="Lucy" />
		<property name="age" value="12" />
	</bean>

	<bean id="organ" class="quickstart.aspectj.Organization" />

</beans>

(2)java bean
package quickstart.aspectj;

public class Person {
	private String name;

	private String age;

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getAge() {
		return age;
	}

	public void setAge(String age) {
		this.age = age;
	}

	public String login(String loginInfo) {
		System.out.println("Person login() " + "LoginInfo:" + loginInfo + this);
		return this.name + " logining...";
	}

	public void loginThrow() throws Exception {
		throw new Exception();
	}

}

package quickstart.aspectj;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;

@Aspect
public class Organization {

	// 创建切入点 (以下切点注释方法均可以使用)
	// @Pointcut("within(quickstart.aspectj.Person)")
	// @Pointcut("execution(* quickstart.aspectj.Person.*(..))")
	@Pointcut("execution(* quickstart.aspectj.Person.login(..))")
	public void logPerson() {
	}

	// 后通知 (After (finally) advice) 使用切入点 logPerson (在“返回后通知”之前)
	@After("quickstart.aspectj.Organization.logPerson()")
	public void logAfter(JoinPoint joinPoint) {
		System.out.println("logPerson 后通知 方法名:"
				+ joinPoint.getSignature().getName());
	}

	// 前置通知 (Before advice) 使用切入点 logPerson
	@Before("quickstart.aspectj.Organization.logPerson()")
	public void logBefore(JoinPoint joinPoint) {
		System.out.println("logPerson 前置通知   方法名:"
				+ joinPoint.getSignature().getName());
	}

	// 前置通知 (Before advice) 使用切入点 logPerson
	@Before("quickstart.aspectj.Organization.logPerson() &&"
			+ "args(info)")
	public void logBeforeArgs(JoinPoint joinPoint, String info) {
		System.out.println("logPerson 前置通知(有参数)   方法名:"
				+ joinPoint.getSignature().getName() + " 参数: " + info);
	}

	// 返回后通知1 (After returning advice) 使用切入点 logPerson (在“后通知”之后)
	@AfterReturning("quickstart.aspectj.Organization.logPerson()")
	public void logAfterReturning1(JoinPoint joinPoint) {
		System.out.println("logPerson 返回后通知1 方法名:"
				+ joinPoint.getSignature().getName() + " return: ");
	}

	// 返回后通知2 (After returning advice) 使用切入点 logPerson (在“后通知”之后)
	@AfterReturning(pointcut = "quickstart.aspectj.Organization.logPerson()", returning = "retVal")
	public void logAfterReturning2(JoinPoint joinPoint, Object retVal) {
		System.out.println("logPerson 返回后通知2 方法名:"
				+ joinPoint.getSignature().getName() + " return: "
				+ retVal.toString());
	}

	// 环绕通知 (Around Advice) 使用切入点 logPerson (在“前通知”之后)
	@Around("quickstart.aspectj.Organization.logPerson()")
	public Object logAround(ProceedingJoinPoint pjp) throws Throwable {
		// start stopwatch
		System.out.println("logPerson 环绕通知 start stopwatch 方法名:"
				+ pjp.getSignature().getName());
		// 执行切入点
		Object retVal = pjp.proceed();

		// stop stopwatch
		System.out.println("logPerson 环绕通知 stop stopwatch 方法名:"
				+ pjp.getSignature().getName() + " return: "
				+ retVal.toString());

		return retVal;
	}

	// 创建切入点
	@Pointcut("execution(* quickstart.aspectj.Person.loginThrow())")
	public void logThrowsPerson() {
	}

	// 抛出后通知(After throwing advice)
	@AfterThrowing("quickstart.aspectj.Organization.logThrowsPerson()")
	public void afterThrowAdvice() {
		System.out.println("抛出后通知(After throwing advice)");
	}

}

四、测试
package logcd.test;

import org.junit.BeforeClass;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import quickstart.aspectj.Person;


public class AspectTest {
	private static ApplicationContext appContext;
	
	@BeforeClass  
	public static void Init(){   
		appContext = new ClassPathXmlApplicationContext("beans.xml");
	} 
	
	@Test
	public void login(){
		Person person = (Person)appContext.getBean("person");
		person.login("Login Info Test");
	}
}
分享到:
评论

相关推荐

    spring的aop配置

    Spring AOP(面向切面编程)是Spring框架的重要组成部分,它允许我们实现代码的解耦,专注于业务逻辑,而将横切关注点如日志、事务管理等分离出来。AOP通过定义切面(Aspects)、通知(Advisors)、切入点...

    spingAOP注解方式

    Spring AOP注解方式是Spring框架提供的一种面向切面编程的实现方式,它允许开发者在不修改原有业务代码的情况下,插入额外的功能,如日志记录、性能监控、安全控制、事务管理和异常处理等。这种方式极大地简化了代码...

    开发者突击·精通AOP整合应用开发 源码

    Spring AOP:以loC为基础讲解Spring下的AOP开发,讲解了3种AOP的开发方式,即使用@Aspect注释符、基于Schema的配置的开发方式和Spring API的开发方式,最后在实际的Java EE项目中实现5种Spring AOP功能(日志记录器...

    spring完全学习实例(一)

    主要包括Spring的IoC、AOP(注释注入、Schema注入、与AspectJ的集成、有接口和无接口的实现的界面编程)、中间数据访问层(编程事事务管理、声明式事务管理、与Hibernate的集成、与JDO的集成、与JTA的集成、纯Spring...

    spring源码 附带中文翻译

    `aop`包则包含了Spring的AOP支持,如`AspectJ`相关的类和接口,以及`Advisor`、`Pointcut`、`Proxy`等概念。AOP允许开发者定义横切关注点,将这些关注点与业务逻辑分离,提高了代码的复用性。Spring AOP通过代理模式...

    simple-spring-memcached:一个通过注释在Spring Bean中启用Memcached缓存的嵌入式库

    简单的Spring Memcached 一个通过注释在Spring bean中启用... 该项目通过在 , 或客户端之上使用Java 5注释和Spring / AspectJ AOP来启用Spring管理的bean中的缓存。 使用Simple Spring Memcached仅需要一点点配置

    spring-framework-3.2.5.RELEASE 源代码

    `org.springframework.aop.aspectj`包则提供了基于AspectJ的AOP支持。 4. **MVC(模型-视图-控制器)** Spring MVC是Spring在Web开发中的应用,`org.springframework.web.servlet`包包含了DispatcherServlet、...

    spring-5.2.3.rar

    最后,"aspectjweaver-1.9.5.jar"是AspectJ库,它是Spring AOP实现的重要组成部分,支持切面编程。"jsr250-api-1.0.jar"和"javax.inject-1.jar"则是Java EE中的依赖,用于实现JSR 250和JSR 330标准,提供依赖注入的...

    spring-source-weaving-example:使用AspectJ的Spring Boot源代码编织示例

    当所有源代码(包括注释类,方面类和目标类)都可用时,AspectJ源编织是编译时编织。 AspectJ编译器( ajc )处理源代码并生成编织字节代码。 所有源代码应在编译时一起显示。 什么时候需要源编织? 由于Spring的...

    exemplo-spring-desktop:使用带有注释和AspectJ的Spring框架的示例

    4. **在Spring中使用AspectJ**:Spring支持两种AOP实现:基于代理的和基于织入的。基于AspectJ的AOP是基于织入的,可以在编译时或加载时进行,提供更细粒度的控制。AspectJ LTW(Load-Time Weaving)可以在类加载到...

    Spring in Action(第二版 中文高清版).part2

    6.4.3 在Spring 2.0里声明事务 6.4.4 定义注释驱动事务 6.5 小结 第7章 保护Spring 7.1 Spring Security介绍 7.2 验证用户身份 7.2.1 配置Provider Manager 7.2.2 根据数据库验证身份 7.2.3 根据LDAP仓库...

    《MyEclipse 6 Java 开发中文教程》前10章

    10.4.2 使用标注(@AspectJ)实现AOP 221 10.4.3 开发环绕通知(Around Advice)AOP 应用 223 10.5 Spring数据库开发 227 10.5.1 DataSource 和 JDBCTemplate开发 227 10.5.2 Hibernate 整合 Spring开发 236 10.5....

    Spring in Action(第2版)中文版

    6.4.3在spring2.0里声明事务 6.4.4定义注释驱动事务 6.5小结 第7章保护spring 7.1springsecurity介绍 7.2验证用户身份 7.2.1配置providermanager 7.2.2根据数据库验证身份 7.2.3根据ldap仓库进行身份验证 ...

    Spring in Action(第二版 中文高清版).part1

    6.4.3 在Spring 2.0里声明事务 6.4.4 定义注释驱动事务 6.5 小结 第7章 保护Spring 7.1 Spring Security介绍 7.2 验证用户身份 7.2.1 配置Provider Manager 7.2.2 根据数据库验证身份 7.2.3 根据LDAP仓库...

    Spring宝典源码3

    这份资料包含的案例丰富且注释详尽,对于学习和掌握Spring的高级特性和内部机制具有极大的帮助。 Spring是Java企业级应用开发中的主流框架,它以其依赖注入(Dependency Injection,DI)和面向切面编程(Aspect-...

    spring_FrameWork3.0

    - **Spring AOP APIs:** Spring 提供了一系列的 AOP 相关 API,包括 AspectJ 注解、@Before/@After 等注解。 **3-7 节测试** - **测试支持:** Spring 提供了单元测试和集成测试的支持,可以帮助开发者编写高质量...

    spring-5.2.8.RELEASE-docs.zip

    此外,还有关于AOP(面向切面编程)的支持,如AspectJ集成,以及Spring的IoC(控制反转)容器的相关内容,包括BeanFactory和ApplicationContext的创建与管理。 "kdoc-api"目录可能包含的是针对Kotlin开发者的API...

    spring4注解

    除了上面提到的注解外,Spring还提供了其他模块的注解,如AOP、Security、Data JPA等模块中也有相应的注解来支持特定的功能需求。 #### 三、注解实例说明 尽管本节原计划通过编写一些示例来详细介绍常用的注解用法...

    aopDemo:springboot + aopAround日志记录+自定义注释解@ReqLog

    由于项目名称提到"AOP Around",我们可以推测这里使用的是基于注解的配置,这通常涉及到创建一个实现了`org.aspectj.lang.annotation.Aspect`接口的类,并在其中定义`@Around`注解的方法。这个方法会接收一个`...

    点智数码--注释驱动的-Spring-cache-缓存的介绍.doc

    4. **AspectJ 支持**:Spring Cache 基于 AOP(面向切面编程)实现,可以对任何方法进行缓存处理。通过使用 AspectJ,开发者可以精确地控制哪些方法的结果应被缓存。 5. **灵活性与扩展性**:Spring Cache 允许...

Global site tag (gtag.js) - Google Analytics