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

TAKETODAY / today-infrastructure / 18154768944

01 Oct 2025 07:26AM UTC coverage: 81.882% (-0.005%) from 81.887%
18154768944

push

github

web-flow
Merge pull request #290 from TAKETODAY/dev/jspecify

jspecify

59788 of 78013 branches covered (76.64%)

Branch coverage included in aggregate %.

141239 of 167496 relevant lines covered (84.32%)

3.6 hits per line

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

13.64
today-context/src/main/java/infra/context/weaving/DefaultContextLoadTimeWeaver.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.weaving;
19

20
import org.jspecify.annotations.Nullable;
21

22
import java.lang.instrument.ClassFileTransformer;
23

24
import infra.beans.factory.BeanClassLoaderAware;
25
import infra.beans.factory.DisposableBean;
26
import infra.instrument.InstrumentationSavingAgent;
27
import infra.instrument.classloading.InstrumentationLoadTimeWeaver;
28
import infra.instrument.classloading.LoadTimeWeaver;
29
import infra.instrument.classloading.ReflectiveLoadTimeWeaver;
30
import infra.instrument.classloading.TomcatLoadTimeWeaver;
31
import infra.lang.Assert;
32
import infra.logging.Logger;
33
import infra.logging.LoggerFactory;
34

35
/**
36
 * Default {@link LoadTimeWeaver} bean for use in an application context,
37
 * decorating an automatically detected internal {@code LoadTimeWeaver}.
38
 *
39
 * <p>Typically registered for the default bean name "{@code loadTimeWeaver}";
40
 * the most convenient way to achieve this is Framework's
41
 * {@code <context:load-time-weaver>} XML tag or {@code @EnableLoadTimeWeaving}
42
 * on a {@code @Configuration} class.
43
 *
44
 * <p>This class implements a runtime environment check for obtaining the
45
 * appropriate weaver implementation, including
46
 * {@link InstrumentationSavingAgent Infra VM agent} and any {@link ClassLoader}
47
 * supported by Framework's {@link ReflectiveLoadTimeWeaver}.
48
 *
49
 * @author Juergen Hoeller
50
 * @author Ramnivas Laddad
51
 * @author Costin Leau
52
 * @author <a href="https://github.com/TAKETODAY">Harry Yang</a>
53
 * @see infra.context.ConfigurableApplicationContext#LOAD_TIME_WEAVER_BEAN_NAME
54
 * @since 4.0
55
 */
56
public class DefaultContextLoadTimeWeaver implements LoadTimeWeaver, BeanClassLoaderAware, DisposableBean {
57

58
  protected final Logger logger = LoggerFactory.getLogger(getClass());
5✔
59

60
  @Nullable
61
  private LoadTimeWeaver loadTimeWeaver;
62

63
  public DefaultContextLoadTimeWeaver() {
2✔
64
  }
1✔
65

66
  public DefaultContextLoadTimeWeaver(ClassLoader beanClassLoader) {
×
67
    setBeanClassLoader(beanClassLoader);
×
68
  }
×
69

70
  @Override
71
  public void setBeanClassLoader(ClassLoader classLoader) {
72
    LoadTimeWeaver serverSpecificLoadTimeWeaver = createServerSpecificLoadTimeWeaver(classLoader);
×
73
    if (serverSpecificLoadTimeWeaver != null) {
×
74
      if (logger.isDebugEnabled()) {
×
75
        logger.debug("Determined server-specific load-time weaver: {}",
×
76
                serverSpecificLoadTimeWeaver.getClass().getName());
×
77
      }
78
      this.loadTimeWeaver = serverSpecificLoadTimeWeaver;
×
79
    }
80
    else if (InstrumentationLoadTimeWeaver.isInstrumentationAvailable()) {
×
81
      logger.debug("Found Infra JVM agent for instrumentation");
×
82
      this.loadTimeWeaver = new InstrumentationLoadTimeWeaver(classLoader);
×
83
    }
84
    else {
85
      try {
86
        this.loadTimeWeaver = new ReflectiveLoadTimeWeaver(classLoader);
×
87
        if (logger.isDebugEnabled()) {
×
88
          logger.debug("Using reflective load-time weaver for class loader: " +
×
89
                  this.loadTimeWeaver.getInstrumentableClassLoader().getClass().getName());
×
90
        }
91
      }
92
      catch (IllegalStateException ex) {
×
93
        throw new IllegalStateException(ex.getMessage() + " Specify a custom LoadTimeWeaver or start your " +
×
94
                "Java virtual machine with Infra agent: -javaagent:today-instrument-{version}.jar");
95
      }
×
96
    }
97
  }
×
98

99
  /*
100
   * This method never fails, allowing to try other possible ways to use an
101
   * server-agnostic weaver. This non-failure logic is required since
102
   * determining a load-time weaver based on the ClassLoader name alone may
103
   * legitimately fail due to other mismatches.
104
   */
105
  @Nullable
106
  protected LoadTimeWeaver createServerSpecificLoadTimeWeaver(ClassLoader classLoader) {
107
    String name = classLoader.getClass().getName();
×
108
    try {
109
      if (name.startsWith("org.apache.catalina")) {
×
110
        return new TomcatLoadTimeWeaver(classLoader);
×
111
      }
112
    }
113
    catch (Exception ex) {
×
114
      if (logger.isInfoEnabled()) {
×
115
        logger.info("Could not obtain server-specific LoadTimeWeaver: {}", ex.getMessage());
×
116
      }
117
    }
×
118
    return null;
×
119
  }
120

121
  @Override
122
  public void destroy() {
123
    if (this.loadTimeWeaver instanceof InstrumentationLoadTimeWeaver) {
×
124
      if (logger.isDebugEnabled()) {
×
125
        logger.debug("Removing all registered transformers for class loader: {}",
×
126
                this.loadTimeWeaver.getInstrumentableClassLoader().getClass().getName());
×
127
      }
128
      ((InstrumentationLoadTimeWeaver) this.loadTimeWeaver).removeTransformers();
×
129
    }
130
  }
×
131

132
  @Override
133
  public void addTransformer(ClassFileTransformer transformer) {
134
    Assert.state(this.loadTimeWeaver != null, "Not initialized");
4!
135
    this.loadTimeWeaver.addTransformer(transformer);
×
136
  }
×
137

138
  @Override
139
  public ClassLoader getInstrumentableClassLoader() {
140
    Assert.state(this.loadTimeWeaver != null, "Not initialized");
4!
141
    return this.loadTimeWeaver.getInstrumentableClassLoader();
×
142
  }
143

144
  @Override
145
  public ClassLoader getThrowawayClassLoader() {
146
    Assert.state(this.loadTimeWeaver != null, "Not initialized");
4!
147
    return this.loadTimeWeaver.getThrowawayClassLoader();
×
148
  }
149

150
}
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