|
|
|
|
@@ -81,8 +81,7 @@ class InstanceSupplierCodeGenerator {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
InstanceSupplierCodeGenerator(GenerationContext generationContext,
|
|
|
|
|
ClassName className, GeneratedMethods generatedMethods,
|
|
|
|
|
boolean allowDirectSupplierShortcut) {
|
|
|
|
|
ClassName className, GeneratedMethods generatedMethods, boolean allowDirectSupplierShortcut) {
|
|
|
|
|
|
|
|
|
|
this.generationContext = generationContext;
|
|
|
|
|
this.className = className;
|
|
|
|
|
@@ -104,9 +103,7 @@ class InstanceSupplierCodeGenerator {
|
|
|
|
|
"No suitable executor found for " + registeredBean.getBeanName());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private CodeBlock generateCodeForConstructor(RegisteredBean registeredBean,
|
|
|
|
|
Constructor<?> constructor) {
|
|
|
|
|
|
|
|
|
|
private CodeBlock generateCodeForConstructor(RegisteredBean registeredBean, Constructor<?> constructor) {
|
|
|
|
|
String beanName = registeredBean.getBeanName();
|
|
|
|
|
Class<?> beanClass = registeredBean.getBeanClass();
|
|
|
|
|
Class<?> declaringClass = constructor.getDeclaringClass();
|
|
|
|
|
@@ -122,18 +119,16 @@ class InstanceSupplierCodeGenerator {
|
|
|
|
|
private CodeBlock generateCodeForAccessibleConstructor(String beanName, Class<?> beanClass,
|
|
|
|
|
Constructor<?> constructor, boolean dependsOnBean, Class<?> declaringClass) {
|
|
|
|
|
|
|
|
|
|
this.generationContext.getRuntimeHints().reflection()
|
|
|
|
|
.registerConstructor(constructor, ExecutableMode.INTROSPECT);
|
|
|
|
|
this.generationContext.getRuntimeHints().reflection().registerConstructor(
|
|
|
|
|
constructor, ExecutableMode.INTROSPECT);
|
|
|
|
|
if (!dependsOnBean && constructor.getParameterCount() == 0) {
|
|
|
|
|
if (!this.allowDirectSupplierShortcut) {
|
|
|
|
|
return CodeBlock.of("$T.using($T::new)", InstanceSupplier.class,
|
|
|
|
|
declaringClass);
|
|
|
|
|
return CodeBlock.of("$T.using($T::new)", InstanceSupplier.class, declaringClass);
|
|
|
|
|
}
|
|
|
|
|
if (!isThrowingCheckedException(constructor)) {
|
|
|
|
|
return CodeBlock.of("$T::new", declaringClass);
|
|
|
|
|
}
|
|
|
|
|
return CodeBlock.of("$T.of($T::new)", ThrowingSupplier.class,
|
|
|
|
|
declaringClass);
|
|
|
|
|
return CodeBlock.of("$T.of($T::new)", ThrowingSupplier.class, declaringClass);
|
|
|
|
|
}
|
|
|
|
|
GeneratedMethod generatedMethod = generateGetInstanceSupplierMethod(method ->
|
|
|
|
|
buildGetInstanceMethodForConstructor(method, beanName, beanClass, constructor,
|
|
|
|
|
@@ -167,12 +162,11 @@ class InstanceSupplierCodeGenerator {
|
|
|
|
|
CodeBlock.Builder code = CodeBlock.builder();
|
|
|
|
|
code.add(generateResolverForConstructor(beanClass, constructor, parameterOffset));
|
|
|
|
|
boolean hasArguments = constructor.getParameterCount() > 0;
|
|
|
|
|
CodeBlock arguments = hasArguments
|
|
|
|
|
? new AutowiredArgumentsCodeGenerator(declaringClass, constructor)
|
|
|
|
|
.generateCode(constructor.getParameterTypes(), parameterOffset)
|
|
|
|
|
CodeBlock arguments = hasArguments ?
|
|
|
|
|
new AutowiredArgumentsCodeGenerator(declaringClass, constructor)
|
|
|
|
|
.generateCode(constructor.getParameterTypes(), parameterOffset)
|
|
|
|
|
: NO_ARGS;
|
|
|
|
|
CodeBlock newInstance = generateNewInstanceCodeForConstructor(dependsOnBean,
|
|
|
|
|
declaringClass, arguments);
|
|
|
|
|
CodeBlock newInstance = generateNewInstanceCodeForConstructor(dependsOnBean, declaringClass, arguments);
|
|
|
|
|
code.add(generateWithGeneratorCode(hasArguments, newInstance));
|
|
|
|
|
method.addStatement(code.build());
|
|
|
|
|
}
|
|
|
|
|
@@ -180,10 +174,8 @@ class InstanceSupplierCodeGenerator {
|
|
|
|
|
private CodeBlock generateResolverForConstructor(Class<?> beanClass,
|
|
|
|
|
Constructor<?> constructor, int parameterOffset) {
|
|
|
|
|
|
|
|
|
|
CodeBlock parameterTypes = generateParameterTypesCode(
|
|
|
|
|
constructor.getParameterTypes(), parameterOffset);
|
|
|
|
|
return CodeBlock.of("return $T.<$T>forConstructor($L)",
|
|
|
|
|
BeanInstanceSupplier.class, beanClass, parameterTypes);
|
|
|
|
|
CodeBlock parameterTypes = generateParameterTypesCode(constructor.getParameterTypes(), parameterOffset);
|
|
|
|
|
return CodeBlock.of("return $T.<$T>forConstructor($L)", BeanInstanceSupplier.class, beanClass, parameterTypes);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private CodeBlock generateNewInstanceCodeForConstructor(boolean dependsOnBean,
|
|
|
|
|
@@ -207,18 +199,17 @@ class InstanceSupplierCodeGenerator {
|
|
|
|
|
boolean dependsOnBean = !Modifier.isStatic(factoryMethod.getModifiers());
|
|
|
|
|
Visibility accessVisibility = getAccessVisibility(registeredBean, factoryMethod);
|
|
|
|
|
if (accessVisibility != Visibility.PRIVATE) {
|
|
|
|
|
return generateCodeForAccessibleFactoryMethod(beanName, beanClass, factoryMethod,
|
|
|
|
|
declaringClass, dependsOnBean);
|
|
|
|
|
return generateCodeForAccessibleFactoryMethod(
|
|
|
|
|
beanName, beanClass, factoryMethod, declaringClass, dependsOnBean);
|
|
|
|
|
}
|
|
|
|
|
return generateCodeForInaccessibleFactoryMethod(beanName, beanClass, factoryMethod,
|
|
|
|
|
declaringClass);
|
|
|
|
|
return generateCodeForInaccessibleFactoryMethod(beanName, beanClass, factoryMethod, declaringClass);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private CodeBlock generateCodeForAccessibleFactoryMethod(String beanName,
|
|
|
|
|
Class<?> beanClass, Method factoryMethod, Class<?> declaringClass, boolean dependsOnBean) {
|
|
|
|
|
|
|
|
|
|
this.generationContext.getRuntimeHints().reflection()
|
|
|
|
|
.registerMethod(factoryMethod, ExecutableMode.INTROSPECT);
|
|
|
|
|
this.generationContext.getRuntimeHints().reflection().registerMethod(
|
|
|
|
|
factoryMethod, ExecutableMode.INTROSPECT);
|
|
|
|
|
if (!dependsOnBean && factoryMethod.getParameterCount() == 0) {
|
|
|
|
|
CodeBlock.Builder code = CodeBlock.builder();
|
|
|
|
|
code.add("$T.<$T>forFactoryMethod($T.class, $S)", BeanInstanceSupplier.class,
|
|
|
|
|
@@ -235,14 +226,13 @@ class InstanceSupplierCodeGenerator {
|
|
|
|
|
private CodeBlock generateCodeForInaccessibleFactoryMethod(String beanName, Class<?> beanClass,
|
|
|
|
|
Method factoryMethod, Class<?> declaringClass) {
|
|
|
|
|
|
|
|
|
|
this.generationContext.getRuntimeHints().reflection()
|
|
|
|
|
.registerMethod(factoryMethod, ExecutableMode.INVOKE);
|
|
|
|
|
this.generationContext.getRuntimeHints().reflection().registerMethod(factoryMethod, ExecutableMode.INVOKE);
|
|
|
|
|
GeneratedMethod getInstanceMethod = generateGetInstanceSupplierMethod(method -> {
|
|
|
|
|
method.addJavadoc("Get the bean instance supplier for '$L'.", beanName);
|
|
|
|
|
method.addModifiers(PRIVATE_STATIC);
|
|
|
|
|
method.returns(ParameterizedTypeName.get(BeanInstanceSupplier.class, beanClass));
|
|
|
|
|
method.addStatement(generateInstanceSupplierForFactoryMethod(beanClass, factoryMethod,
|
|
|
|
|
declaringClass, factoryMethod.getName()));
|
|
|
|
|
method.addStatement(generateInstanceSupplierForFactoryMethod(
|
|
|
|
|
beanClass, factoryMethod, declaringClass, factoryMethod.getName()));
|
|
|
|
|
});
|
|
|
|
|
return generateReturnStatement(getInstanceMethod);
|
|
|
|
|
}
|
|
|
|
|
@@ -256,14 +246,15 @@ class InstanceSupplierCodeGenerator {
|
|
|
|
|
method.addModifiers(modifiers);
|
|
|
|
|
method.returns(ParameterizedTypeName.get(BeanInstanceSupplier.class, beanClass));
|
|
|
|
|
CodeBlock.Builder code = CodeBlock.builder();
|
|
|
|
|
code.add(generateInstanceSupplierForFactoryMethod(beanClass, factoryMethod, declaringClass, factoryMethodName));
|
|
|
|
|
code.add(generateInstanceSupplierForFactoryMethod(
|
|
|
|
|
beanClass, factoryMethod, declaringClass, factoryMethodName));
|
|
|
|
|
boolean hasArguments = factoryMethod.getParameterCount() > 0;
|
|
|
|
|
CodeBlock arguments = hasArguments
|
|
|
|
|
? new AutowiredArgumentsCodeGenerator(declaringClass, factoryMethod)
|
|
|
|
|
.generateCode(factoryMethod.getParameterTypes())
|
|
|
|
|
CodeBlock arguments = hasArguments ?
|
|
|
|
|
new AutowiredArgumentsCodeGenerator(declaringClass, factoryMethod)
|
|
|
|
|
.generateCode(factoryMethod.getParameterTypes())
|
|
|
|
|
: NO_ARGS;
|
|
|
|
|
CodeBlock newInstance = generateNewInstanceCodeForMethod(dependsOnBean,
|
|
|
|
|
declaringClass, factoryMethodName, arguments);
|
|
|
|
|
CodeBlock newInstance = generateNewInstanceCodeForMethod(
|
|
|
|
|
dependsOnBean, declaringClass, factoryMethodName, arguments);
|
|
|
|
|
code.add(generateWithGeneratorCode(hasArguments, newInstance));
|
|
|
|
|
method.addStatement(code.build());
|
|
|
|
|
}
|
|
|
|
|
@@ -276,11 +267,9 @@ class InstanceSupplierCodeGenerator {
|
|
|
|
|
BeanInstanceSupplier.class, beanClass, declaringClass,
|
|
|
|
|
factoryMethodName);
|
|
|
|
|
}
|
|
|
|
|
CodeBlock parameterTypes = generateParameterTypesCode(
|
|
|
|
|
factoryMethod.getParameterTypes(), 0);
|
|
|
|
|
CodeBlock parameterTypes = generateParameterTypesCode(factoryMethod.getParameterTypes(), 0);
|
|
|
|
|
return CodeBlock.of("return $T.<$T>forFactoryMethod($T.class, $S, $L)",
|
|
|
|
|
BeanInstanceSupplier.class, beanClass, declaringClass,
|
|
|
|
|
factoryMethodName, parameterTypes);
|
|
|
|
|
BeanInstanceSupplier.class, beanClass, declaringClass, factoryMethodName, parameterTypes);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private CodeBlock generateNewInstanceCodeForMethod(boolean dependsOnBean,
|
|
|
|
|
@@ -310,11 +299,8 @@ class InstanceSupplierCodeGenerator {
|
|
|
|
|
return code.build();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private Visibility getAccessVisibility(RegisteredBean registeredBean,
|
|
|
|
|
Member member) {
|
|
|
|
|
|
|
|
|
|
AccessControl beanTypeAccessControl = AccessControl
|
|
|
|
|
.forResolvableType(registeredBean.getBeanType());
|
|
|
|
|
private Visibility getAccessVisibility(RegisteredBean registeredBean, Member member) {
|
|
|
|
|
AccessControl beanTypeAccessControl = AccessControl.forResolvableType(registeredBean.getBeanType());
|
|
|
|
|
AccessControl memberAccessControl = AccessControl.forMember(member);
|
|
|
|
|
return AccessControl.lowest(beanTypeAccessControl, memberAccessControl).getVisibility();
|
|
|
|
|
}
|
|
|
|
|
|