先上代码,对代码进行详细介绍然后再引入相关的概念问题。
组建代码的时候出现了许多问题:例如:Error occured processing XML 'org/springframework/aop/aspectj/AspectJMethodBeforeAdvice'. See Error Log for more details。对于这个问题是缺少三种jart包,分别是
Aspectjrt
,
Aspectj-weaver
,
aop-alliance。导入这三种jar包就可以解决相关的问题。
第一次搭建xml,面向切面编程的时候会出现各种各样的问题,除了上面所介绍的问题之外,还存在下面一个问题:
Exception in thread "main" java.lang.ClassCastException: com.sun.proxy.$Proxy3 cannot be cast to taskImpl.Volunter
此时需要做的是:在aop:config中配置proxy-target-class="true"。
整个项目的代码如下所示:
Bean.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-4.0.xsd">
<bean id="magician" class="taskImpl.Magician"/>
<bean id="volunter11" class="taskImpl.Volunter"/>
<aop:config proxy-target-class="true">
<aop:aspect ref="magician"><!--定义一个切面,其中ref所指向的是SPring中的通知,通知概述了切面主要完成的工作-->
<aop:pointcut id="person" expression="execution(* coreTask.Person.thinkOfSomething(String)) and args(thoughts)"/><!--*与表达式之间要存在空格--><!--主要完成了相关切点的相关定义,在thinkOfSomething中定义切点,切点与通知共同组成切面,thoughts为接收的参数-->
<aop:before pointcut-ref="person"
method="interceptThoughts"
arg-names="thoughts"/><!--其实最让人困惑的还是相关的调用逻辑,其中当切点expreesion所指向的方法被调用的时候,method方法被触发,其中thoughts为上面接收的参数,该参数传递给method所指向的方法-->
</aop:aspect>
</aop:config>
</beans>
<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-4.0.xsd">
<bean id="magician" class="taskImpl.Magician"/>
<bean id="volunter11" class="taskImpl.Volunter"/>
<aop:config proxy-target-class="true">
<aop:aspect ref="magician"><!--定义一个切面,其中ref所指向的是SPring中的通知,通知概述了切面主要完成的工作-->
<aop:pointcut id="person" expression="execution(* coreTask.Person.thinkOfSomething(String)) and args(thoughts)"/><!--*与表达式之间要存在空格--><!--主要完成了相关切点的相关定义,在thinkOfSomething中定义切点,切点与通知共同组成切面,thoughts为接收的参数-->
<aop:before pointcut-ref="person"
method="interceptThoughts"
arg-names="thoughts"/><!--其实最让人困惑的还是相关的调用逻辑,其中当切点expreesion所指向的方法被调用的时候,method方法被触发,其中thoughts为上面接收的参数,该参数传递给method所指向的方法-->
</aop:aspect>
</aop:config>
</beans>
aop:before表示在切点所在的方法调用之前调用通知(切面)中的相关方法,aop:after-return表示在切点所在的方法返回之后(也就是调用完后调用通知里面的相关方法,这一点的相关验证见源码:)
接口的主要文件:MindReader与Person主要的接口如下:
package coreTask;
public interface MindReader {
public void interceptThoughts(String thoughts);
public String getThoughts();
}
public interface MindReader {
public void interceptThoughts(String thoughts);
public String getThoughts();
}
package coreTask;
public interface Person {
public void thinkOfSomething(String thoughts);
}
相关的实现类如下:
public interface Person {
public void thinkOfSomething(String thoughts);
}
相关的实现类如下:
package taskImpl;
import coreTask.MindReader;
public class Magician implements MindReader {
private String thoughts;
@Override
public void interceptThoughts(String thoughts) {
// TODO Auto-generated method stub
System.out.println("Intercepting volunter's thoughts");
this.thoughts=thoughts;
}
@Override
public String getThoughts() {
// TODO Auto-generated method stub
return thoughts;
}
}
import coreTask.MindReader;
public class Magician implements MindReader {
private String thoughts;
@Override
public void interceptThoughts(String thoughts) {
// TODO Auto-generated method stub
System.out.println("Intercepting volunter's thoughts");
this.thoughts=thoughts;
}
@Override
public String getThoughts() {
// TODO Auto-generated method stub
return thoughts;
}
}
package taskImpl;
import coreTask.Person;
public class Volunter implements Person
{
private String thoughts;
@Override
public void thinkOfSomething(String thoughts) {
// TODO Auto-generated method stub
this.thoughts=thoughts;
}
public String getThoughts()
{
return thoughts;
}
}
import coreTask.Person;
public class Volunter implements Person
{
private String thoughts;
@Override
public void thinkOfSomething(String thoughts) {
// TODO Auto-generated method stub
this.thoughts=thoughts;
}
public String getThoughts()
{
return thoughts;
}
}
测试程序:
package TestUnit;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import taskImpl.Magician;
import taskImpl.Volunter;
public class Main {
public static void main(String[]args)
{
ApplicationContext context=new ClassPathXmlApplicationContext("Bean.xml");
Volunter person=(Volunter)context.getBean("volunter11");
Magician magician=(Magician)context.getBean("magician");
person.thinkOfSomething("I'm handsome");
System.out.println("MindReader read your mind:"+magician.getThoughts());
}
}
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import taskImpl.Magician;
import taskImpl.Volunter;
public class Main {
public static void main(String[]args)
{
ApplicationContext context=new ClassPathXmlApplicationContext("Bean.xml");
Volunter person=(Volunter)context.getBean("volunter11");
Magician magician=(Magician)context.getBean("magician");
person.thinkOfSomething("I'm handsome");
System.out.println("MindReader read your mind:"+magician.getThoughts());
}
}
输出:
Intercepting volunter's thoughts
MindReader read your mind:I'm handsome
MindReader read your mind:I'm handsome