Allow AccessControl to determine visibility from a given type
This commit adapts AccessVisibility so that it can determine if the member or type signature is accessible from a given package. This lets implementers figure out if reflection is necessary without assuming that package private visibility is OK. Closes gh-29245
This commit is contained in:
@@ -20,9 +20,10 @@ import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Member;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.springframework.aot.generate.AccessVisibility;
|
||||
import org.springframework.aot.generate.AccessControl;
|
||||
import org.springframework.aot.hint.ExecutableMode;
|
||||
import org.springframework.aot.hint.RuntimeHints;
|
||||
import org.springframework.javapoet.ClassName;
|
||||
import org.springframework.javapoet.CodeBlock;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
@@ -45,11 +46,15 @@ import org.springframework.util.ReflectionUtils;
|
||||
*/
|
||||
class InjectionCodeGenerator {
|
||||
|
||||
private final ClassName targetClassName;
|
||||
|
||||
private final RuntimeHints hints;
|
||||
|
||||
|
||||
InjectionCodeGenerator(RuntimeHints hints) {
|
||||
InjectionCodeGenerator(ClassName targetClassName, RuntimeHints hints) {
|
||||
Assert.notNull(hints, "TargetClassName must not be null");
|
||||
Assert.notNull(hints, "Hints must not be null");
|
||||
this.targetClassName = targetClassName;
|
||||
this.hints = hints;
|
||||
}
|
||||
|
||||
@@ -72,9 +77,8 @@ class InjectionCodeGenerator {
|
||||
CodeBlock resourceToInject) {
|
||||
|
||||
CodeBlock.Builder code = CodeBlock.builder();
|
||||
AccessVisibility visibility = AccessVisibility.forMember(field);
|
||||
if (visibility == AccessVisibility.PRIVATE
|
||||
|| visibility == AccessVisibility.PROTECTED) {
|
||||
AccessControl accessControl = AccessControl.forMember(field);
|
||||
if (!accessControl.isAccessibleFrom(this.targetClassName)) {
|
||||
this.hints.reflection().registerField(field);
|
||||
code.addStatement("$T field = $T.findField($T.class, $S)", Field.class,
|
||||
ReflectionUtils.class, field.getDeclaringClass(), field.getName());
|
||||
@@ -95,9 +99,8 @@ class InjectionCodeGenerator {
|
||||
Assert.isTrue(method.getParameterCount() == 1,
|
||||
"Method '" + method.getName() + "' must declare a single parameter");
|
||||
CodeBlock.Builder code = CodeBlock.builder();
|
||||
AccessVisibility visibility = AccessVisibility.forMember(method);
|
||||
if (visibility == AccessVisibility.PRIVATE
|
||||
|| visibility == AccessVisibility.PROTECTED) {
|
||||
AccessControl accessControl = AccessControl.forMember(method);
|
||||
if (!accessControl.isAccessibleFrom(this.targetClassName)) {
|
||||
this.hints.reflection().registerMethod(method, ExecutableMode.INVOKE);
|
||||
code.addStatement("$T method = $T.findMethod($T.class, $S, $T.class)",
|
||||
Method.class, ReflectionUtils.class, method.getDeclaringClass(),
|
||||
|
||||
@@ -794,16 +794,17 @@ public class PersistenceAnnotationBeanPostProcessor implements InstantiationAwar
|
||||
method.addParameter(RegisteredBean.class, REGISTERED_BEAN_PARAMETER);
|
||||
method.addParameter(this.target, INSTANCE_PARAMETER);
|
||||
method.returns(this.target);
|
||||
method.addCode(generateMethodCode(generationContext.getRuntimeHints(), generatedClass.getMethods()));
|
||||
method.addCode(generateMethodCode(generationContext.getRuntimeHints(), generatedClass));
|
||||
});
|
||||
beanRegistrationCode.addInstancePostProcessor(generatedMethod.toMethodReference());
|
||||
}
|
||||
|
||||
private CodeBlock generateMethodCode(RuntimeHints hints, GeneratedMethods generatedMethods) {
|
||||
private CodeBlock generateMethodCode(RuntimeHints hints, GeneratedClass generatedClass) {
|
||||
CodeBlock.Builder code = CodeBlock.builder();
|
||||
InjectionCodeGenerator injectionCodeGenerator = new InjectionCodeGenerator(hints);
|
||||
InjectionCodeGenerator injectionCodeGenerator = new InjectionCodeGenerator(
|
||||
generatedClass.getName(), hints);
|
||||
for (InjectedElement injectedElement : this.injectedElements) {
|
||||
CodeBlock resourceToInject = generateResourceToInjectCode(generatedMethods,
|
||||
CodeBlock resourceToInject = generateResourceToInjectCode(generatedClass.getMethods(),
|
||||
(PersistenceElement) injectedElement);
|
||||
code.add(injectionCodeGenerator.generateInjectionCode(
|
||||
injectedElement.getMember(), INSTANCE_PARAMETER,
|
||||
@@ -823,9 +824,9 @@ public class PersistenceAnnotationBeanPostProcessor implements InstantiationAwar
|
||||
EntityManagerFactoryUtils.class, ListableBeanFactory.class,
|
||||
REGISTERED_BEAN_PARAMETER, unitName);
|
||||
}
|
||||
String[] methodNameParts = { "get" , unitName, "EntityManager" };
|
||||
String[] methodNameParts = { "get", unitName, "EntityManager" };
|
||||
GeneratedMethod generatedMethod = generatedMethods.add(methodNameParts, method ->
|
||||
generateGetEntityManagerMethod(method, injectedElement));
|
||||
generateGetEntityManagerMethod(method, injectedElement));
|
||||
return CodeBlock.of("$L($L)", generatedMethod.getName(), REGISTERED_BEAN_PARAMETER);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user