001/*
002 * Copyright 2002-2020 the original author or authors.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *      https://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017package org.springframework.context.annotation;
018
019import org.springframework.beans.factory.BeanClassLoaderAware;
020import org.springframework.beans.factory.annotation.Autowired;
021import org.springframework.beans.factory.config.BeanDefinition;
022import org.springframework.context.ConfigurableApplicationContext;
023import org.springframework.context.annotation.EnableLoadTimeWeaving.AspectJWeaving;
024import org.springframework.context.weaving.AspectJWeavingEnabler;
025import org.springframework.context.weaving.DefaultContextLoadTimeWeaver;
026import org.springframework.core.annotation.AnnotationAttributes;
027import org.springframework.core.type.AnnotationMetadata;
028import org.springframework.instrument.classloading.LoadTimeWeaver;
029
030/**
031 * {@code @Configuration} class that registers a {@link LoadTimeWeaver} bean.
032 *
033 * <p>This configuration class is automatically imported when using the
034 * {@link EnableLoadTimeWeaving} annotation. See {@code @EnableLoadTimeWeaving}
035 * javadoc for complete usage details.
036 *
037 * @author Chris Beams
038 * @since 3.1
039 * @see LoadTimeWeavingConfigurer
040 * @see ConfigurableApplicationContext#LOAD_TIME_WEAVER_BEAN_NAME
041 */
042@Configuration
043@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
044public class LoadTimeWeavingConfiguration implements ImportAware, BeanClassLoaderAware {
045
046        private AnnotationAttributes enableLTW;
047
048        private LoadTimeWeavingConfigurer ltwConfigurer;
049
050        private ClassLoader beanClassLoader;
051
052
053        @Override
054        public void setImportMetadata(AnnotationMetadata importMetadata) {
055                this.enableLTW = AnnotationConfigUtils.attributesFor(importMetadata, EnableLoadTimeWeaving.class);
056                if (this.enableLTW == null) {
057                        throw new IllegalArgumentException(
058                                        "@EnableLoadTimeWeaving is not present on importing class " + importMetadata.getClassName());
059                }
060        }
061
062        @Autowired(required = false)
063        public void setLoadTimeWeavingConfigurer(LoadTimeWeavingConfigurer ltwConfigurer) {
064                this.ltwConfigurer = ltwConfigurer;
065        }
066
067        @Override
068        public void setBeanClassLoader(ClassLoader beanClassLoader) {
069                this.beanClassLoader = beanClassLoader;
070        }
071
072
073        @Bean(name = ConfigurableApplicationContext.LOAD_TIME_WEAVER_BEAN_NAME)
074        @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
075        public LoadTimeWeaver loadTimeWeaver() {
076                LoadTimeWeaver loadTimeWeaver = null;
077
078                if (this.ltwConfigurer != null) {
079                        // The user has provided a custom LoadTimeWeaver instance
080                        loadTimeWeaver = this.ltwConfigurer.getLoadTimeWeaver();
081                }
082
083                if (loadTimeWeaver == null) {
084                        // No custom LoadTimeWeaver provided -> fall back to the default
085                        loadTimeWeaver = new DefaultContextLoadTimeWeaver(this.beanClassLoader);
086                }
087
088                AspectJWeaving aspectJWeaving = this.enableLTW.getEnum("aspectjWeaving");
089                switch (aspectJWeaving) {
090                        case DISABLED:
091                                // AJ weaving is disabled -> do nothing
092                                break;
093                        case AUTODETECT:
094                                if (this.beanClassLoader.getResource(AspectJWeavingEnabler.ASPECTJ_AOP_XML_RESOURCE) == null) {
095                                        // No aop.xml present on the classpath -> treat as 'disabled'
096                                        break;
097                                }
098                                // aop.xml is present on the classpath -> enable
099                                AspectJWeavingEnabler.enableAspectJWeaving(loadTimeWeaver, this.beanClassLoader);
100                                break;
101                        case ENABLED:
102                                AspectJWeavingEnabler.enableAspectJWeaving(loadTimeWeaver, this.beanClassLoader);
103                                break;
104                }
105
106                return loadTimeWeaver;
107        }
108
109}