Пользовательская аннотация Java, которая внедряет другой объект - PullRequest
1 голос
/ 24 февраля 2012

Я пытаюсь научиться писать собственные аннотации на Java.

В целях обучения я решил попытаться создать аннотацию, которая сделает поле доступным для класса с помощью аннотации, то есть: внедрение, но не обязательное использование в качестве одиночного элемента, чтобы сделать его немного более простым (я думаю), но это также приветствуется.

======================================= КЛАСС 1 ====== ===========================

import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;


@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface AutoInject {

}

======================================= КЛАСС 2 ====== ===========================

// The class to be injected in Main.java
public class TestClass0 {

    void printSomething(){
        System.out.println("PrintSomething: TestClass0");
    }

}

======================================= КЛАСС 3 ====== ===========================

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;

public class Main {

    TestClass0 ts0; 
    // Injecting here!!
    @AutoInject
    public TestClass0 getTso() {
        return ts0;
    }
    public void setTso(TestClass0 ts) {
        ts0 = ts;
    }

    public static void main(String[] args) {
        performAnnotationScanOnClass (Main.class);

        // Create instance 
        Main main = new Main();     
        main.getTso().printSomething();

    }

    public static void performAnnotationScanOnClass(Class<?> clazz) {
        Field[] fields = clazz.getDeclaredFields();

        for ( Field field : fields ) {

             Annotation[] annotations = field.getAnnotations();
             for (Annotation annotation : annotations) {

                 if ( annotation instanceof AutoInject ) {
                     AutoInject autoInject = (AutoInject) annotation;

//                     if ( field.get( ... ) == null )
//                         field.set( ... , value)
                 }

             }

        }
    }

}

Как вы можете видеть в статическом void main () ... Я пытаюсь вызвать метод в TestClass0, ожидая его доступности. Я знаю, что вышеупомянутое уже близко к завершению, но я только начал изучать аннотации и хотел бы получить ваше руководство.

Как мы можем запустить фрагмент кода, который инициализирует свойство либо в new , либо при вызове get метода . Использование аннотаций. Я думаю без изменения вызывать метод.

Спасибо!

1 Ответ

3 голосов
/ 24 февраля 2012

Вы перебираете поля в коде сканирования, но определенные вами аннотации допускают аннотацию только для методов.Это означает, что вы никогда не увидите аннотации.

Похоже, вы пытаетесь использовать поля, как будто они были свойствами Java-бинов.Вот пример внедрения сеттера с использованием ваших классов AutoInject и TestClass0 как есть:

Main.java:

import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;

public class Main {
    public TestClass0 ts0;

    public TestClass0 getTso() {
        return ts0;
    }

    @AutoInject
    public void setTso(TestClass0 ts) {
        ts0 = ts;
    }

    public static void main(String[] args) {
        // Create instance
        Main main = new Main();
        injectDependencies(main).getTso().printSomething();

    }

    public static <T> T injectDependencies(final T obj) {
        try {
            Class clazz = obj.getClass();
            BeanInfo beanInfo = Introspector.getBeanInfo(clazz);

            for (PropertyDescriptor pd : beanInfo.getPropertyDescriptors()) {
                Method readMethod = pd.getReadMethod();
                Method writeMethod = pd.getWriteMethod();

                if (writeMethod == null) {
                    continue;
                }

                Object existingVal = pd.getReadMethod().invoke(obj);
                if (existingVal == null) {
                    for (Annotation annotation : writeMethod.getAnnotations()) {
                        if (annotation instanceof AutoInject) {
                            Class propertyType = pd.getPropertyType();
                            writeMethod.invoke(obj, propertyType.newInstance());
                        }
                    }
                }
            }
        } catch (Exception e) {
            // do something intelligent :)
        }
        return obj;
    }

}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...