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

TAKETODAY / today-infrastructure / 20389109996

20 Dec 2025 04:24AM UTC coverage: 84.437% (+0.02%) from 84.42%
20389109996

Pull #289

github

web-flow
Merge 9e92e9a22 into 1fbfdc80f
Pull Request #289: Netty HTTP 处理重构

62125 of 78670 branches covered (78.97%)

Branch coverage included in aggregate %.

146626 of 168558 relevant lines covered (86.99%)

3.71 hits per line

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

90.74
today-context/src/main/java/infra/context/annotation/ConfigurationClassUtils.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 org.jspecify.annotations.Nullable;
21

22
import java.io.IOException;
23
import java.util.Set;
24

25
import infra.aop.AopInfrastructureBean;
26
import infra.beans.factory.annotation.AnnotatedBeanDefinition;
27
import infra.beans.factory.config.BeanDefinition;
28
import infra.beans.factory.config.BeanFactoryPostProcessor;
29
import infra.beans.factory.config.BeanPostProcessor;
30
import infra.beans.factory.support.AbstractBeanDefinition;
31
import infra.bytecode.proxy.Enhancer;
32
import infra.context.BootstrapContext;
33
import infra.context.event.EventListenerFactory;
34
import infra.core.Conventions;
35
import infra.core.Ordered;
36
import infra.core.annotation.MergedAnnotation;
37
import infra.core.annotation.Order;
38
import infra.core.type.AnnotationMetadata;
39
import infra.logging.Logger;
40
import infra.logging.LoggerFactory;
41
import infra.stereotype.Component;
42

43
/**
44
 * Utilities for identifying {@link Configuration} classes.
45
 *
46
 * @author Chris Beams
47
 * @author Juergen Hoeller
48
 * @author Sam Brannen
49
 * @author <a href="https://github.com/TAKETODAY">Harry Yang</a>
50
 * @since 4.0
51
 */
52
public abstract class ConfigurationClassUtils {
×
53

54
  public static final String CONFIGURATION_CLASS_FULL = "full";
55
  public static final String CONFIGURATION_CLASS_LITE = "lite";
56

57
  /**
58
   * When set to {@link Boolean#TRUE}, this attribute signals that the bean class
59
   * for the given {@link BeanDefinition} should be considered as a candidate
60
   * configuration class in 'lite' mode by default.
61
   * <p>For example, a class registered directly with an {@code ApplicationContext}
62
   * should always be considered a configuration class candidate.
63
   */
64
  static final String CANDIDATE_ATTRIBUTE =
2✔
65
          Conventions.getQualifiedAttributeName(ConfigurationClassPostProcessor.class, "candidate");
2✔
66

67
  public static final String CONFIGURATION_CLASS_ATTRIBUTE =
2✔
68
          Conventions.getQualifiedAttributeName(ConfigurationClassPostProcessor.class, "configurationClass");
2✔
69

70
  private static final String ORDER_ATTRIBUTE =
2✔
71
          Conventions.getQualifiedAttributeName(ConfigurationClassPostProcessor.class, "order");
2✔
72

73
  private static final Logger log = LoggerFactory.getLogger(ConfigurationClassUtils.class);
3✔
74

75
  private static final Set<String> candidateIndicators = Set.of(
4✔
76
          Import.class.getName(), Component.class.getName(),
4✔
77
          ComponentScan.class.getName(), ImportResource.class.getName()
3✔
78
  );
79

80
  /**
81
   * Initialize a configuration class proxy for the specified class.
82
   *
83
   * @param userClass the configuration class to initialize
84
   */
85
  @SuppressWarnings("unused") // Used by AOT-optimized generated code
86
  public static Class<?> initializeConfigurationClass(Class<?> userClass) {
87
    Class<?> configurationClass = new ConfigurationClassEnhancer().enhance(userClass, null);
×
88
    Enhancer.registerStaticCallbacks(configurationClass, ConfigurationClassEnhancer.CALLBACKS);
×
89
    return configurationClass;
×
90
  }
91

92
  /**
93
   * Check whether the given bean definition is a candidate for a configuration class
94
   * (or a nested component class declared within a configuration/component class,
95
   * to be auto-registered as well), and mark it accordingly.
96
   *
97
   * @param beanDef the bean definition to check
98
   * @param bootstrapContext the current bootstrap context
99
   * @return whether the candidate qualifies as (any kind of) configuration class
100
   */
101
  static boolean checkConfigurationClassCandidate(BeanDefinition beanDef, BootstrapContext bootstrapContext) {
102
    String className = beanDef.getBeanClassName();
3✔
103
    if (className == null || beanDef.getFactoryMethodName() != null) {
5✔
104
      return false;
2✔
105
    }
106

107
    AnnotationMetadata metadata;
108
    if (beanDef instanceof AnnotatedBeanDefinition annotated
8✔
109
            && className.equals(annotated.getMetadata().getClassName())) {
4✔
110
      // Can reuse the pre-parsed metadata from the given BeanDefinition...
111
      metadata = annotated.getMetadata();
4✔
112
    }
113
    else if (beanDef instanceof AbstractBeanDefinition abd && abd.hasBeanClass()) {
9!
114
      // Check already loaded Class if present...
115
      // since we possibly can't even load the class file for this Class.
116
      Class<?> beanClass = abd.getBeanClass();
3✔
117
      if (BeanFactoryPostProcessor.class.isAssignableFrom(beanClass)
6✔
118
              || BeanPostProcessor.class.isAssignableFrom(beanClass)
4✔
119
              || AopInfrastructureBean.class.isAssignableFrom(beanClass)
4✔
120
              || EventListenerFactory.class.isAssignableFrom(beanClass)) {
2✔
121
        return false;
2✔
122
      }
123
      metadata = AnnotationMetadata.introspect(beanClass);
3✔
124
    }
1✔
125
    else {
126
      try {
127
        metadata = bootstrapContext.getAnnotationMetadata(className);
4✔
128
      }
129
      catch (IOException ex) {
1✔
130
        if (log.isDebugEnabled()) {
3!
131
          log.debug("Could not find class file for introspecting configuration annotations: {}",
×
132
                  className, ex);
133
        }
134
        return false;
2✔
135
      }
1✔
136
    }
137

138
    MergedAnnotation<Configuration> config = metadata.getAnnotation(Configuration.class);
4✔
139
    if (config.isPresent() && !Boolean.FALSE.equals(config.getBoolean("proxyBeanMethods"))) {
10✔
140
      beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_FULL);
5✔
141
    }
142
    else if (config.isPresent()
6✔
143
            || Boolean.TRUE.equals(beanDef.getAttribute(CANDIDATE_ATTRIBUTE))
4✔
144
            || isConfigurationCandidate(metadata)) {
2✔
145
      beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_LITE);
5✔
146
    }
