• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

TAKETODAY / today-infrastructure / 17175530323

23 Aug 2025 12:36PM UTC coverage: 81.854% (+0.009%) from 81.845%
17175530323

push

github

TAKETODAY
:art:

59686 of 77901 branches covered (76.62%)

Branch coverage included in aggregate %.

141140 of 167446 relevant lines covered (84.29%)

3.6 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

88.02
today-context/src/main/java/infra/context/annotation/AnnotationConfigUtils.java
1
/*
2
 * Copyright 2017 - 2025 the original author or authors.
3
 *
4
 * This program is free software: you can redistribute it and/or modify
5
 * it under the terms of the GNU General Public License as published by
6
 * the Free Software Foundation, either version 3 of the License, or
7
 * (at your option) any later version.
8
 *
9
 * This program is distributed in the hope that it will be useful,
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
 * GNU General Public License for more details.
13
 *
14
 * You should have received a copy of the GNU General Public License
15
 * along with this program. If not, see [https://www.gnu.org/licenses/]
16
 */
17

18
package infra.context.annotation;
19

20
import java.util.function.Consumer;
21

22
import infra.aop.framework.autoproxy.AutoProxyUtils;
23
import infra.beans.factory.annotation.AnnotatedBeanDefinition;
24
import infra.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor;
25
import infra.beans.factory.annotation.DisableDependencyInjection;
26
import infra.beans.factory.annotation.EnableDependencyInjection;
27
import infra.beans.factory.config.BeanDefinition;
28
import infra.beans.factory.config.BeanDefinitionHolder;
29
import infra.beans.factory.config.BeanFactoryPostProcessor;
30
import infra.beans.factory.config.BeanPostProcessor;
31
import infra.beans.factory.support.BeanDefinitionRegistry;
32
import infra.beans.factory.support.RootBeanDefinition;
33
import infra.beans.factory.support.StandardBeanFactory;
34
import infra.context.event.DefaultEventListenerFactory;
35
import infra.context.event.EventListenerMethodProcessor;
36
import infra.context.support.GenericApplicationContext;
37
import infra.core.annotation.AnnotationAwareOrderComparator;
38
import infra.core.annotation.MergedAnnotation;
39
import infra.core.annotation.MergedAnnotations;
40
import infra.core.type.AnnotatedTypeMetadata;
41
import infra.core.type.AnnotationMetadata;
42
import infra.lang.Nullable;
43
import infra.util.ClassUtils;
44

45
/**
46
 * Utility class that allows for convenient registration of common
47
 * {@link BeanPostProcessor} and
48
 * {@link BeanFactoryPostProcessor}
49
 * definitions for annotation-based configuration.
50
 *
51
 * @author Mark Fisher
52
 * @author Juergen Hoeller
53
 * @author Chris Beams
54
 * @author Phillip Webb
55
 * @author Stephane Nicoll
56
 * @author <a href="https://github.com/TAKETODAY">Harry Yang</a>
57
 * @see ConfigurationClassPostProcessor
58
 * @since 4.0
59
 */
