2)META-INF/jboss-aop.xml在classpath中任何Jar文件中在META-INF/下的jboss-aop.xml的都会被加载。Jboss AOP使用ClassLoader.getResoures("META-INF/jboss-aop.xml")来获取所有的文件。
<aspect class="org.jboss.MyAspect"/>
在基本的声明总,需要指定aspect类的全名。如果需要通过AspectManager来引用aspect,aspect的name与class name一致。aspect的默认scope为PER_VM。需要注意的是,aspect实例并不是发布时创建,而是按需创建。
<aspect class="org.jboss.MyAspect" scope="PER_VM"/>
scope属性定义了aspect实例在什么时候创建。
名字 | 描述 |
PER_VM | 整个JVM中每个aspect类只分配一个实例 |
PER_CLASS | 为一个普通class仅分配一个aspect class实例。如果aspect的一个advice绑定到普通类上,此实例才被创建。 |
PER_INSTANCE | 为每个advice实例对象创建一个aspect实例。如果一个method有一个advice被匹配,advice的实例会被分配,此时会有一个aspect被创建。 |
PER_JOINPOINT | 为每个joinpoint advice创建一个aspect实例。如果joinpoint是静态成员,仅会有一个aspect实例被创建。 |
PER_CLASS_JOINPOINT | 为每个advice joinpoint创建一个aspect实例,次aspect实例被joinpioint类的每个实例共享。 |
<aspect class="org.jboss.SomeAspect">
<attribute name="SomeIntValue">55</attribute>
<advisor-attribute name="MyAdvisor"/>
<instance-advisor-attribute name="MyInstanceAdvisor"/>
<joinpoint-attribute name="MyJoinpoint"/>
</aspect>
aspect默认使用JavaBean风格配置。<attribute>标签将委托给set方法,且转换类型。此外可以注入AOP运行时构造器给aspect,此处有类型属性。
<advisor-attribute> org.jboss.aop.Advisor
<instance-advisor-attribute> org.jboss.aop.InstanceAdvisor
<joinpoint-attribute> org.jboss.aop.joinpoint.Joinpoint
<aspect class="org.jboss.SomeAspect">
<attribute name="SomeIntValue">55</attribute>
<advisor-attribute name="MyAdvisor"/>
<instance-advisor-attribute name="MyInstanceAdvisor"/>
<joinpoint-attribute name="MyJoinpoint"/>
</aspect>
public class SomeAspect {
public SomeAspect() {}
public void setSomeIntValue(int val) {...}
public void setMyAdvisor(org.jboss.aop.Advisor advisor) {...}
public void setMyInstanceAdvisor(org.jboss.aop.InstanceAdvisor advisor) {...}
public void setMyJoinpoint(org.jboss.aop.joinpoint.Joinpoint joinpoin) {...}
}
<aspect name="MyAspect" factory="org.jboss.AspectConfigFactory" scope="PER_CLASS">
<some-arbitrary-xml>value</some-arbitrary-xml>
</aspect>
<interceptor class="org.jboss.MyInterceptor" scope="PER_VM"/>
<interceptor class="org.jboss.SomeInterceptor">
<attribute name="SomeIntValue">55</attribute>
<advisor-attribute name="MyAdvisor"/>
<instance-advisor-attribute name="MyInstanceAdvisor"/>
<joinpoint-attribute name="MyJoinpoint"/>
</interceptor>
<interceptor name="MyAspect" factory="org.jboss.InterceptorConfigFactory" scope="PER_CLASS">
<some-arbitrary-xml>value</some-arbitrary-xml>
</interceptor>
Interceptors的XML定义与aspect一致。
<bind pointcut="execution(void Foo->bar())">
<interceptor-ref name="org.jboss.MyInterceptor/>
<before name="beforeAdvice" aspect="org.jboss.MyAspect"/>
<around name="aroundAdvice" aspect="org.jboss.MyAspect"/>
<after name="afterAdvice" aspect="org.jboss.MyAspect"/>
<throwing name="throwingAdvice" aspect="org.jboss.MyAspect"/>
<finally name="finallyAdvice" aspect="org.jboss.MyAspect"/>
<advice name="trace" aspect="org.jboss.MyAspect"/>
</bind>
bind:标签用来绑定advice,或interceptor到joinpoint。pointcut属性必选,至少一个advice或interceptor-ref被定义。
interceptor-ref:它 必须引用已存在的interceptor定义。<stack name="stuff">
<interceptor class="SimpleInterceptor1" scope="PER_VM"/>
<advice name="trace" aspect="org.jboss.TracingAspect"/>
<interceptor class="SimpleInterceptor3">
<attribute name="size">55</attribute>
</interceptor>
</stack>
<bind pointcut="execution(* POJO->*(..))">
<stack-ref name="stuff"/>
</bind>
<pointcut name="publicMethods" expr="execution(public * *->*(..))"/>
<pointcut name="staticMethods" expr="execution(static * *->*(..))"/>
<bind pointcut="publicMethods AND staticMethods">
<interceptor-ref name="tracing"/>
</bind>
<introduction class="org.acme.MyClass">
<interfaces>java.io.Serializable</interfaces>
</introduction>
上面的声明,org.acme.Myclass将会被强制实现java.io.Serializalbe接口。class属性可以是通配符,但不能是布尔表达式。如果需要更加复杂的类型表达式,可以使用expr属性替代。
<introduction expr="has(* *->@test(..)) OR class(org.acme.*)">
<interfaces>java.io.Serializable</interfaces>
</introduction>
expr可以是在typedef表达式内允许的任何类型表达式
<introduction class="org.acme.MyClass">
<mixin>
<interfaces>java.io.Externalizable</interfaces>
<class>org.acme.ExternalizableMixin</class>
<construction>new org.acme.ExternalizableMixin(this)</construction>
</mixin>
</introduction>
interface:引入的接口清单
<cflow-stack name="recursive2">
<called expr="void POJO->recursive(int)"/>
<called expr="void POJO->recursive(int)"/>
<not-called expr="void POJO->recursive(int)"/>
</cflow-stack>
cflow-statck有name,和多个called和not-called元素,它定义了使用Java call stack各自构造器或方法调用。expr属性必须是方法或构造器表达式。called,expr必须出现在call statck内。not-called,不允许在stack内有指定的表达式。上例中,如果栈内有两个且仅有两个recursive方法调用,会触发cflow-stack。可以在bind元素中通过cflow属性引用它。
<bind pointcut="execution(void POJO->recursive(int))"
cflow="recursive2 AND !cflow2">
<interceptor class="SimpleInterceptor"/>
</bind>
<typedef name="jmx" expr="class(@org.jboss.jmx.@MBean) OR \
has(* *->org.jboss.jmx.@ManagedOperation) OR
has(* *->org.jboss.jmx.@ManagedAttribute)"/>
<pointcut name="stuff" expr="execution(* $typedef{jmx}->*(..))"/>
<introduction expr="class($typedef{jmx})">
typedef允许定义复杂类型的表达式,然后在pointcut中使用。
package org.jboss.aop.pointcut;
import org.jboss.aop.joinpoint.Invocation;
public interface DynamicCFlow
{
boolean shouldExecute(Invocation invocation);
}
<dynamic-cflow name="simple" class="org.jboss.SimpleDynamicCFlow"/>
<bind expr="execution(void Foo->bar())" cflow="simple">
<prepare expr="execution(void Foo-bar())"/>