Spring教程-Spring AOP AspectJ XML配置示例
Spring AOP AspectJ XML配置示例
Spring允许您在XML文件中定义方面(Aspects)、通知(Advices)和切点(Pointcuts)。
在上一页中,我们已经看到了使用注解的AOP示例。现在,我们将通过XML配置文件来看相同的示例。
让我们看一下用于定义通知的XML元素。
1.aop:before 在调用实际业务逻辑方法之前应用。
2.aop:after 在调用实际业务逻辑方法之后应用。
3.aop:after-returning 在调用实际业务逻辑方法之后应用。它可以用于在通知中拦截返回值。
4.aop:around 在调用实际业务逻辑方法之前和之后应用。
5.aop:after-throwing 在实际业务逻辑方法抛出异常时应用。
要了解AOP概念、优势等内容,请访问AOP概念教程。
1)aop:before示例
AspectJ Before Advice在实际业务逻辑方法之前应用。您可以在此执行任何操作,例如转换、身份验证等。
创建一个包含实际业务逻辑的类。
文件:Operation.java
package cn.javatiku;
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的aspect类。
文件:TrackOperation.java
package cn.javatiku;
import org.aspectj.lang.JoinPoint;
public class TrackOperation{
public void myadvice(JoinPoint jp)//it is 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-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd ">
<aop:aspectj-autoproxy />
<bean id="opBean" class="cn.javatiku.Operation"> </bean>
<bean id="trackAspect" class="cn.javatiku.TrackOperation"></bean>
<aop:config>
<aop:aspect id="myaspect" ref="trackAspect" >
<!-- @Before -->
<aop:pointcut id="pointCutBefore" expression="execution(* cn.javatiku.Operation.*(..))" />
<aop:before method="myadvice" pointcut-ref="pointCutBefore" />
</aop:aspect>
</aop:config>
</beans>
现在,让我们调用实际的方法。
文件:Test.java
package cn.javatiku;
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();
}
}
输出
calling msg...
additional concern
msg() method invoked
calling m...
additional concern
m() method invoked
calling k...
additional concern
k() method invoked
如您所见,在调用msg()、m()和k()方法之前,都会打印出额外的关注点。
2)aop:after示例
AspectJ after advice在调用实际业务逻辑方法之后应用。它可以用于记录日志、安全性、通知等。
在这里,我们假设Operation.java、TrackOperation.java和Test.java文件与aop:before示例中所给的相同。
现在创建定义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-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd ">
<aop:aspectj-autoproxy />
<bean id="opBean" class="cn.javatiku.Operation"> </bean>
<bean id="trackAspect" class="cn.javatiku.TrackOperation"></bean>
<aop:config>
<aop:aspect id="myaspect" ref="trackAspect" >
<!-- @After -->
<aop:pointcut id="pointCutAfter" expression="execution(* cn.javatiku.Operation.*(..))" />
<aop:after method="myadvice" pointcut-ref="pointCutAfter" />
</aop:aspect>
</aop:config>
</beans>
输出
calling msg...
msg() method invoked
additional concern
calling m...
m() method invoked
additional concern
calling k...
k() method invoked
additional concern
3)aop:after-returning示例
使用after returning advice,我们可以在advice中获取方法的返回结果。
创建一个包含实际业务逻辑的类。
文件:Operation.java
package cn.javatiku;
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 returning advice的aspect类。
文件:TrackOperation.java
package cn.javatiku;
import org.aspectj.lang.JoinPoint;
public class TrackOperation{
public void myadvice(JoinPoint jp,Object result)//it is advice (after 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...");
}
}
现在创建定义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-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd ">
<aop:aspectj-autoproxy />
<bean id="opBean" class="cn.javatiku.Operation"> </bean>
<bean id="trackAspect" class="cn.javatiku.TrackOperation"></bean>
<aop:config>
<aop:aspect id="myaspect" ref="trackAspect" >
<!-- @AfterReturning -->
<aop:pointcut id="pointCutAfterReturning" expression="execution(* cn.javatiku.Operation.*(..))" />
<aop:after-returning method="myadvice" returning="result" pointcut-ref="pointCutAfterReturning" />
</aop:aspect>
</aop:config>
</beans>
现在,让我们调用实际的方法。
文件:Test.java
package cn.javatiku;
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());
}
}
输出
calling m...
m() method invoked
additional concern
Method Signature: int cn.javatiku.Operation.m()
Result in advice: 2
end of after returning advice...
2
calling k...
k() method invoked
additional concern
Method Signature: int cn.javatiku.Operation.k()
Result in advice: 3
end of after returning advice...
3
您可以看到返回值打印了两次,一次是由TrackOperation类打印的,另一次是由Test类打印的。
4)aop:around示例
AspectJ around advice在调用实际业务逻辑方法之前和之后应用。
创建一个包含实际业务逻辑的类。
文件:Operation.java
package cn.javatiku;
public class Operation{
public void msg(){System.out.println("msg() is invoked");}
public void display(){System.out.println("display() is invoked");}
}
创建一个包含around advice的aspect类。
文件:TrackOperation.java
package cn.javatiku;
import org.aspectj.lang.ProceedingJoinPoint;
public class TrackOperation
{
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;
}
}
现在创建定义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-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd ">
<aop:aspectj-autoproxy />
<bean id="opBean" class="cn.javatiku.Operation"> </bean>
<bean id="trackAspect" class="cn.javatiku.TrackOperation"></bean>
<aop:config>
<aop:aspect id="myaspect" ref="trackAspect" >
<!-- @Around -->
<aop:pointcut id="pointCutAround" expression="execution(* cn.javatiku.Operation.*(..))" />
<aop:around method="myadvice" pointcut-ref="pointCutAround" />
</aop:aspect>
</aop:config>
</beans>
现在,让我们调用实际的方法。
文件:Test.java
package cn.javatiku;
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();
}
}
输出:
Additional Concern Before calling actual method
msg() is invoked
Additional Concern After calling actual method
Additional Concern Before calling actual method
display() is invoked
Additional Concern After calling actual method
5)aop:after-throwing示例
通过使用after throwing advice,我们可以在TrackOperation类中打印异常。让我们看一下AspectJ AfterThrowing advice的示例。
创建一个包含实际业务逻辑的类。
文件:Operation.java
package cn.javatiku;
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 throwing advice的aspect类。
在这里,我们还需要传递Throwable引用,以便我们可以在这里拦截异常。
文件:TrackOperation.java
package cn.javatiku;
import org.aspectj.lang.JoinPoint;
public class TrackOperation{
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...");
}
}
现在创建定义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-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd ">
<aop:aspectj-autoproxy />
<bean id="opBean" class="cn.javatiku.Operation"> </bean>
<bean id="trackAspect" class="cn.javatiku.TrackOperation"></bean>
<aop:config>
<aop:aspect id="myaspect" ref="trackAspect" >
<!-- @AfterThrowing -->
<aop:pointcut id="pointCutAfterThrowing" expression="execution(* cn.javatiku.Operation.*(..))" />
<aop:after-throwing method="myadvice" throwing="error" pointcut-ref="pointCutAfterThrowing" />
</aop:aspect>
</aop:config>
</beans>
现在,让我们调用实际的方法。
文件:Test.java
package cn.javatiku;
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);}
}
}
输出
calling validate...
Thanks for vote
calling validate again...
additional concern
Method Signature: void cn.javatiku.Operation.validate(int)
Exception is: java.lang.ArithmeticException: Not valid age
end of after throwing advice...
java.lang.ArithmeticException: Not valid age