- @Before示例
- @After示例
- @AfterReturning示例
- @Around的例子
- @AfterThrowing示例
Spring框架建议你在基于Spring 1.2旧样式dtd的AOP实现上使用Spring AspectJ AOP实现, 因为它为你提供了更多的控制并且易于使用。
有两种使用Spring AOP AspectJ实现的方法:
- 通过注解:我们将在这里学习。
- 通过xml配置(基于模式):我们将在下一页中学习它。
要了解aop概念及其优势等, 请访问此处。AOP概念教程
下载所有示例(使用MyEclipse IDE开发)
Spring AspectJ AOP实现提供了许多注解:
- @Aspect将类声明为方面。
- @Pointcut声明切入点表达式。
用于创建Advice的注解如下:
- @Before声明之前的Advice。在调用实际方法之前应用它。
- @After声明事后Advice。在调用实际方法之后并返回结果之前应用。
- @AfterReturning声明返回After Advice。在调用实际方法之后并返回结果之前应用。但是你可以在Advice中获得结果值。
- @Around声明了Around的Advice。它在调用实际方法之前和之后应用。
- @AfterThrowing声明引发Advice。如果实际方法抛出异常, 则应用此方法。
了解切入点
切入点是Spring AOP的一种表达语言。
@Pointcut批注用于定义切入点。我们也可以通过名称引用切入点表达式。让我们看一下切入点表达式的简单示例。
@Pointcut("execution(* Operation.*(..))")
private void doSomething() {}
切入点表达式的名称为doSomething()。无论返回类型如何, 它将应用于Operation类的所有方法。
了解切入点表达式
让我们尝试通过以下示例了解切入点表达式:
@Pointcut("execution(public * *(..))")
它将应用于所有公共方法。
@Pointcut("execution(public Operation.*(..))")
它将应用于Operation类的所有公共方法。
@Pointcut("execution(* Operation.*(..))")
它将应用于Operation类的所有方法。
@Pointcut("execution(public Employee.set*(..))")
它将应用于Employee类的所有公共设置方法。
@Pointcut("execution(int Operation.*(..))")
它将应用于返回int值的Operation类的所有方法。
1)@之前的例子
在实际业务逻辑方法之前应用AspectJ Before Advice。你可以在此处执行任何操作, 例如转换, 身份验证等。
创建一个包含实际业务逻辑的类。
文件:Operation.java
package com.srcmini;
public class Operation{
public void msg(){System.out.println("msg method invoked");}
public int m(){System.out.println("m method invoked");return 2;}
public int k(){System.out.println("k method invoked");return 3;}
}
现在, 创建包含在Before Advice的方面类。
文件:TrackOperation.java
package com.srcmini;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
@Aspect
public class TrackOperation{
@Pointcut("execution(* Operation.*(..))")
public void k(){}//pointcut name
@Before("k()")//applying pointcut on before advice
public void myadvice(JoinPoint jp)//it is advice (before advice)
{
System.out.println("additional concern");
//System.out.println("Method Signature: " + jp.getSignature());
}
}
现在创建定义bean的applicationContext.xml文件。
文件: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: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.xsd">
<bean id="opBean" class="com.srcmini.Operation"> </bean>
<bean id="trackMyBean" class="com.srcmini.TrackOperation"></bean>
<bean class="org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator"></bean>
</beans>
现在, 让我们调用实际方法。
文件:Test.java
package com.srcmini;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test{
public static void main(String[] args){
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
Operation e = (Operation) context.getBean("opBean");
System.out.println("calling msg...");
e.msg();
System.out.println("calling m...");
e.m();
System.out.println("calling k...");
e.k();
}
}
输出
调用msg …调用了附加关注msg()方法调用了m …调用了附加关注m()方法调用了k …调用了附加关注k()方法
如你所见, 在调用msg(), m()和k()方法之前, 需要打印其他一些问题。
现在, 如果你更改切入点表达式, 如下所示:
@Pointcut(” execution(* Operation.m *(..))”)
现在, 在操作类中以m开头的方法将受到更多关注。输出将如下所示:
调用msg …调用了其他关注的msg()方法调用m …调用了额外的关注m()方法调用k …调用了k()方法
现在你可以看到在调用k()方法之前未打印其他问题。
2)@之后的例子
调用实际的业务逻辑方法后, 将应用忠于Advice的AspectJ。它可以用来维护日志, 安全性, 通知等。
在这里, 我们假设Operation.java, applicationContext.xml和Test.java文件与@Before示例中给出的文件相同。
创建包含事后Advice的方面类。
文件:TrackOperation.java
package com.srcmini;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Pointcut;
@Aspect
public class TrackOperation{
@Pointcut("execution(* Operation.*(..))")
public void k(){}//pointcut name
@After("k()")//applying pointcut on after advice
public void myadvice(JoinPoint jp)//it is advice (after advice)
{
System.out.println("additional concern");
//System.out.println("Method Signature: " + jp.getSignature());
}
}
输出
调用msg … msg()方法调用附加关注点调用m … m()方法调用附加关注点调用k … k()方法调用附加关注点
你可以看到在调用msg(), m()和k()方法之后, 还会显示其他问题。
3)@AfterReturning示例
通过在返回After Advice使用, 我们可以在Advice中获得结果。
创建包含业务逻辑的类。
文件:Operation.java
package com.srcmini;
public class Operation{
public int m(){System.out.println("m() method invoked");return 2;}
public int k(){System.out.println("k() method invoked");return 3;}
}
返回After Advice, 创建包含的方面类。
文件:TrackOperation.java
package com.srcmini;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
@Aspect
public class TrackOperation{
@AfterReturning(
pointcut = "execution(* Operation.*(..))", returning= "result")
public void myadvice(JoinPoint jp, Object result)//it is advice (after returning advice)
{
System.out.println("additional concern");
System.out.println("Method Signature: " + jp.getSignature());
System.out.println("Result in advice: "+result);
System.out.println("end of after returning advice...");
}
}
文件:applicationContext.xml
与@BeforeAdvice示例中给出的相同
文件:Test.java
现在, 创建调用实际方法的Test类。
package com.srcmini;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test{
public static void main(String[] args){
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
Operation e = (Operation) context.getBean("opBean");
System.out.println("calling m...");
System.out.println(e.m());
System.out.println("calling k...");
System.out.println(e.k());
}
}
输出
调用m … m()方法调用了其他方法方法签名:int com.srcmini.Operation.m()通知结果:2返回After Advice的结尾… 2调用k … k()方法调用了其他方法有关方法签名:int com.srcmini.Operation.k()通知结果:3返回After Advice的结尾… 3
你可以看到返回值被打印了两次, 一次是由TrackOperation类打印的, 而第二次是由Test类打印的。
4)@Around的例子
Around Advice的AspectJ在调用实际的业务逻辑方法之前和之后都会应用。
在这里, 我们假设applicationContext.xml文件与@Before示例中给出的文件相同。
创建一个包含实际业务逻辑的类。
文件:Operation.java
package com.srcmini;
public class Operation{
public void msg(){System.out.println("msg() is invoked");}
public void display(){System.out.println("display() is invoked");}
}
创建包含Around Advice的方面类。
你需要在advice方法中传递PreceedingJoinPoint引用, 以便我们可以通过调用progress()方法来进行请求。
文件:TrackOperation.java
package com.srcmini;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
@Aspect
public class TrackOperation
{
@Pointcut("execution(* Operation.*(..))")
public void abcPointcut(){}
@Around("abcPointcut()")
public Object myadvice(ProceedingJoinPoint pjp) throws Throwable
{
System.out.println("Additional Concern Before calling actual method");
Object obj=pjp.proceed();
System.out.println("Additional Concern After calling actual method");
return obj;
}
}
文件:Test.java
现在, 创建调用实际方法的Test类。
package com.srcmini;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test{
public static void main(String[] args){
ApplicationContext context = new classPathXmlApplicationContext("applicationContext.xml");
Operation op = (Operation) context.getBean("opBean");
op.msg();
op.display();
}
}
输出
调用实际方法msg()之前的其他问题调用实际方法之后的其他问题调用实际方法display()之前的其他问题调用实际方法之后的其他问题
你可以看到在调用msg()和display方法之前和之后都会打印出其他问题。
5)@AfterThrowing示例
通过使用引发After Advice的用法, 我们可以在TrackOperation类中打印异常。让我们看一下AspectJ AfterThrowing Advice的示例。
创建包含业务逻辑的类。
文件:Operation.java
package com.srcmini;
public class Operation{
public void validate(int age)throws Exception{
if(age<18){
throw new ArithmeticException("Not valid age");
}
else{
System.out.println("Thanks for vote");
}
}
}
创建After Advice包含的方面类。
在这里, 我们还需要传递Throwable引用, 以便我们可以在此处拦截异常。
文件:TrackOperation.java
package com.srcmini;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
@Aspect
public class TrackOperation{
@AfterThrowing(
pointcut = "execution(* Operation.*(..))", throwing= "error")
public void myadvice(JoinPoint jp, Throwable error)//it is advice
{
System.out.println("additional concern");
System.out.println("Method Signature: " + jp.getSignature());
System.out.println("Exception is: "+error);
System.out.println("end of after throwing advice...");
}
}
文件:applicationContext.xml
与@BeforeAdvice示例中给出的相同
文件:Test.java
现在, 创建调用实际方法的Test类。
package com.srcmini;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test{
public static void main(String[] args){
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
Operation op = (Operation) context.getBean("opBean");
System.out.println("calling validate...");
try{
op.validate(19);
}catch(Exception e){System.out.println(e);}
System.out.println("calling validate again...");
try{
op.validate(11);
}catch(Exception e){System.out.println(e);}
}
}
输出
调用验证…感谢投票再次验证…其他关注方法签名:void com.srcmini.Operation.validate(int)异常是:java.lang.ArithmeticException:抛出After Advice无效的年龄结束… java.lang.ArithmeticException:无效年龄
下载所有示例(使用MyEclipse IDE开发)
评论前必须登录!
注册