Java 如何确定ApplicationConfig.class是否标记有自定义注释

Java 如何确定ApplicationConfig.class是否标记有自定义注释,java,spring,spring-mvc,annotations,spring-boot,Java,Spring,Spring Mvc,Annotations,Spring Boot,我希望基于标记ApplicationConfig.class的自定义注释启用应用程序功能,如下所示: @FooBar(enabled = true) @Configuration @ComponentScan(basePackageClasses = Application.class, excludeFilters = @Filter({Controller.class, Configuration.class})) @EnableJpaRepositories("com.package.re

我希望基于标记
ApplicationConfig.class
的自定义注释启用应用程序功能,如下所示:

@FooBar(enabled = true)
@Configuration
@ComponentScan(basePackageClasses = Application.class, excludeFilters = @Filter({Controller.class, Configuration.class}))
@EnableJpaRepositories("com.package.repository")
class ApplicationConfig { 
    // Application specific configs and bean defs.
}
自定义注释名为
FooBar

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface FooBar   {
    boolean enabled() default true;
}
在应用程序启动期间,我想检测这个类(或任何其他类/bean)是否用这个注释进行了注释

这是我的尝试,部分基于此,它包括两种方法来确定正在使用注释

@Component
public class MyClassWithEventListeners implements ApplicationContextAware {

@Autowired
ApplicationEventPublisher applicationEventPublisher;

@Autowired
ApplicationContext applicationContext;


@EventListener
void contextRefreshedEvent(ContextRefreshedEvent event) {
    ApplicationContext applicationContext = event.getApplicationContext();
    applicationContext.getClassLoader();

    AutowireCapableBeanFactory autowireCapableBeanFactory = applicationContext.getAutowireCapableBeanFactory();

    String[] names = event.getApplicationContext().getBeanDefinitionNames();

    for (String name : names) {
        Object o = autowireCapableBeanFactory.getBean(name);
        if (AopProxyUtils.ultimateTargetClass(o).isAnnotationPresent(FooBar.class)) {
            System.out.println("Found class annotated with FooBar");
        }
    }

}

@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
    this.applicationContext = applicationContext;
    List<String> beanNames = getBeansWithAnnotation(FooBar.class);
    if(beanNames !=null){
        System.out.println("Found class annotated with FooBar");
    }
}

public List<String> getBeansWithAnnotation(Class<? extends Annotation> type) {
    Predicate<Map<String, Object>> filter = Predicates.alwaysTrue();
    return getBeansWithAnnotation(type, filter);
}

public List<String> getBeansWithAnnotation(Class<? extends Annotation> type, Predicate<Map<String, Object>> attributeFilter) {

    List<String> result = Lists.newArrayList();

    ConfigurableListableBeanFactory factory = ((ConfigurableApplicationContext) applicationContext).getBeanFactory();
    for (String name : factory.getBeanDefinitionNames()) {
        BeanDefinition bd = factory.getBeanDefinition(name);

        if (bd.getSource() instanceof StandardMethodMetadata) {
            StandardMethodMetadata metadata = (StandardMethodMetadata) bd.getSource();

            Map<String, Object> attributes = metadata.getAnnotationAttributes(type.getName());
            if (null == attributes) {
                continue;
            }

            if (attributeFilter.apply(attributes)) {
                result.add(name);
            }
        }
    }

    return result;
}
}
@组件
公共类MyClassWithEventListeners实现ApplicationContextAware{
@自动连线
ApplicationEventPublisher应用EventPublisher;
@自动连线
应用上下文应用上下文;
@事件监听器
作废contextRefreshedEvent(contextRefreshedEvent事件){
ApplicationContext ApplicationContext=event.getApplicationContext();
applicationContext.getClassLoader();
AutowireCapableBeanFactory AutowireCapableBeanFactory=applicationContext.getAutowireCapableBeanFactory();
字符串[]名称=event.getApplicationContext().getBeanDefinitionNames();
for(字符串名称:名称){
对象o=autowireCapableBeanFactory.getBean(名称);
if(aopproxutils.ultimateTargetClass(o).isAnnotationPresent(FooBar.class)){
System.out.println(“用FooBar注释的发现类”);
}
}
}
@凌驾
public void setApplicationContext(ApplicationContext ApplicationContext)抛出BeansException{
this.applicationContext=applicationContext;
List beanNames=GetBeanWithAnnotation(FooBar.class);
if(beanNames!=null){
System.out.println(“用FooBar注释的发现类”);
}
}

公共列表GetBeanWithAnnotation(类核心容器实际上支持这些内容,因此无需破解上下文。当您在配置类上添加
@EnableXYZ
时,您可能会从阅读所发生的事情中获益。例如
@EnableCaching
@EnableJms
的工作方式大致相同:


接口使用
@Import
进行元注释,这会导致上下文加载更多的bean。启用
的部分在我看来有点无用。注释的存在与否起着相同的作用,并且更加明确。

核心容器实际上支持这些内容,因此无需破解上下文。当您在配置类上添加
@EnableXYZ
时,您可能会从阅读所发生的事情中受益。例如
@EnableCaching
@EnableJms
的工作方式大致相同:


接口使用
@Import
进行元注释,这会导致上下文加载更多bean。启用
的部分在我看来有点无用。注释的存在与否起着相同的作用,并且更加明确。

也许您可以使用类提供的实用程序,而不是AoP提供的UTIL?

@Test
public void testAccess(){
    SomeAnnotatedClass annotatedClassInstance = new SomeAnnotatedClass();

    Assert.assertNotNull(annotatedClassInstance.getClass().getAnnotation(FooBar.class));
}

也许您可以使用类提供的实用程序而不是AoP提供的UTIL

@Test
public void testAccess(){
    SomeAnnotatedClass annotatedClassInstance = new SomeAnnotatedClass();

    Assert.assertNotNull(annotatedClassInstance.getClass().getAnnotation(FooBar.class));
}

我进一步研究了这一点,发现了两种可能的解决方案。第一种简单地检测是否存在自定义注释:

@Component
public class MyClassWithEventListeners {

@EventListener
void contextRefreshedEvent(ContextRefreshedEvent event) throws NoSuchFieldException, IllegalAccessException {
    ApplicationContext applicationContext = event.getApplicationContext();
    String[] annotations = applicationContext.getBeanNamesForAnnotation(FooBar.class);
    if (annotations != null && annotations.length > 0) {
        System.out.println("Annotation found");
    } else {
        System.out.println("Annotation not found");
    }
}
}
第二种方法使用反射来获取注释中设置的值。在本例中,
的值为enabled

@Component
public class MyClassWithEventListeners {

@EventListener
void contextRefreshedEvent(ContextRefreshedEvent event) throws NoSuchFieldException, IllegalAccessException {
    ApplicationContext applicationContext = event.getApplicationContext();
    AnnotationConfigWebApplicationContext annotationContext = ((AnnotationConfigWebApplicationContext) applicationContext);

    for (Field field : annotationContext.getClass().getDeclaredFields()) {
        if ("annotatedClasses".equals(field.getName())) {
            field.setAccessible(true);
            Set<Class<?>> classes = (Set<Class<?>>) field.get(annotationContext);
            for (Class clazz : classes) {
                for (Annotation annotation : clazz.getDeclaredAnnotations()) {
                    if (annotation.annotationType().isAssignableFrom(FooBar.class)) {
                        enabled = ((ServiceRegistration) annotation).enabled();
                        System.out.println("Enabled: " + enabled);
                    }
                }
            }
        }
    }
}
}
@组件
公共类MyClassWithEventListeners{
@事件监听器
void contextRefreshedEvent(contextRefreshedEvent事件)抛出NoSuchFieldException、IllegalAccessException{
ApplicationContext ApplicationContext=event.getApplicationContext();
AnnotationConfigWebApplicationContext annotationContext=((AnnotationConfigWebApplicationContext)applicationContext);
对于(字段:annotationContext.getClass().getDeclaredFields()){
if(“annotatedClasses.equals(field.getName())){
字段。setAccessible(true);

Set我进一步研究了这一点,发现了两种可能的解决方案。第一种简单地检测自定义注释是否存在:

@Component
public class MyClassWithEventListeners {

@EventListener
void contextRefreshedEvent(ContextRefreshedEvent event) throws NoSuchFieldException, IllegalAccessException {
    ApplicationContext applicationContext = event.getApplicationContext();
    String[] annotations = applicationContext.getBeanNamesForAnnotation(FooBar.class);
    if (annotations != null && annotations.length > 0) {
        System.out.println("Annotation found");
    } else {
        System.out.println("Annotation not found");
    }
}
}
第二种方法使用反射来获取注释中设置的值。在本例中,
的值为enabled

@Component
public class MyClassWithEventListeners {

@EventListener
void contextRefreshedEvent(ContextRefreshedEvent event) throws NoSuchFieldException, IllegalAccessException {
    ApplicationContext applicationContext = event.getApplicationContext();
    AnnotationConfigWebApplicationContext annotationContext = ((AnnotationConfigWebApplicationContext) applicationContext);

    for (Field field : annotationContext.getClass().getDeclaredFields()) {
        if ("annotatedClasses".equals(field.getName())) {
            field.setAccessible(true);
            Set<Class<?>> classes = (Set<Class<?>>) field.get(annotationContext);
            for (Class clazz : classes) {
                for (Annotation annotation : clazz.getDeclaredAnnotations()) {
                    if (annotation.annotationType().isAssignableFrom(FooBar.class)) {
                        enabled = ((ServiceRegistration) annotation).enabled();
                        System.out.println("Enabled: " + enabled);
                    }
                }
            }
        }
    }
}
}
@组件
公共类MyClassWithEventListeners{
@事件监听器
void contextRefreshedEvent(contextRefreshedEvent事件)抛出NoSuchFieldException、IllegalAccessException{
ApplicationContext ApplicationContext=event.getApplicationContext();
AnnotationConfigWebApplicationContext annotationContext=((AnnotationConfigWebApplicationContext)applicationContext);
对于(字段:annotationContext.getClass().getDeclaredFields()){
if(“annotatedClasses.equals(field.getName())){
字段。setAccessible(true);

set您是否尝试过使用简单的
ApplicationContext().findannotationbean(beanname,annotationType)
?同意:启用的值有点毫无意义。感谢您提供有关
@Import
的提示,这在将来可能会有用。您是否尝试过使用简单的
ApplicationContext().findannotationbean(beanname,注释类型)
?同意:启用的值有点毫无意义。感谢您提供有关
@Import
的提示,这在将来可能会很有用。这是我在上面发布的答案中最有帮助的。在查看@EnableXXXX后面的代码时,我发现了引导我找到上述代码的提示。这对找到答案最有帮助在查看@enablexx后面的代码时,我发现了一些提示,可以引导我找到上面的代码。