JBoss.org Community Documentation
Sometimes when we want to introduce/force a new class to implement an interface, that interface introduces new methods to a class. The class needs to implement these methods to be valid. In these cases a mixin class is used. The mixin class must implement the methods specified by the interface(s) and the main class can then implement these methods and delegate to the mixin class.
Mixins are created using the @Mixin annotation. Only methods within a class
annotated with
@Aspect
or
@InterceptorDef
can be annotated with
@Mixin
. The annotated method has
The declaration of
org.jboss.aop.Mixin
:
package org.jboss.aop; @Target({ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) public @interface Mixin { Class target() default java.lang.Class.class; String typeExpression() default ""; Class[] interfaces(); boolean isTransient() default true; }
The parameters of
@Mixin
are:
target
, the name of the class we want to introduce
an interface to.
typeExpression
, a type expression that should resolve
to one or more classes we want to introduce an interface to.
interfaces
, an array of the interfaces we want to introduce,
implemented by the mixin class.
isTransient
. Internally AOP makes the main class keep a
reference to the mixin class, and this sets if that reference should be
transient or not. The default is true.
target
or
typeExpression
has to be specified,
but not both.
An example aspect using
@Mixin
follows:
package com.mypackage; import org.jboss.aop.Mixin; import com.mypackage.POJO; @Aspect (scope=org.jboss.aop.advice.Scope.PER_VM) public class IntroductionAspect { @Mixin (target=com.mypackage.POJO.class, interfaces={java.io.Externalizable.class}) public static ExternalizableMixin createExternalizableMixin(POJO pojo) { return new ExternalizableMixin(pojo); } }
Since this is slightly more complex than the previous examples we have seen, the
POJO
and
ExternalizableMixin
classes are
included here.
package com.mypackage; public class POJO { String stuff; }
package com.mypackage; import java.io.Externalizable; import java.io.IOException; import java.io.ObjectInput; import java.io.ObjectOutput; public class ExternalizableMixin implements Externalizable { POJO pojo; public ExternalizableMixin(POJO pojo) { this.pojo = pojo; } public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { pojo.stuff = in.readUTF(); } public void writeExternal(ObjectOutput out) throws IOException { out.writeUTF(pojo.stuff); } }
This has the same effect as the following XML configuration:
<introduction classs="com.mypackage.POJO"> <mixin transient="true"> <interfaces> java.io.Externalizable </interfaces> <class>com.mypackage.ExternalizableMixin</class> <construction>IntroductionAspect.createExternalizableMixin(this)</construction> </mixin> </introduction>