/*
* Copyright 2017-2020 original authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.micronaut.inject;
import edu.umd.cs.findbugs.annotations.NonNull;
import edu.umd.cs.findbugs.annotations.Nullable;
import io.micronaut.context.BeanContext;
import io.micronaut.context.BeanResolutionContext;
import io.micronaut.context.Qualifier;
import io.micronaut.core.annotation.AnnotationMetadataDelegate;
import io.micronaut.core.naming.Named;
import io.micronaut.core.reflect.ReflectionUtils;
import io.micronaut.core.type.Argument;
import io.micronaut.inject.qualifiers.Qualifiers;
import java.lang.annotation.Annotation;
import java.lang.reflect.Modifier;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.stream.Stream;
Defines a bean definition and its requirements. A bean definition must have a singled injectable constructor or a
no-args constructor.
Author: Graeme Rocher Type parameters: - <T> – The bean type
Since: 1.0
/**
* Defines a bean definition and its requirements. A bean definition must have a singled injectable constructor or a
* no-args constructor.
*
* @param <T> The bean type
* @author Graeme Rocher
* @since 1.0
*/
public interface BeanDefinition<T> extends AnnotationMetadataDelegate, Named, BeanType<T> {
Attribute used to store a dynamic bean name.
/**
* Attribute used to store a dynamic bean name.
*/
String NAMED_ATTRIBUTE = Named.class.getName();
Returns: The scope of the bean
/**
* @return The scope of the bean
*/
Optional<Class<? extends Annotation>> getScope();
Returns: Whether the scope is singleton
/**
* @return Whether the scope is singleton
*/
boolean isSingleton();
Returns: Is this definition provided by another bean
/**
* @return Is this definition provided by another bean
*/
boolean isProvided();
Returns: Whether the bean declared with EachProperty
or EachBean
/**
* @return Whether the bean declared with {@link io.micronaut.context.annotation.EachProperty} or
* {@link io.micronaut.context.annotation.EachBean}
*/
boolean isIterable();
Returns: The produced bean type
/**
* @return The produced bean type
*/
@Override
Class<T> getBeanType();
Returns: The type that declares this definition, null if not applicable.
/**
* @return The type that declares this definition, null if not applicable.
*/
Optional<Class<?>> getDeclaringType();
The single concrete constructor that is an injection point for creating the bean.
Returns: The constructor injection point
/**
* The single concrete constructor that is an injection point for creating the bean.
*
* @return The constructor injection point
*/
ConstructorInjectionPoint<T> getConstructor();
Returns: All required components for this entity definition
/**
* @return All required components for this entity definition
*/
Collection<Class> getRequiredComponents();
All methods that require injection. This is a subset of all the methods in the class.
Returns: The required properties
/**
* All methods that require injection. This is a subset of all the methods in the class.
*
* @return The required properties
*/
Collection<MethodInjectionPoint> getInjectedMethods();
All the fields that require injection.
Returns: The required fields
/**
* All the fields that require injection.
*
* @return The required fields
*/
Collection<FieldInjectionPoint> getInjectedFields();
All the methods that should be called once the bean has been fully initialized and constructed.
Returns: Methods to call post construct
/**
* All the methods that should be called once the bean has been fully initialized and constructed.
*
* @return Methods to call post construct
*/
Collection<MethodInjectionPoint> getPostConstructMethods();
All the methods that should be called when the object is to be destroyed.
Returns: Methods to call pre-destroy
/**
* All the methods that should be called when the object is to be destroyed.
*
* @return Methods to call pre-destroy
*/
Collection<MethodInjectionPoint> getPreDestroyMethods();
Returns: The class name
/**
* @return The class name
*/
@Override
String getName();
Finds a single ExecutableMethod
for the given name and argument types. Params: - name – The method name
- argumentTypes – The argument types
Type parameters: - <R> – The return type
Returns: An optional ExecutableMethod
/**
* Finds a single {@link ExecutableMethod} for the given name and argument types.
*
* @param name The method name
* @param argumentTypes The argument types
* @param <R> The return type
* @return An optional {@link ExecutableMethod}
*/
<R> Optional<ExecutableMethod<T, R>> findMethod(String name, Class... argumentTypes);
Finds possible methods for the given method name.
Params: - name – The method name
Type parameters: - <R> – The return type
Returns: The possible methods
/**
* Finds possible methods for the given method name.
*
* @param name The method name
* @param <R> The return type
* @return The possible methods
*/
<R> Stream<ExecutableMethod<T, R>> findPossibleMethods(String name);
Inject the given bean with the context.
Params: - context – The context
- bean – The bean
Returns: The injected bean
/**
* Inject the given bean with the context.
*
* @param context The context
* @param bean The bean
* @return The injected bean
*/
T inject(BeanContext context, T bean);
Inject the given bean with the context.
Params: - resolutionContext – the resolution context
- context – The context
- bean – The bean
Returns: The injected bean
/**
* Inject the given bean with the context.
*
* @param resolutionContext the resolution context
* @param context The context
* @param bean The bean
* @return The injected bean
*/
T inject(BeanResolutionContext resolutionContext, BeanContext context, T bean);
Returns: The ExecutableMethod
instances for this definition
/**
* @return The {@link ExecutableMethod} instances for this definition
*/
Collection<ExecutableMethod<T, ?>> getExecutableMethods();
Whether this bean definition represents a proxy.
Returns: True if it represents a proxy
/**
* Whether this bean definition represents a proxy.
*
* @return True if it represents a proxy
*/
default boolean isProxy() {
return this instanceof ProxyBeanDefinition;
}
If the bean itself declares any type arguments this method will return the classes that represent those types.
Returns: The type arguments
/**
* If the bean itself declares any type arguments this method will return the classes that represent those types.
*
* @return The type arguments
*/
default @NonNull List<Argument<?>> getTypeArguments() {
return getTypeArguments(getBeanType());
}
Return the type arguments for the given interface or super type for this bean.
Params: - type – The super class or interface type
Returns: The type arguments
/**
* Return the type arguments for the given interface or super type for this bean.
*
* @param type The super class or interface type
* @return The type arguments
*/
default @NonNull List<Argument<?>> getTypeArguments(Class<?> type) {
if (type == null) {
return Collections.emptyList();
}
return getTypeArguments(type.getName());
}
Returns the type parameters as a class array for the given type.
Params: - type – The type
Returns: The type parameters
/**
* Returns the type parameters as a class array for the given type.
* @param type The type
* @return The type parameters
*/
default @NonNull Class[] getTypeParameters(@Nullable Class<?> type) {
if (type == null) {
return ReflectionUtils.EMPTY_CLASS_ARRAY;
} else {
final List<Argument<?>> typeArguments = getTypeArguments(type);
return typeArguments.stream().map(Argument::getType).toArray(Class[]::new);
}
}
Returns the type parameters as a class array for the bean type.
Returns: The type parameters for the bean type as a class array.
/**
*
* Returns the type parameters as a class array for the bean type.
*
* @return The type parameters for the bean type as a class array.
*/
default @NonNull Class[] getTypeParameters() {
return getTypeParameters(getBeanType());
}
Return the type arguments for the given interface or super type for this bean.
Params: - type – The super class or interface type
Returns: The type arguments
/**
* Return the type arguments for the given interface or super type for this bean.
*
* @param type The super class or interface type
* @return The type arguments
*/
default @NonNull List<Argument<?>> getTypeArguments(String type) {
return Collections.emptyList();
}
Finds a single ExecutableMethod
for the given name and argument types. Params: - name – The method name
- argumentTypes – The argument types
Type parameters: - <R> – The return type
Throws: - IllegalStateException – If the method cannot be found
Returns: An optional ExecutableMethod
/**
* Finds a single {@link ExecutableMethod} for the given name and argument types.
*
* @param name The method name
* @param argumentTypes The argument types
* @param <R> The return type
* @return An optional {@link ExecutableMethod}
* @throws IllegalStateException If the method cannot be found
*/
@SuppressWarnings("unchecked")
default <R> ExecutableMethod<T, R> getRequiredMethod(String name, Class... argumentTypes) {
return (ExecutableMethod<T, R>) findMethod(name, argumentTypes)
.orElseThrow(() -> ReflectionUtils.newNoSuchMethodError(getBeanType(), name, argumentTypes));
}
Returns: Whether the bean definition is abstract
/**
* @return Whether the bean definition is abstract
*/
default boolean isAbstract() {
return Modifier.isAbstract(getBeanType().getModifiers());
}
Resolve the declared qualifier for this bean.
Returns: The qualifier or null if this isn't one
/**
* Resolve the declared qualifier for this bean.
* @return The qualifier or null if this isn't one
*/
default @Nullable Qualifier<T> getDeclaredQualifier() {
final String annotation = getAnnotationNameByStereotype(javax.inject.Qualifier.class).orElse(null);
if (annotation != null) {
if (annotation.equals(Qualifier.PRIMARY)) {
// primary is the same as null
return null;
}
return Qualifiers.byAnnotation(this, annotation);
} else {
Qualifier<T> qualifier = resolveDynamicQualifier();
if (qualifier == null) {
String name = stringValue(javax.inject.Named.class).orElse(null);
qualifier = name != null ? Qualifiers.byAnnotation(this, name) : null;
}
return qualifier;
}
}
Returns: Method that can be overridden to resolve a dynamic qualifier
/**
* @return Method that can be overridden to resolve a dynamic qualifier
*/
default @Nullable Qualifier<T> resolveDynamicQualifier() {
return null;
}
}