我们用Hello的例子来诠释Spring AOP 2.0 的特性。
Hello
- public interface Hello {
- void sayHelloBefore();
- void sayHelloAfter();
- void sayHelloAround();
- }
public interface Hello {
void sayHelloBefore();
void sayHelloAfter();
void sayHelloAround();
}
SayHello
- public class SayHello implements Hello{
- /**
- *
- */
- public void sayHelloBefore() {
- System.out.println("say Hello before!");
- }
- /**
- *
- */
- public void sayHelloAfter() {
- System.out.println("say Hello after!");
- }
- /**
- *
- */
- public void sayHelloAround() {
- System.out.println("say Hello around!");
- }
- }
public class SayHello implements Hello{
/**
*
*/
public void sayHelloBefore() {
System.out.println("say Hello before!");
}
/**
*
*/
public void sayHelloAfter() {
System.out.println("say Hello after!");
}
/**
*
*/
public void sayHelloAround() {
System.out.println("say Hello around!");
}
}
Before
- public class Before {
- public void invoke(JoinPoint joinPoint) {
- System.out.println("Before:" + joinPoint.getSignature().getName());
- }
- }
public class Before {
public void invoke(JoinPoint joinPoint) {
System.out.println("Before:" + joinPoint.getSignature().getName());
}
}
After
- public class After {
- public void invoke(JoinPoint joinPoint) {
- System.out.println("After:" + joinPoint.getSignature().getName());
- }
- }
public class After {
public void invoke(JoinPoint joinPoint) {
System.out.println("After:" + joinPoint.getSignature().getName());
}
}
Around
- public class Around {
- public Object invoke(ProceedingJoinPoint joinPoint) throws Throwable {
- System.out.println("Around:" + joinPoint.getSignature().getName());
- return joinPoint.proceed();
- }
- }
public class Around {
public Object invoke(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("Around:" + joinPoint.getSignature().getName());
return joinPoint.proceed();
}
}
Introduction
- public class Introduction {
- public Object invoke(ProceedingJoinPoint joinPoint) throws Throwable {
- System.out
- .println("Introduction:" + joinPoint.getSignature().getName());
- return joinPoint.proceed();
- }
- }
public class Introduction {
public Object invoke(ProceedingJoinPoint joinPoint) throws Throwable {
System.out
.println("Introduction:" + joinPoint.getSignature().getName());
return joinPoint.proceed();
}
}
Introduction 引入的作用在于是一个类在不做任何代码修改的前提下,拥有另一套方法,或者说具备另一套本领,比如我们现在就想让这个实现了Hello接口的SayHello类拥有Ok接口的方法
- public interface Ok {
- void sayOk();
- }
public interface Ok {
void sayOk();
}
IntroductionOk 首先要解决上述接口Ok的实现
- public class IntroductionOk implements Ok {
- @Override
- public void sayOk() {
- System.out.println("Ok!");
- }
- }
public class IntroductionOk implements Ok {
@Override
public void sayOk() {
System.out.println("Ok!");
}
}
AllTest
- public class AllTest {
- private ApplicationContext app;
- /**
- * @throws java.lang.Exception
- */
- @Before
- public void setUp() throws Exception {
- app = new ClassPathXmlApplicationContext("applicationContext.xml");
- }
- @Test
- public final void testHello() {
- Hello hello = (Hello) app.getBean("hello");
- hello.sayHelloBefore();
- hello.sayHelloAfter();
- hello.sayHelloAround();
- // 由于对Hello接口进行了引入,
- // 使得实现了Hello接口的类可以具备Ok接口的功能。
- // 同时,我们可以拦截这个方法让他执行其他我们需要执行的操作
- hello.sayHelloIntroduction();
- ((Ok) hello).sayOk();
- }
- }
public class AllTest {
private ApplicationContext app;
/**
* @throws java.lang.Exception
*/
@Before
public void setUp() throws Exception {
app = new ClassPathXmlApplicationContext("applicationContext.xml");
}
@Test
public final void testHello() {
Hello hello = (Hello) app.getBean("hello");
hello.sayHelloBefore();
hello.sayHelloAfter();
hello.sayHelloAround();
// 由于对Hello接口进行了引入,
// 使得实现了Hello接口的类可以具备Ok接口的功能。
// 同时,我们可以拦截这个方法让他执行其他我们需要执行的操作
hello.sayHelloIntroduction();
((Ok) hello).sayOk();
}
}
关于表达式符号
.*+定义目标为包下的所有类
+定义目标为该接口的所有实现类
- <?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="hello"
- class="org.zlex.aop.SayHello" />
- <!-- after -->
- <bean
- id="after"
- class="org.zlex.aop.After" />
- <aop:config>
- <aop:pointcut
- id="afterPoint"
- expression="execution(* org.zlex.aop.Hello.sayHelloAfter(..))" />
- <aop:aspect
- id="afterAspect"
- ref="after">
- <aop:after
- method="invoke"
- pointcut-ref="afterPoint" />
- </aop:aspect>
- </aop:config>
- <!-- before -->
- <bean
- id="before"
- class="org.zlex.aop.Before" />
- <aop:config>
- <aop:pointcut
- id="beforePoint"
- expression="execution(* org.zlex.aop.Hello.sayHelloBefore(..))" />
- <aop:aspect
- id="beforeAspect"
- ref="before">
- <aop:before
- method="invoke"
- pointcut-ref="beforePoint" />
- </aop:aspect>
- </aop:config>
- <!-- around -->
- <bean
- id="around"
- class="org.zlex.aop.Around" />
- <aop:config>
- <aop:pointcut
- id="aroundPoint"
- expression="execution(* org.zlex.aop.Hello.sayHelloAround(..))" />
- <aop:aspect
- id="aroundAspect"
- ref="around">
- <aop:around
- method="invoke"
- pointcut-ref="aroundPoint" />
- </aop:aspect>
- </aop:config>
- <!-- introduction -->
- <!--
- .*+是用于包下的,不是用于接口
- +定义目标为该接口的所有实现类
- -->
- <bean
- id="introduction"
- class="org.zlex.aop.Introduction" />
- <bean
- id="introductionOk"
- class="org.zlex.aop.IntroductionOk" />
- <aop:config>
- <aop:aspect
- ref="introduction">
- <aop:pointcut
- id="introductionPoint"
- expression="execution(* org.zlex.aop.Hello.sayHelloIntroduction(..))" />
- <aop:declare-parents
- implement-interface="org.zlex.aop.Ok"
- types-matching="org.zlex.aop.Hello+"
- delegate-ref="introductionOk" />
- <aop:around
- method="invoke"
- pointcut-ref="introductionPoint" />
- </aop:aspect>
- </aop:config>
- </beans>
<?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="hello" class="org.zlex.aop.SayHello" /> <!-- after --> <bean id="after" class="org.zlex.aop.After" /> <aop:config> <aop:pointcut id="afterPoint" expression="execution(* org.zlex.aop.Hello.sayHelloAfter(..))" /> <aop:aspect id="afterAspect" ref="after"> <aop:after method="invoke" pointcut-ref="afterPoint" /> </aop:aspect> </aop:config> <!-- before --> <bean id="before" class="org.zlex.aop.Before" /> <aop:config> <aop:pointcut id="beforePoint" expression="execution(* org.zlex.aop.Hello.sayHelloBefore(..))" /> <aop:aspect id="beforeAspect" ref="before"> <aop:before method="invoke" pointcut-ref="beforePoint" /> </aop:aspect> </aop:config> <!-- around --> <bean id="around" class="org.zlex.aop.Around" /> <aop:config> <aop:pointcut id="aroundPoint" expression="execution(* org.zlex.aop.Hello.sayHelloAround(..))" /> <aop:aspect id="aroundAspect" ref="around"> <aop:around method="invoke" pointcut-ref="aroundPoint" /> </aop:aspect> </aop:config> <!-- introduction --> <!-- .*+是用于包下的,不是用于接口 +定义目标为该接口的所有实现类 --> <bean id="introduction" class="org.zlex.aop.Introduction" /> <bean id="introductionOk" class="org.zlex.aop.IntroductionOk" /> <aop:config> <aop:aspect ref="introduction"> <aop:pointcut id="introductionPoint" expression="execution(* org.zlex.aop.Hello.sayHelloIntroduction(..))" /> <aop:declare-parents implement-interface="org.zlex.aop.Ok" types-matching="org.zlex.aop.Hello+" delegate-ref="introductionOk" /> <aop:around method="invoke" pointcut-ref="introductionPoint" /> </aop:aspect> </aop:config> </beans>
执行查看日志:
引用
Before:sayHelloBefore
say SayHello before!
say Hello after!
After:sayHelloAfter
Around:sayHelloAround
say Hello around!
Introduction:sayHelloIntroduction
say Hello introduction!
Ok!
仔细观察
引用
Before:sayHelloBefore
say Hello before!
在输出say Hello before!前输出Before:sayHelloBefore
引用
say Hello after!
After:sayHelloAfter
在输出say Hello after!后输出After:sayHelloAfter
Around比较特殊,可以用ProceedingJoinPoint调用proceed()方法
引用
Around:sayHelloAround
say Hello around!
引用
Introduction:sayHelloIntroduction
say Hello introduction!
Ok!
同样是Hello接口,在执行了sayHelloIntroduction方法时被拦截,同时输出say Hello introduction!,此时还可以执行Ok的方法输出
引用
Ok!
。显然,Hello的实现类多了Ok接口的本领。
Spring Beans 结构图如下:
如此这样,就可以控制AOP了,当前资料少,实例也少,继续研究!希望能做出来点实际的东西。