Spring AOP + AspectJ framework
来源:互联网 发布:xp系统显示网络有重名 编辑:程序博客网 时间:2024/05/20 18:41
转载出处:http://www.blogjava.net/fancydeepin ]
AOP(Aspect Orient Programming),也就是常说的面向方面编程,它是作为面向对象编程的一种补充,专门用于处理系统中分布于各个模块(不同方法)
中的交叉关注点的问题,在 Java EE 应用中,常常通过 AOP 来处理一些具有横切性质的系统级服务,如事务管理、安全检查、缓存、对象池管理等。
简单点来说,它就是一个拦截器可以拦截一些进程,例如,当某个方法执行时,Spring AOP 可以拦截该执行的方法,并允许在方法执行之前或之后添加额外的功能,
以上如若解释的不好,勿喷 -_- ||
AspectJ 是一个基于 Java 语言的 AOP 框架,提供了强大的 AOP 功能,Spring 从 2.0 起,对 AspectJ 功能都提供了支持 .
几个常用的 AspectJ 注解 :
@Before 在方法执行前被执行
@After 在方法执行后被执行
@AfterReturning 在方法执行后被执行,并同时拦截方法返回的结果
@AfterThrowing 在方法抛出异常时候被执行,若方法不抛出异常,则不会被执行
@Around 这个,不知道要怎么解释了,比较不好解释,就像你拦截了一个方法,并在适当的时候给予放行,放行前后可以做额外的处理,下面看示例就很容易明白了
环境 :
eclipse 3.6
maven 3.0.4
spring 3.0.5
aspectj 1.6.11
pom.xml 清单 :
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.fancy</groupId>
<artifactId>spring-aop</artifactId>
<packaging>war</packaging>
<version>1.0</version>
<name>spring-aop Maven Webapp</name>
<url>http://maven.apache.org</url>
<properties>
<spring.version>3.0.5.RELEASE</spring.version>
<aspectj.version>1.6.11</aspectj.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- Spring AOP + AspectJ -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>${aspectj.version}</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>${aspectj.version}</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.7</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<finalName>spring-aop</finalName>
</build>
</project>
applicationContext.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" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<!-- 开启注解 -->
<context:annotation-config/>
<!-- 自动扫描 -->
<context:component-scan base-package="com.fancy"/>
<!-- 启动 AspectJ 支持 -->
<aop:aspectj-autoproxy />
</beans>
还是来编写 HelloWorld :
1 . 编写 HelloWorld 接口
package com.fancy.service;
public interface HelloWorld {
public void sayHi();
public void sayHiAround(String username);
public void sayHiThrowException() throws Exception;
public String sayHiReturnValue();
}
2 . 编写 HelloWorld 接口的实现,并将其注解成 spring 的一个组件
package com.fancy.service.impl;
import com.fancy.service.HelloWorld;
import org.springframework.stereotype.Component;
@Component
public class HelloWorldImpl implements HelloWorld {
public void sayHi() {
System.out.println("sayHi ---->> Hi fancy !");
}
public void sayHiAround(String username) {
System.out.println("sayHiAround ---->> Hi " + username + " !");
}
public void sayHiThrowException() throws Exception {
System.out.println("sayHiThrowException ---->> Hi fancy !");
throw new Exception("Throw an exception here !!!!");
}
public String sayHiReturnValue() {
System.out.println("sayHiReturnValue ---->> Hi fancy !");
return "fancy";
}
}
3 . 编写方面代码 :
AspectJ @Before 示例
package com.fancy.aspect;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class MyAspect {
@Before("execution (* com.fancy.service.HelloWorld.sayHi(..))")
public void logBefore(JoinPoint joinPoint){
System.out.println("logBefore() Method Invoke!");
System.out.println("Hijack Method Name : " + joinPoint.getSignature().getName());
}
}
其中,@Before("execution (* com.fancy.service.HelloWorld.sayHi(..))") 中的 execution (* com.fancy.service.HelloWorld.sayHi(..)) 是切入点表达式,
更多的帮助信息可以查看 spring 的帮助文档,spring 3.0.5 的帮助文档中是在 第 7 章的 7.2.3.4 小节,因为文档上说的也不是太清楚,在这里我也不好说话,
其中的 execution 是用于匹配方法执行的连接点,那个 * 号所占的位不知道是不是代表方法的访问权限,文档上没说,网上也没找到相关解释,哪位知道的望告知啊~~
接下来的 com.fancy.service.HelloWorld.sayHi 就很明显了,就是切入点方法名,再接下来的是 (..),(..) 代表匹配任意数量的参数,可以是 0 个也可以是多个 ;
如果你确定这个方法不需要参数,可以直接使用 (),还可以使用 (*) 来匹配一个任意类型的参数,还可以使用 (* , String),这样代表匹配两个参数,第二个参数必须是
String 类型的参数,这些在 spring 帮助文档的 7.2.3.4 小节都有说到,在这里就不多说了,可以自己去看,英文的看起来更带劲 *_*
再接下来的是 JoinPoint 接口,org.aspectj.lang.JoinPoint 接口表示的是目标类连接点对象,这个我也找不到相关的 API,只能手工整理一下了 :
JoinPoint API
java.lang.Object getThis() :获取代理对象本身;
java.lang.Object getTarget() :获取连接点所在的目标对象;
Signature getSignature() :获取连接点的方法签名对象;
java.lang.Object[] getArgs():获取连接点方法运行时的入参列表;
Junit 测试
package junit.test;
import org.junit.Test;
import org.junit.BeforeClass;
import com.fancy.service.HelloWorld;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestApp {
private static ApplicationContext context = null;
@BeforeClass
public static void setUpBeforeClass() throws Exception {
context = new ClassPathXmlApplicationContext("applicationContext.xml");
}
@Test
public void testMethod() throws Exception{
HelloWorld helloworld = (HelloWorld)context.getBean("helloWorldImpl");
helloworld.sayHi();
}
}
后台输出 :
logBefore() Method Invoke!
Hijack Method Name : sayHi
sayHi ---->> Hi fancy !
AspectJ @After 示例
package com.fancy.aspect;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class MyAspect {
@After("execution (* com.fancy.service.HelloWorld.sayHi(..))")
public void logAfter(JoinPoint joinPoint){
System.out.println("logAfter() Method Invoke!");
System.out.println("Hijack Method Name : " + joinPoint.getSignature().getName());
}
}
Junit 测试
@Test
public void testMethod() throws Exception{
HelloWorld helloworld = (HelloWorld)context.getBean("helloWorldImpl");
helloworld.sayHi();
}
后台输出 :
sayHi ---->> Hi fancy !
logAfter() Method Invoke!
Hijack Method Name : sayHi
AspectJ @AfterReturning 示例
package com.fancy.aspect;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class MyAspect {
@AfterReturning(pointcut = "execution (* com.fancy.service.HelloWorld.sayHiReturnValue(..))", returning = "returnValue")
public void logAfterReturning(JoinPoint joinPoint, Object/*String*/ returnValue){
System.out.println("logAfterReturning() Method Invoke!");
System.out.println("Hijack Method Name : " + joinPoint.getSignature().getName());
System.out.println("The Return Value Is : " + returnValue);
}
}
Junit 测试
@Test
public void testMethod() throws Exception{
HelloWorld helloworld = (HelloWorld)context.getBean("helloWorldImpl");
helloworld.sayHiReturnValue();
}
后台输出 :
sayHiReturnValue ---->> Hi fancy !
logAfterReturning() Method Invoke!
Hijack Method Name : sayHiReturnValue
The Return Value Is : fancy
AspectJ @AfterThrowing 示例
package com.fancy.aspect;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class MyAspect {
@AfterThrowing(pointcut = "execution (* com.fancy.service.HelloWorld.sayHiThrowException(..))", throwing = "error")
public void logAfterThrowing(JoinPoint joinPoint, Throwable error){
System.out.println("logAfterThrowing() Method Invoke!");
System.out.println("Hijack Method Name : " + joinPoint.getSignature().getName());
System.out.println("Exception Message :" + error);
}
}
Junit 测试
@Test
public void testMethod() throws Exception{
HelloWorld helloworld = (HelloWorld)context.getBean("helloWorldImpl");
helloworld.sayHiThrowException();
}
后台输出 :
sayHiThrowException ---->> Hi fancy !
logAfterThrowing() Method Invoke!
Hijack Method Name : sayHiThrowException
Exception Message :java.lang.Exception: Throw an exception here !!!!
若将 HelloWorldImpl 类中 sayHiThrowException 方法的异常抛出注释掉,
public void sayHiThrowException() throws Exception {
System.out.println("sayHiThrowException ---->> Hi fancy !");
//throw new Exception("Throw an exception here !!!!");
}
其余不变,再次执行 Junit 测试,后台输出 :
sayHiThrowException ---->> Hi fancy !
这就说明,当该方法能够运行正常的时候,没有抛出异常,则,logAfterThrowing 不会被执行 .
AspectJ @Around 示例
package com.fancy.aspect;
import java.util.Arrays;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class MyAspect {
@Around("execution (* com.fancy.service.HelloWorld.sayHiAround(..))")
public void logAround(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("logAround() Method Invoke!");
System.out.println("Hijack Method Name : " + joinPoint.getSignature().getName());
System.out.println("Hijack Arguments Is : " + Arrays.toString(joinPoint.getArgs()));
System.out.println("Around before : can do something here !");
joinPoint.proceed(); //放行
System.out.println("Around after : can do something here !");
}
}
Junit 测试
@Test
public void testMethod() throws Exception{
HelloWorld helloworld = (HelloWorld)context.getBean("helloWorldImpl");
helloworld.sayHiAround("fancy");
}
后台输出 :
logAround() Method Invoke!
Hijack Method Name : sayHiAround
Hijack Arguments Is : [fancy]
Around before : can do something here !
sayHiAround ---->> Hi fancy !
Around after : can do something here !
其中,需要提一下 ProceedingJoinPoint 接口 :
ProceedingJoinPoint 继承于 JoinPoint,是其子接口,它新增了两个用于执行连接点方法的方法:
java.lang.Object proceed() throws java.lang.Throwable:通过反射执行目标对象的连接点处的方法;
java.lang.Object proceed(java.lang.Object[] args) throws java.lang.Throwable:通过反射执行目标对象连接点处的方法,不过使用新的入参替换原来的入参。
最后附上 spring 3.0.5 帮助文档中的一些信息 :
Some examples of common pointcut expressions are given below.
the execution of any public method:
execution(public * *(..))
the execution of any method with a name beginning with "set":
execution(* set*(..))
the execution of any method defined by the
AccountService
interface:execution(* com.xyz.service.AccountService.*(..))
the execution of any method defined in the service package:
execution(* com.xyz.service.*.*(..))
the execution of any method defined in the service package or a sub-package:
execution(* com.xyz.service..*.*(..))
any join point (method execution only inspring AOP) within the service package:
within(com.xyz.service.*)
any join point (method execution only in Spring AOP) within the service package or a sub-package:
within(com.xyz.service..*)
any join point (method execution only in Spring AOP) where the proxy implements the
AccountService
interface:this(com.xyz.service.AccountService)
'this' is more commonly used in a binding form :- see the following section on advice for how to make the proxy object available in the advice body.
any join point (method execution only in Spring AOP) where the target object implements the
AccountService
interface:target(com.xyz.service.AccountService)
'target' is more commonly used in a binding form :- see the following section on advice for how to make the target object available in the advice body.
any join point (method execution only in Spring AOP) which takes a single parameter, and where the argument passed at runtime is
Serializable
:args(java.io.Serializable)
'args' is more commonly used in a binding form :- see the following section on advice for how to make the method arguments available in the advice body.
Note that the pointcut given in this example is different to
execution(* *(Java.io.Serializable))
: the args version matches if the argument passed at runtime is Serializable, the execution version matches if the method signature declares a single parameter of typeSerializable
.any join point (method execution only in Spring AOP) where the target object has an
@Transactional
annotation:@target(org.springframework.transaction.annotation.Transactional)
'@target' can also be used in a binding form :- see the following section on advice for how to make the annotation object available in the advice body.
any join point (method execution only in Spring AOP) where the declared type of the target object has an
@Transactional
annotation:@within(org.springframework.transaction.annotation.Transactional)
'@within' can also be used in a binding form :- see the following section on advice for how to make the annotation object available in the advice body.
any join point (method execution only in Spring AOP) where the executing method has an
@Transactional
annotation:@annotation(org.springframework.transaction.annotation.Transactional)
'@annotation' can also be used in a binding form :- see the following section on advice for how to make the annotation object available in the advice body.
any join point (method execution only in Spring AOP) which takes a single parameter, and where the runtime type of the argument passed has the
@Classified
annotation:@args(com.xyz.security.Classified)
'@args' can also be used in a binding form :- see the following section on advice for how to make the annotation object(s) available in the advice body.
any join point (method execution only in Spring AOP) on a Spring bean named '
tradeService
':bean(tradeService)
any join point (method execution only in Spring AOP) on Spring beans having names that match the wildcard expression '
*Service
':bean(*Service)
- Spring AOP + AspectJ framework
- Spring AOP + AspectJ framework
- Spring AOP与Aspectj
- spring AspectJ aop学习
- spring aop AspectJ
- Spring AOP + AspectJ annotation
- Spring AOP之AspectJ
- spring (四) aop/aspectj
- Spring AspectJ AOP 示例
- spring aop 与 aspectj
- Spring @AspectJ 实现AOP
- Spring---AspectJ的AOP
- Spring3- Spring AOP AspectJ
- 19、spring AOP+AspectJ
- Spring AOP 和 AspectJ
- Spring AOP之AspectJ
- Spring AspectJ Aop Annotation
- 关于 Spring AOP (AspectJ)
- 从C#学Javascript笔记(四)
- 一个多线程synchronized引发的问题思考
- 大型网站架构系列:电商网站架构案例
- Android:新浪微博分享多个页面回调不能直接回到调用的Activity问题
- eclipse 下代码中的注释乱码解决方案
- Spring AOP + AspectJ framework
- 填数字
- spring boot 实例演示+深度剖析
- 介绍Beyond Compare三种筛选器
- centos的jenkins部署和配置的问题和方法
- nginx实现ssl反向代理实战
- CSS 巧用 :before和:after
- AFNetworking详解和相关文章链接
- Android与JS交互(传值和值回调)