`
log_cd
  • 浏览: 1089255 次
  • 性别: 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");
	}
}
分享到:
评论

相关推荐

    开发者突击·精通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...

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

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

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

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

    《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(第二版 中文高清版).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仓库...

    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仓库...

    全面解析Java注解

     我们有必要对JDK 5.0新增的注解(Annotation)技术进行简单的学习,因为Spring 支持@AspectJ,而@AspectJ本身是基于JDK 5.0的注解技术。所以学习JDK 5.0的注解知识有助于我们更好地理解和掌握Spring的AOP技术。 ...

    multi-tenant-app-demo:使用Spring Boot和Hibernate 5演示基于鉴别字段(共享模式)的多租户应用程序

    使用Spring AOP(AspectJ)设置过滤器参数。 说明: 每个请求都经过一个自定义的servlet过滤器,该过滤器检查X-TenantID http标头,并使用TenantContext类在ThreadLocal变量中对其进行TenantContext 。 如果请求...

    null-check:使用 Spring AOP 在运行时验证 @Nonnull 方法参数

    该项目为javax.annotation.Nonnull注释的方法参数实现了驱动的运行javax.annotation.Nonnull值检查。 在内部, @Before切入点用于拦截具有一个或多个@Nonnull注释参数的方法并检查它们的值是否为非空。 此功能由...

    spring security 参考手册中文版

    作为用户在Spring MVC测试中使用注释运行 108 12.2.4测试HTTP基本认证 109 12.3 SecurityMockMvcRequestBuilders 109 12.3.1测试基于表单的认证 109 12.3.2测试注销 110 12.4 SecurityMockMvcResultMatchers 110 ...

    aop-annotation-logging

    aop注释日志结合Java注释日志实现AOP。 要执行此项目,请在AOPLoggerTest.java中运行main方法请确保为项目启用了AspectJ Tooling,以得到正确的结果。 要在Spring Tool Suite中执行此操作, 将适当的项目导入STS, ...

    fastaop:AJava Aop库,原理同Lombok,使用简单且对对性能无损耗

    FastAop是一种基于Java注释处理的AOP框架,其原理和Lombok类似,通过对编译过程的拦截,修改方法的语法树并织入切面代码从而实现了AOP的功能,相较于传统的AspectJ,Spring -AOP框架有如下特点: 依赖干净,无需...

    J2EE应用开发详解

    259 15.3.1 Constructor注入 259 15.3.2 Setter注入 261 15.3.3 Method注入 263 15.4 Spring AOP技术 266 15.4.1 装备(advices) 267 15.4.2 Spring AOP的传统用法 275 15.4.3 基于@AspectJ注释的AOP 277 15.4.4 ...

    资金:Dapper风格的分布式跟踪仪表库

    发展状况 发布了0.9.0! 这里有很多更新。... spring-使用Spring AOP / spring bean轻松地对您的应用程序进行检测。 下包含的样本MVC应用程序samples目录 Aspectj-使用Java注释和Aspectj向您的应用程序非介

    基于MyEclipse搭建maven+springmvc整合图文教程(含源码0

    在使用maven 打包或者编译时报:-source1.3 中不支持注释错误解决方案如下:      &lt;artifactId&gt;maven-compiler-plugin  &lt;version&gt;2.0.2    &lt;source&gt;1.5  &lt;target&gt;1.5         添加如下配置就不会再报错...

    springboot-boilerplate

    auth会用aop的形式做在这层,因此这层会用到AspectJ aop。 transaction会在这边定义,因此会依赖spring-boot-starter-jdbc(需要transaction这个注释)。 网络模型 spring boot层,仅依赖应用程序,启动/ router / ...

Global site tag (gtag.js) - Google Analytics