147
    else {
148
      return false;
2✔
149
    }
150

151
    // It's a full or lite configuration candidate... Let's determine the order value, if any.
152
    Integer order = getOrder(metadata);
3✔
153
    if (order != null) {
2✔
154
      beanDef.setAttribute(ORDER_ATTRIBUTE, order);
4✔
155
    }
156

157
    return true;
2✔
158
  }
159

160
  /**
161
   * Check the given metadata for a configuration class candidate
162
   * (or nested component class declared within a configuration/component class).
163
   *
164
   * @param metadata the metadata of the annotated class
165
   * @return {@code true} if the given class is to be registered for
166
   * configuration class processing; {@code false} otherwise
167
   */
168
  static boolean isConfigurationCandidate(AnnotationMetadata metadata) {
169
    // Do not consider an interface or an annotation...
170
    if (metadata.isInterface()) {
3✔
171
      return false;
2✔
172
    }
173

174
    // Any of the typical annotations found?
175
    for (String indicator : candidateIndicators) {
10✔
176
      if (metadata.isAnnotated(indicator)) {
4✔
177
        return true;
2✔
178
      }
179
    }
1✔
180

181
    // Finally, let's look for @Component methods...
182
    return hasComponentMethods(metadata);
3✔
183
  }
184

185
  static boolean hasComponentMethods(AnnotationMetadata metadata) {
186
    try {
187
      return metadata.hasAnnotatedMethods(Component.class.getName());
5✔
188
    }
189
    catch (Throwable ex) {
×
190
      log.debug("Failed to introspect @Component methods on class [{}]: {}", metadata.getClassName(), ex.toString());
×
191
      return false;
×
192
    }
193
  }
194

195
  /**
196
   * Determine the order for the given configuration class metadata.
197
   *
198
   * @param metadata the metadata of the annotated class
199
   * @return the {@code @Order} annotation value on the configuration class,
200
   * or {@code Ordered.LOWEST_PRECEDENCE} if none declared
201
   */
202
  @Nullable
203
  public static Integer getOrder(AnnotationMetadata metadata) {
204
    MergedAnnotation<Order> orderAnnotation = metadata.getAnnotation(Order.class);
4✔
205
    return orderAnnotation.isPresent() ? orderAnnotation.getIntValue() : null;
9✔
206
  }
207

208
  /**
209
   * Determine the order for the given configuration class bean definition,
210
   * as set by {@link #checkConfigurationClassCandidate}.
211
   *
212
   * @param beanDef the bean definition to check
213
   * @return the {@link Order @Order} annotation value on the configuration class,
214
   * or {@link Ordered#LOWEST_PRECEDENCE} if none declared
215
   */
216
  public static int getOrder(BeanDefinition beanDef) {
217
    Object order = beanDef.getAttribute(ORDER_ATTRIBUTE);
4✔
218
    if (order instanceof Integer) {
3✔
219
      return (int) order;
4✔
220
    }
221
    return Ordered.LOWEST_PRECEDENCE;
2✔
222
  }
223

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

© 2025 Coveralls, Inc