Spring AOP中@DeclareParents注释中的泛型类型

时间:2014-08-05 13:41:37

标签: java spring generics aop

我正在尝试使用spring aop在Spring框架的方面使用泛型接口和泛型类,我想为使用@EntityController注释的任何类设置父接口:

@Component
@MongoProfile
@Aspect
public class EntityMongoControllerAspect<T> {

    @DeclareParents(value="@EntityController *",defaultImpl=EntityMongoController.class)
    private IEntityController<T> iEntityController;
}

但是eclipse总是抛出异常:

java.lang.IllegalStateException
at org.aspectj.weaver.ResolvedTypeMunger.<init>(ResolvedTypeMunger.java:69)
at org.aspectj.weaver.MethodDelegateTypeMunger.<init>(MethodDelegateTypeMunger.java:61)
at org.aspectj.weaver.bcel.AtAjAttributes.handleDeclareParentsAnnotation(AtAjAttributes.java:852)
at org.aspectj.weaver.bcel.AtAjAttributes.readAj5ClassAttributes(AtAjAttributes.java:384)
at org.aspectj.weaver.bcel.BcelObjectType.ensureAspectJAttrib ... ob.java:241)
at org.eclipse.core.internal.jobs.Worker.run(Worker.java:53)

Compile error: IllegalStateException thrown: Use generic type, not raw type

我的entityMongoController代码是:

public class EntityMongoController<T1> {
 ...
}

所以我怎么能做到这一点?还是有另一种选择?你必须记住我正在使用弹簧配置文件,所以使用原生aspectj不是另一种选择。

1 个答案:

答案 0 :(得分:1)

让我们暂时假设,如果您按照Spring的文档介绍如何将它集成到Spring项目中,原生AspectJ对您来说不是一个显示器。在这种情况下,你可以做这样的事情(我使用原生的AspectJ语法,因为注释风格的@AspectJ语法从可读性/表达性的角度来看有许多缺点):

与嵌入式方面的接口提供默认实现:

package de.scrum_master.app;

public interface IEntityController<T> {
    public void setEntity(T entity);
    public T getEntity();

    static aspect EntityControllerAspect {
        private T IEntityController.entity;
        public void IEntityController.setEntity(T entity) { this.entity = entity; }
        public T IEntityController.getEntity() { return entity; }

        declare parents : @EntityController * implements IEntityController;
    }
}

带有示例main方法的带注释的类,显示效果:

package de.scrum_master.app;

import java.lang.reflect.Method;

@EntityController
public class MyAnnotatedController<T> {
    public void doSomething() {
        System.out.println("Doing something");
    }

    public static void main(String[] args) {
        // Use class type directly so as to call its method
        MyAnnotatedController<String> annotatedTextController = new MyAnnotatedController<>();
        annotatedTextController.doSomething();

        // Print all declared methods (should also show interface methods introduced via ITD)
        for (Method method : annotatedTextController.getClass().getDeclaredMethods()) {
            if (!method.getName().startsWith("ajc$"))
                System.out.println(method);
        }

        // Prove that class type is compatible with interface type
        IEntityController<String> entityTextController = annotatedTextController;
        entityTextController.setEntity("foo");
        // Would not work here because generic interface type is type-safe:
        // entityTextController.setEntity(123);
        System.out.println("Entity value = " + entityTextController.getEntity());

        // Create another object and directly assign it to interface type
        IEntityController<Integer> entityNumberController = new MyAnnotatedController<>();
        entityNumberController.setEntity(123);
        // Would not work here because generic interface type is type-safe:
        // entityNumberController.setEntity("foo");
        System.out.println("Entity value = " + entityNumberController.getEntity());
    }
}

控制台输出:

Doing something
public static void de.scrum_master.app.MyAnnotatedController.main(java.lang.String[])
public java.lang.Object de.scrum_master.app.MyAnnotatedController.getEntity()
public void de.scrum_master.app.MyAnnotatedController.setEntity(java.lang.Object)
public void de.scrum_master.app.MyAnnotatedController.doSomething()
Entity value = foo
Entity value = 123

如果您不理解我的代码段,请随时提出进一步的问题。