как настроить плетение во время загрузки с помощью Spring и Tomcat БЕЗ использования -javaagent в командной строке

Я использую Spring 3.2.9, Tomcat 6.0.44.

Я пытаюсь настроить поставщик инструментов Spring моего приложения (например, spring-instrumentation.jar) для ткачества во время загрузки, когда он развернут на Tomcat.

У меня есть требование НЕ использовать: "-javaagent:/path/path/spring-instrument.jar" в командной строке для выполнения конфигурации.

Я читал, что могу настроить инструментарий Spring, изменив элемент ‹Context› конфигурации Tomcat моего приложения (либо в файле server.xml Tomcat, либо в context.xml моего веб-приложения). Добавление соответствующего элемента ‹Context› в файл server.xml приводит к правильной настройке моего приложения для работы с поставщиком инструментов Spring. Добавление его в context.xml (см. ниже) НЕ приводит к рабочей настройке.

У меня есть файл META-INF/aop.xml, который выглядит так:

    <aspectj>
        <weaver options="-verbose -showWeaveInfo -debug">
            <include within="com.mv.xx.services..*"/>
            <exclude within="com.mv.xx.aop..*"/>
        </weaver>
        <aspects>
            <aspect name="com.mv.xx.aop.MyAspect"/>
        </aspects>
    </aspectj>

Я также указываю, что хочу использовать переплетение во время загрузки, добавив это в свою конфигурацию контекста Spring:

 <context:load-time-weaver />

И я добавляю эту банку в путь к классам моего приложения: spring-instrument-tomcat.jar

ЧТО Я ПРОБОВАЛ:

При запуске Tomcat, если я определяю местоположение spring-instrument.jar в командной строке, используя параметр -javaagent следующим образом:

-javaagent:/path/path2/spring-instrument-3.2.9.RELEASE.jar

Все работает нормально.


Затем я удалил «-javaagent:/path/path2/spring-instrument-3.2.9.RELEASE.jar» из командной строки. В файле Tomcat server.xml (расположенном в $CATALINE_HOME/conf) я добавил элемент ‹Context› к элементу ‹Host›, например так:

<Context path="/myApp" docBase="myApp">
    <Loader loaderClass="org.springframework.instrument.classloading.tomcat.TomcatInstrumentableClassLoader"/>
</Context>

С этой конфигурацией все ведет себя корректно. Однако у меня есть требование не изменять server.xml Tomcat, поскольку я не контролирую server.xml (DevOps делает это и не хочет его изменять).


Затем я удалил элемент ‹Context› из файла server.xml Tomcat. Согласно Spring docs, я могу добавить /META-INF/context.xml в свое веб-приложение и поместить элемент ‹Context›, который раньше был в Tomcat server.xml, в context.xml, например так:

        <Context>
            <Context path="/myApp" docBase="myApp">
                <Loader loaderClass="org.springframework.instrument.classloading.tomcat.TomcatInstrumentableClassLoader"/>
            </Context>
        </Context>

Однако, когда я перезапускаю Tomcat, в журналах появляется сообщение об ошибке:

    SEVERE: Exception sending context initialized event to listener instance of class org.springframework.web.context.ContextLoaderListener
    org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.context.weaving.AspectJWeavingEnabler#0': Initialization of bean failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'loadTimeWeaver': Initialization of bean failed; nested exception is java.lang.IllegalStateException: ClassLoader [org.apache.catalina.loader.WebappClassLoader] does NOT provide an 'addTransformer(ClassFileTransformer)' method. Specify a custom LoadTimeWeaver or start your Java virtual machine with Spring's agent: -javaagent:org.springframework.instrument.jar

Покопавшись, я прочитал что-то, что предложило мне изменить элемент <context:load-time-weaver/> в моей конфигурации Spring, например:

        <context:load-time-weaver weaver-class="org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver" />

И добавьте банку, содержащую InstrumentationLoadTimeWeaver.class, в мой путь к классам.

Однако, когда я это делаю, я получаю это сообщение об ошибке в журналах:

        SEVERE: Exception sending context initialized event to listener instance of class org.springframework.web.context.ContextLoaderListener
        java.lang.IllegalStateException: Must start with Java agent to use InstrumentationLoadTimeWeaver. See Spring documentation.
    etc....

Может ли кто-нибудь объяснить, как настроить плетение во время загрузки с помощью Spring и Tomcat БЕЗ использования -javaagent в командной строке и БЕЗ изменения server.xml?


person StvnBrkdll    schedule 14.03.2016    source источник
comment
Та же проблема! Любое решение?   -  person HVT7    schedule 06.06.2016


Ответы (3)


Это код, который мне удалось использовать, чтобы удалить упомянутое вами исключение. По сути, вам нужно реализовать LoadTimeWeavingConfigurer и переопределить метод getLoadTimeWeaver().

@Configuration
@ComponentScan(basePackages = "org.myproject")
@EnableAspectJAutoProxy
@EnableSpringConfigured
@EnableLoadTimeWeaving(aspectjWeaving = EnableLoadTimeWeaving.AspectJWeaving.AUTODETECT)
public class Config implements LoadTimeWeavingConfigurer {

    @Override
    public LoadTimeWeaver getLoadTimeWeaver() {
        return new ReflectiveLoadTimeWeaver();
    }

    @Bean
    public InstrumentationLoadTimeWeaver loadTimeWeaver()  throws Throwable {
        InstrumentationLoadTimeWeaver loadTimeWeaver = new InstrumentationLoadTimeWeaver();
        return loadTimeWeaver;
    }

}
person Gui    schedule 08.06.2016
comment
@Ryan Я мог бы добиться того же в конфигурации xml. Взгляните на документ Spring - docs.spring.io/spring/docs/current/javadoc-api/org/ Это может помочь. Спасибо - person Gui; 01.03.2017
comment
Спасибо за ссылку. Это выглядит более подробно, чем то, что я нашел. Это не сработало с моей первой попытки, но приятно слышать, что это возможно. - person Ryan; 02.03.2017

Для этого я использовал invesdwin-instrument. Это позволяет вам динамически использовать инструментарий плетения во время загрузки, поэтому вам не нужно использовать какой-либо javaagent.

Однако мне потребовалось немного усилий, чтобы заставить его работать с Tomcat 8.5. Но, наконец, он работает с этой конфигурацией с Spring Boot:

@SpringBootApplication
@EnableLoadTimeWeaving // instead of @ImportResource(locations = "classpath:/META-INF/ctx.spring.weaving.xml")
public class MySpringBootApplication {
    public static void main(final String[] args) {
        DynamicInstrumentationLoader.waitForInitialized(); //dynamically attach java agent to jvm if not already present
        DynamicInstrumentationLoader.initLoadTimeWeavingContext(); //weave all classes before they are loaded as beans
        SpringApplication.run(MySpringBootApplication.class, args); //start application, load some classes
    }
}

Он также должен работать с предыдущей версией Tomcat.

С уважением

person teikitel    schedule 05.01.2018

https://wiki.eclipse.org/EclipseLink/UserGuide/JPA/Advanced_JPA_Development/Performance/Weaving/Static_Weaving

Попробуйте плагин maven по ссылке выше. Это работает

person Rachna    schedule 22.06.2016
comment
Хотя теоретически это может ответить на вопрос, было бы предпочтительнее включить сюда основные части ответа и предоставить ссылку для справки . - person Bhargav Rao; 22.06.2016