我这里的Seam项目使用war方式部署,所以seam的action是POJO而不是EJB。
下面是最终的使用效果,在类上添加自定义的@MySeam, 在需要控制的Field上添加自定义的@SuperString
@Name("productAction")
@MySeam
public class ProductAction {
@SuperString
String name;
@SuperString(postfix="-product")
String product;
... ...
}
下面说说具体怎么做,先写一个Interceptor如下例
import org.jboss.seam.annotations.intercept.AroundInvoke;
import org.jboss.seam.annotations.intercept.Interceptor;
import org.jboss.seam.security.SecurityInterceptor;
import org.jboss.seam.core.EventInterceptor;
import org.jboss.seam.core.MethodContextInterceptor;
import org.jboss.seam.intercept.AbstractInterceptor;
import org.jboss.seam.intercept.InvocationContext;
import org.jboss.seam.util.Reflections;
/**
* MySeamInterceptor will be invoke
* before MethodContextInterceptor, EventInterceptor
* after SecurityInterceptor
*/
@Interceptor(around = {
MethodContextInterceptor.class,
EventInterceptor.class,
},
within = SecurityInterceptor.class
)
public class MySeamInterceptor extends AbstractInterceptor {
private static final long serialVersionUID = -3064515871691261357L;
private static final LogProvider log = Logging.getLogProvider(MySeamInterceptor.class);
private boolean reentrant; //OK, since all Seam components are single-threaded
@AroundInvoke
public Object aroundInvoke(InvocationContext invocation) throws Exception {
if (reentrant) {
if (log.isTraceEnabled()) {
log.trace("reentrant call to component: " + getComponent().getName());
}
return invocation.proceed();
} else {
reentrant = true;
try {
//Component component = getComponent();
changeStringValue(invocation.getTarget());
// you can add more method in here.
return invocation.proceed();
} finally {
reentrant = false;
}
}
}
private void changeStringValue(Object target) {
Field[] fieldArray = target.getClass().getDeclaredFields();
for (Field field : fieldArray) {
if (!field.isAccessible()) {
field.setAccessible(true);
}
if (field.isAnnotationPresent(SuperString.class)) {
SuperString superStr = field.getAnnotation(SuperString.class);
String newValue = System.currentTimeMillis() + superStr.postfix();
setFieldValue(field, target, newValue);
}
}
}
/**
* Set field value.
* @param field The value will be set for this field
* @param target The field belongs to this object
* @param value The field's value
*/
private void setFieldValue(Field field, Object target, Object value) {
try {
Reflections.set(field, target, value);
} catch (Exception e) {
throw new IllegalArgumentException("MySeamInterceptor.setFieldValue(): " +
target.getClass() + "; field: " + field.getName(), e);
}
}
}
继承AbstractInterceptor是比较容易的方式,@AroundInvoke是必须的。
这里的逻辑很简单:在所有标注了@MySeam的类中,寻找标注了@SuperString的Field,并给其赋值。
为了使用MySeamInterceptor,我们需要为它定义一个Annotation,如下:
import org.jboss.seam.annotations.intercept.Interceptors;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Interceptors(MySeamInterceptor.class)
public @interface MySeam {
}
最后是@SuperString,这个就不多说了。
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface SuperString {
String postfix() default "-super";
}