为了在本节的描述中使用 aop 命名空间标签,你需要导入 spring-aop j架构,如下所述:
<?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 ">
<!-- bean definition & aop specific configuration -->
</beans>
你还需要在你的应用程序的 classpath 中使用以下 aspectj 库文件。这些库文件在一个 aspectj 装置的 ‘lib’ 目录中是可用的,否则你可以在 internet 中下载它们。
aspectjrt.jar
aspectjweaver.jar
aspectj.jar
一个 aspect 是使用 元素声明的,支持的 bean 是使用 ref 属性引用的,如下所示:
<aop:config>
<aop:aspect id="myaspect" ref="abean">
...
</aop:aspect>
</aop:config>
<bean id="abean" class="...">
...
</bean>
这里,“abean” 将被配置和依赖注入,就像前面的章节中你看到的其他的 spring bean 一样。
一个切入点有助于确定使用不同建议执行的感兴趣的连接点(即方法)。在处理基于配置的 xml 架构时,切入点将会按照如下所示定义:
<aop:config>
<aop:aspect id="myaspect" ref="abean">
<aop:pointcut id="businessservice"
expression="execution(* com.xyz.myapp.service.*.*(..))"/>
...
</aop:aspect>
</aop:config>
<bean id="abean" class="...">
...
</bean>
下面的示例定义了一个名为 “businessservice” 的切入点,该切入点将与 com.tutorialspoint 包下的 student 类中的 getname() 方法相匹配:
<aop:config>
<aop:aspect id="myaspect" ref="abean">
<aop:pointcut id="businessservice"
expression="execution(* com.tutorialspoint.student.getname(..))"/>
...
</aop:aspect>
</aop:config>
<bean id="abean" class="...">
...
</bean>
你可以使用 <aop:{advice name}> 元素在一个 中声明五个建议中的任何一个,如下所示:
<aop:config>
<aop:aspect id="myaspect" ref="abean">
<aop:pointcut id="businessservice"
expression="execution(* com.xyz.myapp.service.*.*(..))"/>
<!-- a before advice definition -->
<aop:before pointcut-ref="businessservice"
method="dorequiredtask"/>
<!-- an after advice definition -->
<aop:after pointcut-ref="businessservice"
method="dorequiredtask"/>
<!-- an after-returning advice definition -->
<!--the dorequiredtask method must have parameter named retval -->
<aop:after-returning pointcut-ref="businessservice"
returning="retval"
method="dorequiredtask"/>
<!-- an after-throwing advice definition -->
<!--the dorequiredtask method must have parameter named ex -->
<aop:after-throwing pointcut-ref="businessservice"
throwing="ex"
method="dorequiredtask"/>
<!-- an around advice definition -->
<aop:around pointcut-ref="businessservice"
method="dorequiredtask"/>
...
</aop:aspect>
</aop:config>
<bean id="abean" class="...">
...
</bean>
你可以对不同的建议使用相同的 dorequiredtask 或者不同的方法。这些方法将会作为 aspect 模块的一部分来定义。
为了理解上面提到的基于 aop 的 xml 架构的概念,让我们编写一个示例,可以实现几个建议。为了在我们的示例中使用几个建议,让我们使 eclipse ide 处于工作状态,然后按照如下步骤创建一个 spring 应用程序:
步骤 | 描述 |
---|---|
1 | 创建一个名为 springexample 的项目,并且在所创建项目的 src 文件夹下创建一个名为 com.tutorialspoint 的包。 |
2 | 使用 add external jars 选项添加所需的 spring 库文件,就如在 spring hello world example 章节中解释的那样。 |
3 | 在项目中添加 spring aop 指定的库文件 aspectjrt.jar, aspectjweaver.jar 和 aspectj.jar。 |
4 | 在 com.tutorialspoint 包下创建 java 类 logging, student 和 mainapp。 |
5 | 在 src 文件夹下创建 beans 配置文件 beans.xml。 |
6 | 最后一步是创建所有 java 文件和 bean 配置文件的内容,并且按如下解释的那样运行应用程序。 |
这里是 logging.java 文件的内容。这实际上是 aspect 模块的一个示例,它定义了在各个点调用的方法。
package com.tutorialspoint;
public class logging {
/**
* this is the method which i would like to execute
* before a selected method execution.
*/
public void beforeadvice(){
system.out.println("going to setup student profile.");
}
/**
* this is the method which i would like to execute
* after a selected method execution.
*/
public void afteradvice(){
system.out.println("student profile has been setup.");
}
/**
* this is the method which i would like to execute
* when any method returns.
*/
public void afterreturningadvice(object retval){
system.out.println("returning:" + retval.tostring() );
}
/**
* this is the method which i would like to execute
* if there is an exception raised.
*/
public void afterthrowingadvice(illegalargumentexception ex){
system.out.println("there has been an exception: " + ex.tostring());
}
}
下面是 student.java 文件的内容:
package com.tutorialspoint;
public class student {
private integer age;
private string name;
public void setage(integer age) {
this.age = age;
}
public integer getage() {
system.out.println("age : " + age );
return age;
}
public void setname(string name) {
this.name = name;
}
public string getname() {
system.out.println("name : " + name );
return name;
}
public void printthrowexception(){
system.out.println("exception raised");
throw new illegalargumentexception();
}
}
下面是 mainapp.java 文件的内容:
package com.tutorialspoint;
import org.springframework.context.applicationcontext;
import org.springframework.context.support.classpathxmlapplicationcontext;
public class mainapp {
public static void main(string[] args) {
applicationcontext context =
new classpathxmlapplicationcontext("beans.xml");
student student = (student) context.getbean("student");
student.getname();
student.getage();
student.printthrowexception();
}
}
下面是配置文件 beans.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:config>
<aop:aspect id="log" ref="logging">
<aop:pointcut id="selectall"
expression="execution(* com.tutorialspoint.*.*(..))"/>
<aop:before pointcut-ref="selectall" method="beforeadvice"/>
<aop:after pointcut-ref="selectall" method="afteradvice"/>
<aop:after-returning pointcut-ref="selectall"
returning="retval"
method="afterreturningadvice"/>
<aop:after-throwing pointcut-ref="selectall"
throwing="ex"
method="afterthrowingadvice"/>
</aop:aspect>
</aop:config>
<!-- definition for student bean -->
<bean id="student" class="com.tutorialspoint.student">
<property name="name" value="zara" />
<property name="age" value="11"/>
</bean>
<!-- definition for logging aspect -->
<bean id="logging" class="com.tutorialspoint.logging"/>
</beans>
一旦你已经完成的创建了源文件和 bean 配置文件,让我们运行一下应用程序。如果你的应用程序一切都正常的话,这将会输出以下消息:
going to setup student profile.
name : zara
student profile has been setup.
returning:zara
going to setup student profile.
age : 11
student profile has been setup.
returning:11
going to setup student profile.
exception raised
student profile has been setup.
there has been an exception: java.lang.illegalargumentexception
.....
other exception content
让我们来解释一下上面定义的在 com.tutorialspoint 中 选择所有方法的 。让我们假设一下,你想要在一个特殊的方法之前或者之后执行你的建议,你可以通过替换使用真实类和方法名称的切入点定义中的星号(*)来定义你的切入点来缩短你的执行。
<?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:config>
<aop:aspect id="log" ref="logging">
<aop:pointcut id="selectall"
expression="execution(* com.tutorialspoint.student.getname(..))"/>
<aop:before pointcut-ref="selectall" method="beforeadvice"/>
<aop:after pointcut-ref="selectall" method="afteradvice"/>
</aop:aspect>
</aop:config>
<!-- definition for student bean -->
<bean id="student" class="com.tutorialspoint.student">
<property name="name" value="zara" />
<property name="age" value="11"/>
</bean>
<!-- definition for logging aspect -->
<bean id="logging" class="com.tutorialspoint.logging"/>
</beans>
如果你想要执行通过这些更改之后的示例应用程序,这将会输出以下消息:
going to setup student profile.
name : zara
student profile has been setup.
age : 11
exception raised
.....
other exception content