1、@AspectJ的JDK必须是JDK 5.0+
基于@AspectJ配置切面
@AspectJ采用注解描述切点、增强,两者只是表达式方式不同,效果相同。
@AspectJ语法基础-----切点表达式函数
AspectJ使用。Spring支持9个@AspectJ切点表达式函数,他们用不同的方式描述目标类的连接点,根据描述对象不同,可以大致分为4中类型。
#1、方法切点函数:通过描述目标类方法信息定义连接点。
#2、方法入参切点函数:通过描述目标类方法入参的信息定义连接点。
#3、目标类切点函数:通过描述目标类类型信息定义连接点。
#4、代理类切点函数:通过描述目标类的代理类的信息定义连接点。
切点函数:
类别 | 函数 | 入参 | 说明 |
#1 | execution() | 方法匹配模式串 | 表示满足某一匹配模式的所有目标类方法连接点,如execution(*greetTo(..)) |
#1 | @annotation | 方法注解类名 | 表示标注了特定注解的目标方法连接点,如@annotation(com.smart.anno.NeedTest)表示任何标注了@NeedTest注解的目标类方法 |
#2 | args() | 类名 | 通过判别目标类方法運行時入參對象的類型定義指定連接,如args(com.smart.Waiter)表示所有有且僅有一個按類型匹配于Waiter入參的方法 |
#2 | @args() | 類型注解類名 | 通過判別目標方法運行時入參對象的類是否標注特定注解來指定連接點,如@args(com.smart.Monitorable)表示任何這樣的一個目標方法:它有一個入參且入參對象的類標注@Monitor注解 |
#3 | within() |
|
|
| target() |
|
|
| @within() |
|
|
| @target() |
|
|
#4 | this() | 類名 | 假如代理類按類型匹配于指定類,則被代理的目標類所有連接點匹配切點。 |
函數入參中使用通配符:
$1、* 匹配任意字符,但它只能匹配上下文中的一個元素
$2、..匹配任意字符,可以匹配上下文中的多個元素,但在表示類時,必須和*聯合使用,在表示入參時單獨使用。
$3、+ 表示按類型匹配指定類的所有類,必須跟在類名後面,如com.smart.Car+
一个简单的实例:
Waiter接口
package com.smart.aspectj;
public interface Waiter
{
void greetTo(String name);
void serveTo(String name);
}
NaiveWaiter.java
package com.smart.aspectj;
public class NaiveWaiter implements Waiter
{
@Override
public void greetTo(String name)
{
System.out.println("Greet to "+name+"...");
}
@Override
public void serveTo(String name)
{
System.out.println("Serving to "+name+"...");
}
}
package com.smart.aspectj;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
@Aspect //通过该注解将PreGreetingAspect标注为一个切面
public class PreGreetingAspect
{
@Before("execution(* greetTo(..))")//定義切點和增強類型
public void beforeGreeting()//增強的橫切邏輯
{
System.out.println("How are you!");
}
@After("execution(* serveTo(..))")//定義切點和增強類型
public void afterGreeting()//增強的橫切邏輯
{
System.out.println("Enjoy yourself!!");
}
}
package com.smart.aspectj;
import org.junit.Test;
import org.springframework.aop.aspectj.annotation.AspectJProxyFactory;
public class AspectJProxyTest
{
@Test
public void testAspectJ()
{
Waiter target=new NaiveWaiter();
AspectJProxyFactory factory=new AspectJProxyFactory();
//設置目標對象
factory.setTarget(target);
//添加切面類
factory.addAspect(PreGreetingAspect.class);
//生成織入切面的代理對象
Waiter proxy=factory.getProxy();
proxy.greetTo("John");
proxy.serveTo("John");
}
}
得到的结果是:
How are you!
Greet to John...
Serving to John...
Enjoy yourself!!
2、通过配置使用@AspectJ切面
beans.xml
<!-- 目標Bean -->
<bean id="waiter" class="com.smart.aspectj.NaiveWaiter"/>
<!-- 使用@AspectJ注解的切面類 -->
<bean class="com.smart.aspectj.PreGreetingAspect"/>
<!-- 自動代理創建器,自動將@AspectJ注解切面類織入目標Bean中 -->
<bean class="org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator"/>
测试数据:
package com.smart.aspectj;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class SpringAspectJTest
{
@Test
public void testAspectJ()
{
String configPath="com/smart/aspectj/beans.xml";
ApplicationContext ctx=new ClassPathXmlApplicationContext(configPath);
Waiter waiter=(Waiter)ctx.getBean("waiter");
waiter.greetTo("John");
waiter.serveTo("Tom");
}
}
得出结果:
How are you!
Greet to John...
Serving to Tom...
Enjoy yourself!!