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  

标签: spring, Spring教程, Spring技术, Spring语言学习, Spring学习教程, Spring下载, Spring框架, Spring框架入门, Spring框架教程, Spring框架高级教程, Spring面试题, Spring笔试题, Spring编程思想