Example usage for org.springframework.beans BeanUtils findPrimaryConstructor

List of usage examples for org.springframework.beans BeanUtils findPrimaryConstructor

Introduction

In this page you can find the example usage for org.springframework.beans BeanUtils findPrimaryConstructor.

Prototype

@SuppressWarnings("unchecked")
@Nullable
public static <T> Constructor<T> findPrimaryConstructor(Class<T> clazz) 

Source Link

Document

Return the primary constructor of the provided class.

Usage

From source file:org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.java

@Override
@Nullable//from   w w  w .  java 2 s  .c om
public Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, final String beanName)
        throws BeanCreationException {

    // Let's check for lookup methods here..
    if (!this.lookupMethodsChecked.contains(beanName)) {
        try {
            ReflectionUtils.doWithMethods(beanClass, method -> {
                Lookup lookup = method.getAnnotation(Lookup.class);
                if (lookup != null) {
                    Assert.state(beanFactory != null, "No BeanFactory available");
                    LookupOverride override = new LookupOverride(method, lookup.value());
                    try {
                        RootBeanDefinition mbd = (RootBeanDefinition) beanFactory
                                .getMergedBeanDefinition(beanName);
                        mbd.getMethodOverrides().addOverride(override);
                    } catch (NoSuchBeanDefinitionException ex) {
                        throw new BeanCreationException(beanName,
                                "Cannot apply @Lookup to beans without corresponding bean definition");
                    }
                }
            });
        } catch (IllegalStateException ex) {
            throw new BeanCreationException(beanName, "Lookup method resolution failed", ex);
        }
        this.lookupMethodsChecked.add(beanName);
    }

    // Quick check on the concurrent map first, with minimal locking.
    Constructor<?>[] candidateConstructors = this.candidateConstructorsCache.get(beanClass);
    if (candidateConstructors == null) {
        // Fully synchronized resolution now...
        synchronized (this.candidateConstructorsCache) {
            candidateConstructors = this.candidateConstructorsCache.get(beanClass);
            if (candidateConstructors == null) {
                Constructor<?>[] rawCandidates;
                try {
                    rawCandidates = beanClass.getDeclaredConstructors();
                } catch (Throwable ex) {
                    throw new BeanCreationException(beanName,
                            "Resolution of declared constructors on bean Class [" + beanClass.getName()
                                    + "] from ClassLoader [" + beanClass.getClassLoader() + "] failed",
                            ex);
                }
                List<Constructor<?>> candidates = new ArrayList<>(rawCandidates.length);
                Constructor<?> requiredConstructor = null;
                Constructor<?> defaultConstructor = null;
                Constructor<?> primaryConstructor = BeanUtils.findPrimaryConstructor(beanClass);
                int nonSyntheticConstructors = 0;
                for (Constructor<?> candidate : rawCandidates) {
                    if (!candidate.isSynthetic()) {
                        nonSyntheticConstructors++;
                    } else if (primaryConstructor != null) {
                        continue;
                    }
                    AnnotationAttributes ann = findAutowiredAnnotation(candidate);
                    if (ann == null) {
                        Class<?> userClass = ClassUtils.getUserClass(beanClass);
                        if (userClass != beanClass) {
                            try {
                                Constructor<?> superCtor = userClass
                                        .getDeclaredConstructor(candidate.getParameterTypes());
                                ann = findAutowiredAnnotation(superCtor);
                            } catch (NoSuchMethodException ex) {
                                // Simply proceed, no equivalent superclass constructor found...
                            }
                        }
                    }
                    if (ann != null) {
                        if (requiredConstructor != null) {
                            throw new BeanCreationException(beanName, "Invalid autowire-marked constructor: "
                                    + candidate
                                    + ". Found constructor with 'required' Autowired annotation already: "
                                    + requiredConstructor);
                        }
                        boolean required = determineRequiredStatus(ann);
                        if (required) {
                            if (!candidates.isEmpty()) {
                                throw new BeanCreationException(beanName,
                                        "Invalid autowire-marked constructors: " + candidates
                                                + ". Found constructor with 'required' Autowired annotation: "
                                                + candidate);
                            }
                            requiredConstructor = candidate;
                        }
                        candidates.add(candidate);
                    } else if (candidate.getParameterCount() == 0) {
                        defaultConstructor = candidate;
                    }
                }
                if (!candidates.isEmpty()) {
                    // Add default constructor to list of optional constructors, as fallback.
                    if (requiredConstructor == null) {
                        if (defaultConstructor != null) {
                            candidates.add(defaultConstructor);
                        } else if (candidates.size() == 1 && logger.isWarnEnabled()) {
                            logger.warn("Inconsistent constructor declaration on bean with name '" + beanName
                                    + "': single autowire-marked constructor flagged as optional - "
                                    + "this constructor is effectively required since there is no "
                                    + "default constructor to fall back to: " + candidates.get(0));
                        }
                    }
                    candidateConstructors = candidates.toArray(new Constructor<?>[candidates.size()]);
                } else if (rawCandidates.length == 1 && rawCandidates[0].getParameterCount() > 0) {
                    candidateConstructors = new Constructor<?>[] { rawCandidates[0] };
                } else if (nonSyntheticConstructors == 2 && primaryConstructor != null
                        && defaultConstructor != null && !primaryConstructor.equals(defaultConstructor)) {
                    candidateConstructors = new Constructor<?>[] { primaryConstructor, defaultConstructor };
                } else if (nonSyntheticConstructors == 1 && primaryConstructor != null) {
                    candidateConstructors = new Constructor<?>[] { primaryConstructor };
                } else {
                    candidateConstructors = new Constructor<?>[0];
                }
                this.candidateConstructorsCache.put(beanClass, candidateConstructors);
            }
        }
    }
    return (candidateConstructors.length > 0 ? candidateConstructors : null);
}

