use of io.micronaut.inject.ast.Element in project micronaut-core by micronaut-projects.
the class TestBeanElementVisitor method visitBeanElement.
@Override
public BeanElement visitBeanElement(BeanElement beanElement, VisitorContext visitorContext) {
Element producingElement = beanElement.getProducingElement();
if (producingElement instanceof MemberElement) {
producingElement = ((MemberElement) producingElement).getDeclaringType();
}
final String name = producingElement.getName();
if (name.startsWith("testbe")) {
theBeanElement = beanElement;
}
if (name.equals("testbe2.Excluded")) {
// tests bean veto
return null;
}
return beanElement;
}
use of io.micronaut.inject.ast.Element in project micronaut-core by micronaut-projects.
the class AopProxyWriter method visitAroundMethod.
/**
* Visit a method that is to be proxied.
*
* @param beanType The bean type.
* @param methodElement The method element
*/
public void visitAroundMethod(TypedElement beanType, MethodElement methodElement) {
ClassElement returnType = methodElement.isSuspend() ? ClassElement.of(Object.class) : methodElement.getReturnType();
Type returnTypeObject = JavaModelUtils.getTypeReference(returnType);
boolean isPrimitive = returnType.isPrimitive();
boolean isVoidReturn = isPrimitive && returnTypeObject.equals(Type.VOID_TYPE);
final Optional<MethodElement> overridden = methodElement.getOwningType().getEnclosedElement(ElementQuery.ALL_METHODS.onlyInstance().named(name -> name.equals(methodElement.getName())).filter(el -> el.overrides(methodElement)));
if (overridden.isPresent()) {
MethodElement overriddenBy = overridden.get();
String methodElementKey = methodElement.getName() + Arrays.stream(methodElement.getSuspendParameters()).map(p -> p.getType().getName()).collect(Collectors.joining(","));
String overriddenByKey = overriddenBy.getName() + Arrays.stream(methodElement.getSuspendParameters()).map(p -> p.getGenericType().getName()).collect(Collectors.joining(","));
if (!methodElementKey.equals(overriddenByKey)) {
buildMethodDelegate(methodElement, overriddenBy, isVoidReturn);
return;
}
}
String methodName = methodElement.getName();
List<ParameterElement> argumentTypeList = Arrays.asList(methodElement.getSuspendParameters());
int argumentCount = argumentTypeList.size();
final Type declaringTypeReference = JavaModelUtils.getTypeReference(beanType);
MethodRef methodKey = new MethodRef(methodName, argumentTypeList, returnTypeObject);
if (!proxiedMethodsRefSet.contains(methodKey)) {
String interceptedProxyClassName = null;
String interceptedProxyBridgeMethodName = null;
if (!isProxyTarget) {
if (!methodElement.isAbstract() || methodElement.isDefault()) {
interceptedProxyClassName = proxyFullName;
interceptedProxyBridgeMethodName = "$$access$$" + methodName;
String bridgeDesc = getMethodDescriptor(returnType, argumentTypeList);
// now build a bridge to invoke the original method
MethodVisitor bridgeWriter = classWriter.visitMethod(ACC_SYNTHETIC, interceptedProxyBridgeMethodName, bridgeDesc, null, null);
GeneratorAdapter bridgeGenerator = new GeneratorAdapter(bridgeWriter, ACC_SYNTHETIC, interceptedProxyBridgeMethodName, bridgeDesc);
bridgeGenerator.loadThis();
for (int i = 0; i < argumentTypeList.size(); i++) {
bridgeGenerator.loadArg(i);
}
String desc = getMethodDescriptor(returnType, argumentTypeList);
bridgeWriter.visitMethodInsn(INVOKESPECIAL, declaringTypeReference.getInternalName(), methodName, desc, this.isInterface && methodElement.isDefault());
pushReturnValue(bridgeWriter, returnType);
bridgeWriter.visitMaxs(DEFAULT_MAX_STACK, 1);
bridgeWriter.visitEnd();
}
}
BeanDefinitionWriter beanDefinitionWriter = parentWriter == null ? proxyBeanDefinitionWriter : parentWriter;
int methodIndex = beanDefinitionWriter.visitExecutableMethod(beanType, methodElement, interceptedProxyClassName, interceptedProxyBridgeMethodName);
int index = proxyMethodCount++;
methodKey.methodIndex = methodIndex;
proxiedMethods.add(methodKey);
proxiedMethodsRefSet.add(methodKey);
proxyTargetMethods.add(methodKey);
buildMethodOverride(returnType, methodName, index, argumentTypeList, argumentCount, isVoidReturn);
}
}
use of io.micronaut.inject.ast.Element in project micronaut-core by micronaut-projects.
the class BeanDefinitionWriter method isInterceptedLifeCycleByType.
private boolean isInterceptedLifeCycleByType(AnnotationMetadata annotationMetadata, String interceptType) {
return isLifeCycleCache.computeIfAbsent(interceptType, s -> {
if (this.beanTypeElement.isAssignable("io.micronaut.aop.Interceptor")) {
// interceptor beans cannot have lifecycle methods intercepted
return false;
}
final Element originatingElement = getOriginatingElements()[0];
final boolean isFactoryMethod = (originatingElement instanceof MethodElement && !(originatingElement instanceof ConstructorElement));
final boolean isProxyTarget = annotationMetadata.booleanValue(AnnotationUtil.ANN_AROUND, "proxyTarget").orElse(false) || isFactoryMethod;
// for beans that are @Around(proxyTarget=false) only the generated AOP impl should be intercepted
final boolean isAopType = StringUtils.isNotEmpty(interceptedType);
final boolean isConstructorInterceptionCandidate = (isProxyTarget && !isAopType) || (isAopType && !isProxyTarget);
final boolean hasAroundConstruct;
final AnnotationValue<Annotation> interceptorBindings = annotationMetadata.getAnnotation(AnnotationUtil.ANN_INTERCEPTOR_BINDINGS);
List<AnnotationValue<Annotation>> interceptorBindingAnnotations;
if (interceptorBindings != null) {
interceptorBindingAnnotations = interceptorBindings.getAnnotations(AnnotationMetadata.VALUE_MEMBER);
hasAroundConstruct = interceptorBindingAnnotations.stream().anyMatch(av -> av.stringValue("kind").map(k -> k.equals(interceptType)).orElse(false));
} else {
interceptorBindingAnnotations = Collections.emptyList();
hasAroundConstruct = false;
}
if (isConstructorInterceptionCandidate) {
return hasAroundConstruct;
} else if (hasAroundConstruct) {
AnnotationMetadata typeMetadata = annotationMetadata;
if (!isSuperFactory && typeMetadata instanceof AnnotationMetadataHierarchy) {
typeMetadata = ((AnnotationMetadataHierarchy) typeMetadata).getRootMetadata();
final AnnotationValue<Annotation> av = typeMetadata.getAnnotation(AnnotationUtil.ANN_INTERCEPTOR_BINDINGS);
if (av != null) {
interceptorBindingAnnotations = av.getAnnotations(AnnotationMetadata.VALUE_MEMBER);
} else {
interceptorBindingAnnotations = Collections.emptyList();
}
}
// if no other AOP advice is applied
return interceptorBindingAnnotations.stream().noneMatch(av -> av.stringValue("kind").map(k -> k.equals("AROUND")).orElse(false));
} else {
return false;
}
});
}
use of io.micronaut.inject.ast.Element in project micronaut-core by micronaut-projects.
the class AbstractBeanDefinitionBuilder method build.
/**
* Build the bean definition writer.
* @return The writer, possibly null if it wasn't possible to build it
*/
@Nullable
public BeanDefinitionWriter build() {
if (exposedTypes != null) {
final AnnotationClassValue[] annotationClassValues = Arrays.stream(exposedTypes).map(ce -> new AnnotationClassValue<>(ce.getName())).toArray(AnnotationClassValue[]::new);
annotate(Bean.class, (builder) -> builder.member("typed", annotationClassValues));
}
final BeanDefinitionWriter beanDefinitionWriter = createBeanDefinitionWriter();
if (typeArguments != null) {
beanDefinitionWriter.visitTypeArguments(this.typeArguments);
}
if (constructorElement == null) {
constructorElement = initConstructor(beanType);
}
if (constructorElement == null) {
visitorContext.fail("Cannot create associated bean with no accessible primary constructor. Consider supply the constructor with createWith(..)", originatingElement);
return null;
} else {
beanDefinitionWriter.visitBeanDefinitionConstructor(constructorElement, !constructorElement.isPublic(), visitorContext);
}
Map<ClassElement, List<MemberElement>> sortedInjections = new LinkedHashMap<>();
List<MemberElement> allInjected = new ArrayList<>();
allInjected.addAll(injectedFields);
allInjected.addAll(injectedMethods);
allInjected.sort(SORTER);
for (MemberElement memberElement : allInjected) {
final List<MemberElement> list = sortedInjections.computeIfAbsent(memberElement.getDeclaringType(), classElement -> new ArrayList<>());
list.add(memberElement);
}
for (List<MemberElement> members : sortedInjections.values()) {
members.sort((o1, o2) -> {
if (o1 instanceof FieldElement && o2 instanceof MethodElement) {
return 1;
} else if (o1 instanceof MethodElement && o1 instanceof FieldElement) {
return -1;
}
return 0;
});
}
for (List<MemberElement> list : sortedInjections.values()) {
for (MemberElement memberElement : list) {
if (memberElement instanceof FieldElement) {
InternalBeanElementField ibf = (InternalBeanElementField) memberElement;
ibf.<InternalBeanElementField>with((element) -> visitField(beanDefinitionWriter, element, element));
} else {
InternalBeanElementMethod ibm = (InternalBeanElementMethod) memberElement;
ibm.<InternalBeanElementMethod>with((element) -> beanDefinitionWriter.visitMethodInjectionPoint(ibm.getDeclaringType(), ibm, ibm.isRequiresReflection(), visitorContext));
}
}
}
for (BeanMethodElement executableMethod : executableMethods) {
beanDefinitionWriter.visitExecutableMethod(beanType, executableMethod, visitorContext);
}
for (BeanMethodElement postConstructMethod : postConstructMethods) {
if (postConstructMethod.getDeclaringType().equals(beanType)) {
beanDefinitionWriter.visitPostConstructMethod(beanType, postConstructMethod, ((InternalBeanElementMethod) postConstructMethod).isRequiresReflection(), visitorContext);
}
}
for (BeanMethodElement preDestroyMethod : preDestroyMethods) {
if (preDestroyMethod.getDeclaringType().equals(beanType)) {
beanDefinitionWriter.visitPreDestroyMethod(beanType, preDestroyMethod, ((InternalBeanElementMethod) preDestroyMethod).isRequiresReflection(), visitorContext);
}
}
beanDefinitionWriter.visitBeanDefinitionEnd();
return beanDefinitionWriter;
}
Aggregations