本文将介绍如何在OperaMasks Studio中为基于OperaMasks的应用添加AOP支持,由于本文是介绍AOP的使用,这里不再赘述AOP的好处,以及AOP本身的知识,另外AOP只是一个概念,具体的实现有很多种,并且各种实现的工作原理和使用方法各有不同,本文不可能一一介绍,这里只介绍AspectJ和Spring AOP这两种常用的AOP实现的使用。
由于AspectJ的AOP实现是一种编译期行为,是在编译时将切入点代码织入被切入点,其开发需要特定的工具和运行时库支持,这里将分为两步来介绍。
1. 下载AspectJ开发工具的Eclipse插件
由于不同版本的AspectJ开发插件使用的Eclipse版本可能不同,而OperaMasks Studio目前是构建在Eclipse3.3版本上,所以应该下载对应Eclipse3.3版本的AJDT。
下载地址: http://www.eclipse.org/ajdt/downloads/
2. 安装插件
将上一步下载到的插件安装到OperaMasks Studio中,安装方法和Eclipse安装插件的方法基本相同。
安装后,启动OperaMasks Studio,点击菜单栏的help——>About OperaMasks Studio,如果可以看到下面的图标,则表示安装成功。
准备好开发环境后就可以进行开发了。
使用OperaMasks Studio新建一个Apusic标准工程,添加Web模块,编写一个简单的测试页面:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE HTML PUBLIC "" "">
<f:view xmlns="http://www.w3.org/1999/xhtml" xmlns:f="http://java.sun.com/jsf/core"
xmlns:w="http://www.apusic.com/jsf/widget" xmlns:layout="http://www.apusic.com/jsf/layout"
xmlns:h="http://java.sun.com/jsf/html" xmlns:ajax="http://www.apusic.com/jsf/ajax"
renderKitId="AJAX">
<w:head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</w:head>
<w:page title="Insert title here">
<w:form>
<w:button id="hello" />
<h:outputText id="out" />
</w:form>
</w:page>
</f:view>
对应的Managed Bean:
@ManagedBean(name = "indexBean", scope = ManagedBeanScope.REQUEST)
public class IndexBean implements Serializable {
@Bind
private String out;
@Action
public void hello() {
out = "Hello";
System.out.println("IndexBean.hello()");
}
}
测试刚写的页面,正常运行,页面上按钮下方显示“Hello”,控制台输出:
2009-02-12 20:30:05 信息 [con.out] IndexBean.hello()
下面我们要使用Aspect在方法hello()执行前后各打印一条信息。新建一个Aspect,输入Aspect名字,新建向导出现错误提示:
看来我们的开发环境还没完全准备好,工具已经支持了AspectJ开发,但工程却不支持。不过,没关系,Eclipse的工程属性是由工程根目录下的“.project”和“.classpath”决定的。我们在OperaMasks Studio中新建一个Aspect Project,查看其“.project”和“.classpath”文件,我们发现下面的定义:
在“.project”中
<buildCommand>
<name>org.eclipse.ajdt.core.ajbuilder</name>
<arguments>
</arguments>
</buildCommand>
<nature>org.eclipse.ajdt.ui.ajnature</nature>
在“.classpath”中
<classpathentry kind="con" path="org.eclipse.ajdt.core.ASPECTJRT_CONTAINER"/>
好了,知道了这两点,我们就可以给Apusic标准工程添加Aspect支持了,我们将上面的定义添加到Apusic标准工程的对应文件中,就完成了Apusic标准工程对Aspect的支持。下面我们继续上面的工作,新建一个Aspect:
public aspect AspectTest {
pointcut greeting():
execution(void IndexBean.hello());
before(): greeting() {
System.out.println("AspectTest.before()");
}
after(): greeting() {
System.out.println("AspectTest.after()");
}
}
建好Aspect后,我们发现在bofore()和after()和IndexBean的hello()方法的左边出现了小图标,表示成功切入。如果出现警告图标,警告未成功切入,请clean一下工程。
运行测试页面,点击按钮,页面出现异常,查看异常信息,是AspectJ相关的jar包缺失,原因很简单,编译时类库是不会部署到应用中的,所以我们要把相关的jar包放在WEB-INF/lib目录下,重新部署应用,运行页面,点击按钮,页面上按钮下方显示“Hello”,控制台输出:
2009-02-13 09:10:21 信息 [con.out] AspectTest.before()
2009-02-13 09:10:21 信息 [con.out] IndexBean.hello()
2009-02-13 09:10:21 信息 [con.out] AspectTest.after()
OK,正如我们的预期,切入点正常执行,我们成功的在Apusic标准工程中使用了AspectJ。关于AspectJ在OperaMasks应用中的使用的介绍也到此结束,这里没有介绍更复杂的AspectJ使用,只是考虑到本文的初衷只是介绍如何在Apusic标准工程中使用AspectJ,至于AspectJ本身的语法、使用方法等不是本文关注的重点。
由于OperaMasks可以和Spring无缝集成,参考http://www.operamasks.org/articles/magic-6/html_single/ 。所以Spring AOP在OperaMasks应用中的使用也是顺理成章,这里只给出一个简单的例子供大家参考。
1. 首先新建一个Apusic标准工程,分别添加WEB模块与添加Spring支持。
2. 编写三个拦截器类:HelloBeforeAdvice.java、HelloInterceptor.java、HelloAfterAdvice.java :
public class HelloBeforeAdvice implements MethodBeforeAdvice {
public void before(Method arg0, Object[] arg1, Object arg2)
throws Throwable {
System.out.println("HelloBeforeAdvice.before()");
}
}
public class HelloInceterceptor implements MethodInterceptor {
public Object invoke(MethodInvocation arg0) throws Throwable {
System.out.println("HelloInceterceptor.invoke()");
return null;
}
}
public class HelloAfterAdvice implements AfterReturningAdvice {
public void afterReturning(Object arg0, Method arg1, Object[] arg2,
Object arg3) throws Throwable {
System.out.println("HelloAfterAdvice.afterReturning()");
}
}
3. 在appletcationContext.xml文件配置这三个拦截器:
<bean id="service" class="test.ServiceImp" />
<!-- 第一个拦截器-->
<bean id="myAdvice" class="test.HelloBeforeAdvice" />
<!-- 第二个拦截器-->
<bean id="myAroundInterceptor" class="test.HelloInterceptor" />
<!-- 将拦截器包装成Advisor,该对象还确定代理对怎样的方法增加处理-->
<bean id="runAdvisor"
class="org.springframework.aop.support.RegexpMethodPointcutAdvisor"/>
<!-- advice属性确定处理bean-->
<property name="advice">
<!-- 此处的处理bean定义采用嵌套bean,也可引用容器的另一个bean-->
<bean class="test.HelloAfterAdvice" />
</property>
<!-- patterns确定正则表达式模式-->
<property name="patterns">
<list>
<!-- 确定正则表达式列表-->
<value>.*hello.*</value>
</list>
</property>
</bean>
4. 编写需要被拦截的数据对象,本实例中用一个简单的接口和实现模拟Spring管理的业务逻辑:
public interface IService {
void hello();
void hi();
}
public class ServiceImp implements IService {
public void hello() {
System.out.println("ServiceImp.hello()");
}
public void hi() {
System.out.println("ServiceImp.hi()");
}
}
5. 在applicationContext.xml文件配置数据对象:
<!-- 使用ProxyFactoryBean 产生代理对象-->
<bean id="person"
class="org.springframework.aop.framework.ProxyFactoryBean">
<!-- 代理对象所实现的接口-->
<property name="proxyInterfaces">
<value>test.IService</value>
</property>
<!-- 设置目标对象-->
<property name="target">
<ref local="service" />
</property>
<!-- 代理对象所使用的拦截器-->
<property name="interceptorNames">
<list>
<value>runAdvisor</value>
<value>myAdvice</value>
<value>myAroundInterceptor</value>
</list>
</property>
</bean>
6. 编写测试页面:
页面:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE HTML PUBLIC "" "">
<f:view xmlns="http://www.w3.org/1999/xhtml" xmlns:f="http://java.sun.com/jsf/core"
xmlns:w="http://www.apusic.com/jsf/widget" xmlns:layout="http://www.apusic.com/jsf/layout"
xmlns:h="http://java.sun.com/jsf/html" xmlns:ajax="http://www.apusic.com/jsf/ajax"
renderKitId="AJAX">
<w:head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</w:head>
<w:page title="Insert title here">
<w:form>
<w:button id="hello" />
<h:outputText id="out" />
</w:form>
</w:page>
</f:view>
Managed Bean:
@ManagedBean(name = "testAOPBean", scope = ManagedBeanScope.SESSION)
public class TestAOPBean implements Serializable {
@Inject(value = "#{person}")
private IService service;
@Bind
private String out;
@Action
public void hello() {
out = "Hello";
service.hello();
System.out.println("TestAOPBean.hello()");
service.hi();
}
}
运行页面,点击按钮,页面上按钮下方显示“Hello”,控制台输出:
2009-02-13 10:03:18 信息 [con.out] HelloBeforeAdvice.before()
2009-02-13 10:03:18 信息 [con.out] HelloInceterceptor.invoke()
2009-02-13 10:03:18 信息 [con.out] HelloAfterAdvice.afterReturning()
2009-02-13 10:03:18 信息 [con.out] TestAOPBean.hello()
2009-02-13 10:03:18 信息 [con.out] HelloBeforeAdvice.before()
2009-02-13 10:03:18 信息 [con.out] HelloInceterceptor.invoke()
跟预期的一样,使用Spring AOP成功。