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; 029import org.springframework.lang.Nullable; 030import org.springframework.util.Assert; 031 032/** 033 * {@code @Configuration} class that registers a {@link LoadTimeWeaver} bean. 034 * 035 * <p>This configuration class is automatically imported when using the 036 * {@link EnableLoadTimeWeaving} annotation. See {@code @EnableLoadTimeWeaving} 037 * javadoc for complete usage details. 038 * 039 * @author Chris Beams 040 * @since 3.1 041 * @see LoadTimeWeavingConfigurer 042 * @see ConfigurableApplicationContext#LOAD_TIME_WEAVER_BEAN_NAME 043 */ 044@Configuration 045@Role(BeanDefinition.ROLE_INFRASTRUCTURE) 046public class LoadTimeWeavingConfiguration implements ImportAware, BeanClassLoaderAware { 047 048 @Nullable 049 private AnnotationAttributes enableLTW; 050 051 @Nullable 052 private LoadTimeWeavingConfigurer ltwConfigurer; 053 054 @Nullable 055 private ClassLoader beanClassLoader; 056 057 058 @Override 059 public void setImportMetadata(AnnotationMetadata importMetadata) { 060 this.enableLTW = AnnotationConfigUtils.attributesFor(importMetadata, EnableLoadTimeWeaving.class); 061 if (this.enableLTW == null) { 062 throw new IllegalArgumentException( 063 "@EnableLoadTimeWeaving is not present on importing class " + importMetadata.getClassName()); 064 } 065 } 066 067 @Autowired(required = false) 068 public void setLoadTimeWeavingConfigurer(LoadTimeWeavingConfigurer ltwConfigurer) { 069 this.ltwConfigurer = ltwConfigurer; 070 } 071 072 @Override 073 public void setBeanClassLoader(ClassLoader beanClassLoader) { 074 this.beanClassLoader = beanClassLoader; 075 } 076 077 078 @Bean(name = ConfigurableApplicationContext.LOAD_TIME_WEAVER_BEAN_NAME) 079 @Role(BeanDefinition.ROLE_INFRASTRUCTURE) 080 public LoadTimeWeaver loadTimeWeaver() { 081 Assert.state(this.beanClassLoader != null, "No ClassLoader set"); 082 LoadTimeWeaver loadTimeWeaver = null; 083 084 if (this.ltwConfigurer != null) { 085 // The user has provided a custom LoadTimeWeaver instance 086 loadTimeWeaver = this.ltwConfigurer.getLoadTimeWeaver(); 087 } 088 089 if (loadTimeWeaver == null) { 090 // No custom LoadTimeWeaver provided -> fall back to the default 091 loadTimeWeaver = new DefaultContextLoadTimeWeaver(this.beanClassLoader); 092 } 093 094 if (this.enableLTW != null) { 095 AspectJWeaving aspectJWeaving = this.enableLTW.getEnum("aspectjWeaving"); 096 switch (aspectJWeaving) { 097 case DISABLED: 098 // AJ weaving is disabled -> do nothing 099 break; 100 case AUTODETECT: 101 if (this.beanClassLoader.getResource(AspectJWeavingEnabler.ASPECTJ_AOP_XML_RESOURCE) == null) { 102 // No aop.xml present on the classpath -> treat as 'disabled' 103 break; 104 } 105 // aop.xml is present on the classpath -> enable 106 AspectJWeavingEnabler.enableAspectJWeaving(loadTimeWeaver, this.beanClassLoader); 107 break; 108 case ENABLED: 109 AspectJWeavingEnabler.enableAspectJWeaving(loadTimeWeaver, this.beanClassLoader); 110 break; 111 } 112 } 113 114 return loadTimeWeaver; 115 } 116 117}