From source file:org.springframework.web.method.annotation.ModelAttributeMethodProcessor.java

/**
 * Extension point to create the model attribute if not found in the model,
 * with subsequent parameter binding through bean properties (unless suppressed).
 * <p>The default implementation typically uses the unique public no-arg constructor
 * if available but also handles a "primary constructor" approach for data classes:
 * It understands the JavaBeans {@link ConstructorProperties} annotation as well as
 * runtime-retained parameter names in the bytecode, associating request parameters
 * with constructor arguments by name. If no such constructor is found, the default
 * constructor will be used (even if not public), assuming subsequent bean property
 * bindings through setter methods./* w w w.j av a2  s . c  om*/
 * @param attributeName the name of the attribute (never {@code null})
 * @param parameter the method parameter declaration
 * @param binderFactory for creating WebDataBinder instance
 * @param webRequest the current request
 * @return the created model attribute (never {@code null})
 * @throws BindException in case of constructor argument binding failure
 * @throws Exception in case of constructor invocation failure
 * @see #constructAttribute(Constructor, String, WebDataBinderFactory, NativeWebRequest)
 * @see BeanUtils#findPrimaryConstructor(Class)
 */
protected Object createAttribute(String attributeName, MethodParameter parameter,
        WebDataBinderFactory binderFactory, NativeWebRequest webRequest) throws Exception {

    MethodParameter nestedParameter = parameter.nestedIfOptional();
    Class<?> clazz = nestedParameter.getNestedParameterType();

    Constructor<?> ctor = BeanUtils.findPrimaryConstructor(clazz);
    if (ctor == null) {
        Constructor<?>[] ctors = clazz.getConstructors();
        if (ctors.length == 1) {
            ctor = ctors[0];
        } else {
            try {
                ctor = clazz.getDeclaredConstructor();
            } catch (NoSuchMethodException ex) {
                throw new IllegalStateException("No primary or default constructor found for " + clazz, ex);
            }
        }
    }

    Object attribute = constructAttribute(ctor, attributeName, binderFactory, webRequest);
    if (parameter != nestedParameter) {
        attribute = Optional.of(attribute);
    }
    return attribute;
}