Support for pre-generated CGLIB proxy classes (in AOT scenarios)
Includes runtime storing of generated classes to a directory specified by the "cglib.generatedClasses" system property. Avoids lazy CGLIB fast-class generation and replaces generated Enhancer and MethodWrapper key classes with equivalent record types. Introduces support for early type determination in InstantiationStrategy, AopProxy and SmartInstantiationAwareBeanPostProcessor - in order to trigger CGLIB class generation in refreshForAotProcessing (through early determineBeanType calls for bean definitions). Closes gh-28115
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -422,6 +422,11 @@ public class ClassPathScanningCandidateComponentProvider implements EnvironmentC
|
||||
boolean traceEnabled = logger.isTraceEnabled();
|
||||
boolean debugEnabled = logger.isDebugEnabled();
|
||||
for (Resource resource : resources) {
|
||||
String filename = resource.getFilename();
|
||||
if (filename != null && filename.contains(ClassUtils.CGLIB_CLASS_SEPARATOR)) {
|
||||
// Ignore CGLIB-generated classes in the classpath
|
||||
continue;
|
||||
}
|
||||
if (traceEnabled) {
|
||||
logger.trace("Scanning " + resource);
|
||||
}
|
||||
|
||||
@@ -123,6 +123,7 @@ class ConfigurationClassEnhancer {
|
||||
enhancer.setInterfaces(new Class<?>[] {EnhancedConfiguration.class});
|
||||
enhancer.setUseFactory(false);
|
||||
enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
|
||||
enhancer.setAttemptLoad(true);
|
||||
enhancer.setStrategy(new BeanFactoryAwareGeneratorStrategy(classLoader));
|
||||
enhancer.setCallbackFilter(CALLBACK_FILTER);
|
||||
enhancer.setCallbackTypes(CALLBACK_FILTER.getCallbackTypes());
|
||||
@@ -508,6 +509,7 @@ class ConfigurationClassEnhancer {
|
||||
Enhancer enhancer = new Enhancer();
|
||||
enhancer.setSuperclass(factoryBean.getClass());
|
||||
enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
|
||||
enhancer.setAttemptLoad(true);
|
||||
enhancer.setCallbackType(MethodInterceptor.class);
|
||||
|
||||
// Ideally create enhanced FactoryBean proxy without constructor side effects,
|
||||
|
||||
@@ -64,7 +64,6 @@ import org.springframework.context.ApplicationStartupAware;
|
||||
import org.springframework.context.EnvironmentAware;
|
||||
import org.springframework.context.ResourceLoaderAware;
|
||||
import org.springframework.context.annotation.ConfigurationClassEnhancer.EnhancedConfiguration;
|
||||
import org.springframework.core.NativeDetector;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.PriorityOrdered;
|
||||
import org.springframework.core.env.Environment;
|
||||
@@ -286,11 +285,8 @@ public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPo
|
||||
}
|
||||
|
||||
@Override
|
||||
public BeanFactoryInitializationAotContribution processAheadOfTime(
|
||||
ConfigurableListableBeanFactory beanFactory) {
|
||||
|
||||
return (beanFactory.containsBean(IMPORT_REGISTRY_BEAN_NAME)
|
||||
? new AotContribution(beanFactory) : null);
|
||||
public BeanFactoryInitializationAotContribution processAheadOfTime(ConfigurableListableBeanFactory beanFactory) {
|
||||
return (beanFactory.containsBean(IMPORT_REGISTRY_BEAN_NAME) ? new AotContribution(beanFactory) : null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -452,7 +448,7 @@ public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPo
|
||||
configBeanDefs.put(beanName, abd);
|
||||
}
|
||||
}
|
||||
if (configBeanDefs.isEmpty() || NativeDetector.inNativeImage()) {
|
||||
if (configBeanDefs.isEmpty()) {
|
||||
// nothing to enhance -> return immediately
|
||||
enhanceConfigClasses.end();
|
||||
return;
|
||||
@@ -514,8 +510,8 @@ public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPo
|
||||
|
||||
private static final String BEAN_FACTORY_VARIABLE = BeanFactoryInitializationCode.BEAN_FACTORY_VARIABLE;
|
||||
|
||||
private static final ParameterizedTypeName STRING_STRING_MAP = ParameterizedTypeName
|
||||
.get(Map.class, String.class, String.class);
|
||||
private static final ParameterizedTypeName STRING_STRING_MAP =
|
||||
ParameterizedTypeName.get(Map.class, String.class, String.class);
|
||||
|
||||
private static final String MAPPINGS_VARIABLE = "mappings";
|
||||
|
||||
@@ -523,15 +519,12 @@ public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPo
|
||||
|
||||
private static final String BEAN_NAME = "org.springframework.context.annotation.internalImportAwareAotProcessor";
|
||||
|
||||
|
||||
private final ConfigurableListableBeanFactory beanFactory;
|
||||
|
||||
|
||||
public AotContribution(ConfigurableListableBeanFactory beanFactory) {
|
||||
this.beanFactory = beanFactory;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void applyTo(GenerationContext generationContext,
|
||||
BeanFactoryInitializationCode beanFactoryInitializationCode) {
|
||||
@@ -550,11 +543,8 @@ public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPo
|
||||
}
|
||||
}
|
||||
|
||||
private void generateAddPostProcessorMethod(MethodSpec.Builder method,
|
||||
Map<String, String> mappings) {
|
||||
|
||||
method.addJavadoc(
|
||||
"Add ImportAwareBeanPostProcessor to support ImportAware beans");
|
||||
private void generateAddPostProcessorMethod(MethodSpec.Builder method, Map<String, String> mappings) {
|
||||
method.addJavadoc("Add ImportAwareBeanPostProcessor to support ImportAware beans");
|
||||
method.addModifiers(Modifier.PRIVATE);
|
||||
method.addParameter(DefaultListableBeanFactory.class, BEAN_FACTORY_VARIABLE);
|
||||
method.addCode(generateAddPostProcessorCode(mappings));
|
||||
|
||||
@@ -18,6 +18,7 @@ package org.springframework.context.support;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
@@ -29,6 +30,7 @@ import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.BeanDefinitionCustomizer;
|
||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||
import org.springframework.beans.factory.config.SmartInstantiationAwareBeanPostProcessor;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
|
||||
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
||||
@@ -408,8 +410,29 @@ public class GenericApplicationContext extends AbstractApplicationContext implem
|
||||
invokeBeanFactoryPostProcessors(this.beanFactory);
|
||||
this.beanFactory.freezeConfiguration();
|
||||
PostProcessorRegistrationDelegate.invokeMergedBeanDefinitionPostProcessors(this.beanFactory);
|
||||
preDetermineBeanTypes();
|
||||
}
|
||||
|
||||
/**
|
||||
* Pre-determine bean types in order to trigger early proxy class creation.
|
||||
* @see org.springframework.beans.factory.BeanFactory#getType
|
||||
* @see SmartInstantiationAwareBeanPostProcessor#determineBeanType
|
||||
*/
|
||||
private void preDetermineBeanTypes() {
|
||||
List<SmartInstantiationAwareBeanPostProcessor> bpps =
|
||||
PostProcessorRegistrationDelegate.loadBeanPostProcessors(
|
||||
this.beanFactory, SmartInstantiationAwareBeanPostProcessor.class);
|
||||
for (String beanName : this.beanFactory.getBeanDefinitionNames()) {
|
||||
Class<?> beanType = this.beanFactory.getType(beanName);
|
||||
if (beanType != null) {
|
||||
for (SmartInstantiationAwareBeanPostProcessor bpp : bpps) {
|
||||
beanType = bpp.determineBeanType(beanType, beanName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// Convenient methods for registering individual beans
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user