60
public abstract class AnnotationConfigUtils {
×
61

62
  /**
63
   * The bean name of the internally managed Configuration annotation processor.
64
   */
65
  public static final String CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME =
66
          "infra.context.annotation.internalConfigurationAnnotationProcessor";
67

68
  /**
69
   * The bean name of the internally managed BeanNameGenerator for use when processing
70
   * {@link Configuration} classes. Set by {@link AnnotationConfigApplicationContext}
71
   * and {@code AnnotationConfigWebApplicationContext} during bootstrap in order to make
72
   * any custom name generation strategy available to the underlying
73
   * {@link ConfigurationClassPostProcessor}.
74
   */
75
  public static final String CONFIGURATION_BEAN_NAME_GENERATOR =
76
          "infra.context.annotation.internalConfigurationBeanNameGenerator";
77

78
  /**
79
   * The bean name of the internally managed Autowired annotation processor.
80
   */
81
  public static final String AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME =
82
          "infra.context.annotation.internalAutowiredAnnotationProcessor";
83

84
  /**
85
   * The bean name of the internally managed JPA annotation processor.
86
   */
87
  public static final String PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME =
88
          "infra.context.annotation.internalPersistenceAnnotationProcessor";
89

90
  private static final String PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME =
91
          "infra.orm.jpa.support.PersistenceAnnotationBeanPostProcessor";
92

93
  /**
94
   * The bean name of the internally managed @EventListener annotation processor.
95
   */
96
  public static final String EVENT_LISTENER_PROCESSOR_BEAN_NAME =
97
          "infra.context.event.internalEventListenerProcessor";
98

99
  /**
100
   * The bean name of the internally managed EventListenerFactory.
101
   */
102
  public static final String EVENT_LISTENER_FACTORY_BEAN_NAME =
103
          "infra.context.event.internalEventListenerFactory";
104

105
  /**
106
   * The bean name of the internally managed common annotation processor.
107
   */
108
  public static final String COMMON_ANNOTATION_PROCESSOR_BEAN_NAME =
109
          "infra.context.annotation.internalCommonAnnotationProcessor";
110

111
  private static final boolean jsr250Present = isPresent("javax.annotation.PostConstruct");
3✔
112
  private static final boolean jakartaAnnotationsPresent = isPresent("jakarta.annotation.PostConstruct");
3✔
113
  private static final boolean jpaPresent = isPresent("jakarta.persistence.EntityManagerFactory")
5✔
114
          && isPresent(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME);
4!
115

116
  private static boolean isPresent(String className) {
117
    ClassLoader classLoader = AnnotationConfigUtils.class.getClassLoader();
3✔
118
    return ClassUtils.isPresent(className, classLoader);
4✔
119
  }
120

121
  public static void registerAnnotationConfigProcessors(BeanDefinitionRegistry registry) {
122
    registerAnnotationConfigProcessors(registry, null);
3✔
123
  }
1✔
124

125
  /**
126
   * Register all relevant annotation post processors in the given registry.
127
   *
128
   * @param registry the registry to operate on
129
   */
130
  public static void registerAnnotationConfigProcessors(
131
          BeanDefinitionRegistry registry, @Nullable Consumer<BeanDefinitionHolder> consumer) {
132
    StandardBeanFactory beanFactory = unwrapStandardBeanFactory(registry);
3✔
133
    if (beanFactory != null) {
2!
134
      if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
4✔
135
        beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
3✔
136
      }
137

138
      if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {
4✔
139
        beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
5✔
140
      }
141
    }
142

143
    if (!registry.containsBeanDefinition(AnnotationConfigUtils.CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
4✔
144
      RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
5✔
145
      registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME, consumer);
5✔
146
    }
147

148
    if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
4✔
149
      RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
5✔
150
      registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME, consumer);
5✔
151
    }
152

153
    // Check for Jakarta Annotations support, and if present add the CommonAnnotationBeanPostProcessor.
154
    if ((jakartaAnnotationsPresent || jsr250Present)
6!
155
            && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {
2✔
156
      RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
5✔
157
      registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME, consumer);
5✔
158
    }
159

160
    // Check for JPA support, and if present add the PersistenceAnnotationBeanPostProcessor.
161
    if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) {
2!
162
      RootBeanDefinition def = new RootBeanDefinition();
×
163
      try {
164
        def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME,
×
165
                AnnotationConfigUtils.class.getClassLoader()));
×
166
      }
167
      catch (ClassNotFoundException ex) {
×
168
        throw new IllegalStateException(
×
169
                "Cannot load optional framework class: " + PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, ex);
170
      }
×
171
      registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME, consumer);
×
172
    }
173

174
    if (!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) {
4✔
175
      RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class);
5✔
176
      registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME, consumer);
5✔
177
    }
178

179
    if (!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) {
4✔
180
      RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class);
5✔
181
      registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME, consumer);
5✔
182
    }
183
  }
1✔
184

185
  private static void registerPostProcessor(BeanDefinitionRegistry registry,
186
          RootBeanDefinition definition, String beanName, @Nullable Consumer<BeanDefinitionHolder> consumer) {
187

188
    definition.setEnableDependencyInjection(false);
3✔
189
    definition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
3✔
190
    registry.registerBeanDefinition(beanName, definition);
4✔
191

192
    if (consumer != null) {
2✔
193
      consumer.accept(new BeanDefinitionHolder(definition, beanName));
7✔
194
    }
195
  }
1✔
196

197
  @Nullable
198
  private static StandardBeanFactory unwrapStandardBeanFactory(BeanDefinitionRegistry registry) {
199
    if (registry instanceof StandardBeanFactory) {
3✔
200
      return (StandardBeanFactory) registry;
3✔
201
    }
202
    else if (registry instanceof GenericApplicationContext) {
3!
203
      return ((GenericApplicationContext) registry).getBeanFactory();
4✔
204
    }
205
    else {
206
      return null;
×
207
    }
208
  }
209

