Один из возможных вариантов — использовать aspectj с его возможностью декларировать аннотации и возможности Spring переплетение аспектов времени загрузки.
Я предполагаю, что аннотации не могут быть объявлены условно, но вы всегда можете скомпилировать их в отдельный jar, который можно положить в classpath в зависимости от определенного окружения, чтобы weaver во время загрузки смог его найти.
ОБНОВЛЕНИЕ
Хотя здесь есть много полезных ответов, я нашел отключение/включение аннотаций довольно интересным, играя с аспектом, поэтому пример ниже.
Последние версии аспекта поддерживают удаление аннотаций, но пока эта возможность доступна только для аннотаций полей, поэтому весьма полезный способ — вообще не объявлять аннотации, а если их нужно включить — поставить банку с прекомпилированными аспектами, которые включит аннотации в путь к классам, как я упоминал ранее.
ОБРАЗЕЦ
Первая банка
Основной класс
package org.foo.bar;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Main {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("/applicationContext.xml");
MyClass myObj = context.getBean("myObj", MyClass.class);
System.out.println(myObj);
System.out.println(myObj.getValue1());
System.out.println(myObj.getValue2());
}
}
Класс, в котором мы будем объявлять аннотации
package org.foo.bar;
public class MyClass {
@MyAnn("annotated-field-1")
private String field1;
private String field2;
@MyAnn("annotated-method-1")
public String getValue1() {
String value = null;
try {
MyAnn ann = getClass().getDeclaredMethod("getValue1").getAnnotation(MyAnn.class);
if(ann != null) {
value = ann.value();
}
} catch (NoSuchMethodException e) {
throw new RuntimeException(e);
}
return value;
}
public String getValue2() {
String value = null;
try {
MyAnn ann = getClass().getDeclaredMethod("getValue2").getAnnotation(MyAnn.class);
if(ann != null) {
value = ann.value();
}
} catch (NoSuchMethodException e) {
throw new RuntimeException(e);
}
return value;
}
@Override
public String toString() {
String field1 = null;
try {
MyAnn ann = getClass().getDeclaredField("field1").getAnnotation(MyAnn.class);
if(ann != null) {
field1 = ann.value();
}
} catch (NoSuchFieldException e) {
throw new RuntimeException(e);
}
String field2 = null;
try {
MyAnn ann = getClass().getDeclaredField("field2").getAnnotation(MyAnn.class);
if(ann != null) {
field2 = ann.value();
}
} catch (NoSuchFieldException e) {
throw new RuntimeException(e);
}
StringBuilder sb = new StringBuilder();
sb.append("MyClass");
sb.append("{field1='").append(field1).append('\'');
sb.append(", field2='").append(field2).append('\'');
sb.append('}');
return sb.toString();
}
}
Сама аннотация
package org.foo.bar;
import java.lang.annotation.Documented;
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;
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
@Target({ElementType.FIELD, ElementType.METHOD})
public @interface MyAnn {
String value();
}
Контекст приложения
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd">
<context:load-time-weaver />
<bean id="myObj" class="org.foo.bar.MyClass" />
</beans>
Вторая банка
Аспект
package org.foo.bar;
public aspect ToggleAnnotationAspect {
declare @field : private String org.foo.bar.MyClass.field1 : -@MyAnn;
declare @field : private String org.foo.bar.MyClass.field2 : @MyAnn("annotated-field-2");
declare @method : public String org.foo.bar.MyClass.getValue2() : @MyAnn("annotated-method-2");
}
META-INF/aop.xml
<?xml version="1.0"?>
<aspectj>
<aspects>
<aspect name="org.foo.bar.ToggleAnnotationAspect"/>
</aspects>
</aspectj>
Запуск приложения без второй банки в пути к классам
java -javaagent:spring-instrument-3.1.3.RELEASE.jar \
-classpath app1.jar;<rest_of_cp> org.foo.bar.Main
будет печатать
MyClass{field1='annotated-field-1', field2='null'}
annotated-method-1
null
Запуск приложения со второй банкой в пути к классам
java -javaagent:spring-instrument-3.1.3.RELEASE.jar \
-classpath app1.jar;app1-aspects.jar;<rest_of_cp> org.foo.bar.Main
будет печатать
MyClass{field1='null', field2='annotated-field-2'}
annotated-method-1
annotated-method-2
Таким образом, никаких изменений в исходном коде приложения не производилось.
person
szhem
schedule
21.11.2012