210
  public static void processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd) {
211
    applyAnnotationMetadata(abd, true);
3✔
212
  }
1✔
213

214
  static BeanDefinitionHolder applyScopedProxyMode(
215
          ScopeMetadata metadata, BeanDefinitionHolder definition, BeanDefinitionRegistry registry) {
216

217
    ScopedProxyMode scopedProxyMode = metadata.getScopedProxyMode();
3✔
218
    if (scopedProxyMode.equals(ScopedProxyMode.NO)) {
4✔
219
      return definition;
2✔
220
    }
221
    boolean proxyTargetClass = scopedProxyMode.equals(ScopedProxyMode.TARGET_CLASS);
4✔
222
    return ScopedProxyCreator.createScopedProxy(definition, registry, proxyTargetClass);
5✔
223
  }
224

225
  public static void applyAnnotationMetadata(AnnotatedBeanDefinition definition, boolean detectDIStatus) {
226
    AnnotatedTypeMetadata metadata = definition.getFactoryMethodMetadata();
3✔
227
    if (metadata == null) {
2✔
228
      metadata = definition.getMetadata();
3✔
229
    }
230
    MergedAnnotations annotations = metadata.getAnnotations();
3✔
231
    applyAnnotationMetadata(annotations, definition, detectDIStatus);
4✔
232
  }
1✔
233

234
  public static void applyAnnotationMetadata(MergedAnnotations annotations, BeanDefinition definition, boolean detectDIStatus) {
235
    if (annotations.isPresent(Primary.class)) {
4✔
236
      definition.setPrimary(true);
3✔
237
    }
238

239
    if (annotations.isPresent(Fallback.class)) {
4✔
240
      definition.setFallback(true);
3✔
241
    }
242

243
    MergedAnnotation<Lazy> lazyMergedAnnotation = annotations.get(Lazy.class);
4✔
244
    if (lazyMergedAnnotation.isPresent()) {
3✔
245
      definition.setLazyInit(lazyMergedAnnotation.getBooleanValue());
5✔
246
    }
247
    else if (definition instanceof AnnotatedBeanDefinition annotated) {
6!
248
      AnnotationMetadata metadata = annotated.getMetadata();
3✔
249
      lazyMergedAnnotation = metadata.getAnnotation(Lazy.class);
4✔
250

251
      if (lazyMergedAnnotation.isPresent()) {
3✔
252
        definition.setLazyInit(lazyMergedAnnotation.getBooleanValue());
4✔
253
      }
254
    }
255

256
    MergedAnnotation<Role> roleMergedAnnotation = annotations.get(Role.class);
4✔
257
    if (roleMergedAnnotation.isPresent()) {
3✔
258
      definition.setRole(roleMergedAnnotation.getIntValue());
4✔
259
    }
260

261
    MergedAnnotation<DependsOn> dependsOn = annotations.get(DependsOn.class);
4✔
262
    if (dependsOn.isPresent()) {
3✔
263
      definition.setDependsOn(dependsOn.getStringValueArray());
4✔
264
    }
265

266
    MergedAnnotation<Description> description = annotations.get(Description.class);
4✔
267
    if (description.isPresent()) {
3✔
268
      definition.setDescription(description.getStringValue());
4✔
269
    }
270

271
    if (detectDIStatus) {
2✔
272
      if (annotations.isPresent(EnableDependencyInjection.class)) {
4!
273
        definition.setEnableDependencyInjection(true);
×
274
      }
275
      else if (annotations.isPresent(DisableDependencyInjection.class)) {
4✔
276
        definition.setEnableDependencyInjection(false);
3✔
277
      }
278
    }
279

280
    MergedAnnotation<Proxyable> proxyable = annotations.get(Proxyable.class);
4✔
281
    if (proxyable.isPresent()) {
3✔
282
      ProxyType mode = proxyable.getEnum("value", ProxyType.class);
6✔
283
      if (mode == ProxyType.TARGET_CLASS) {
3✔
284
        definition.setAttribute(AutoProxyUtils.PRESERVE_TARGET_CLASS_ATTRIBUTE, Boolean.TRUE);
5✔
285
      }
286
      else {
287
        Class<?>[] ifcs = proxyable.getClassArray("interfaces");
4✔
288
        if (ifcs.length > 0 || mode == ProxyType.INTERFACES) {
6!
289
          definition.setAttribute(AutoProxyUtils.EXPOSED_INTERFACES_ATTRIBUTE, ifcs);
4✔
290
        }
291
      }
292
    }
293

294
  }
1✔
295

296
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc