001/*
002 * Copyright 2002-2012 the original author or authors.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *      https://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017package org.springframework.beans.factory.annotation;
018
019import java.lang.annotation.Annotation;
020import java.util.Set;
021
022import org.springframework.beans.BeansException;
023import org.springframework.beans.factory.BeanClassLoaderAware;
024import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
025import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
026import org.springframework.beans.factory.support.DefaultListableBeanFactory;
027import org.springframework.core.Ordered;
028import org.springframework.util.ClassUtils;
029
030/**
031 * A {@link org.springframework.beans.factory.config.BeanFactoryPostProcessor}
032 * implementation that allows for convenient registration of custom autowire
033 * qualifier types.
034 *
035 * <pre class="code">
036 * &lt;bean id="customAutowireConfigurer" class="org.springframework.beans.factory.annotation.CustomAutowireConfigurer"&gt;
037 *   &lt;property name="customQualifierTypes"&gt;
038 *     &lt;set&gt;
039 *       &lt;value&gt;mypackage.MyQualifier&lt;/value&gt;
040 *     &lt;/set&gt;
041 *   &lt;/property&gt;
042 * &lt;/bean&gt;</pre>
043 *
044 * @author Mark Fisher
045 * @author Juergen Hoeller
046 * @since 2.5
047 * @see org.springframework.beans.factory.annotation.Qualifier
048 */
049public class CustomAutowireConfigurer implements BeanFactoryPostProcessor, BeanClassLoaderAware, Ordered {
050
051        private int order = Ordered.LOWEST_PRECEDENCE;  // default: same as non-Ordered
052
053        private Set<?> customQualifierTypes;
054
055        private ClassLoader beanClassLoader = ClassUtils.getDefaultClassLoader();
056
057
058        public void setOrder(int order) {
059                this.order = order;
060        }
061
062        @Override
063        public int getOrder() {
064                return this.order;
065        }
066
067        @Override
068        public void setBeanClassLoader(ClassLoader beanClassLoader) {
069                this.beanClassLoader = beanClassLoader;
070        }
071
072        /**
073         * Register custom qualifier annotation types to be considered
074         * when autowiring beans. Each element of the provided set may
075         * be either a Class instance or a String representation of the
076         * fully-qualified class name of the custom annotation.
077         * <p>Note that any annotation that is itself annotated with Spring's
078         * {@link org.springframework.beans.factory.annotation.Qualifier}
079         * does not require explicit registration.
080         * @param customQualifierTypes the custom types to register
081         */
082        public void setCustomQualifierTypes(Set<?> customQualifierTypes) {
083                this.customQualifierTypes = customQualifierTypes;
084        }
085
086
087        @Override
088        @SuppressWarnings("unchecked")
089        public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
090                if (this.customQualifierTypes != null) {
091                        if (!(beanFactory instanceof DefaultListableBeanFactory)) {
092                                throw new IllegalStateException(
093                                                "CustomAutowireConfigurer needs to operate on a DefaultListableBeanFactory");
094                        }
095                        DefaultListableBeanFactory dlbf = (DefaultListableBeanFactory) beanFactory;
096                        if (!(dlbf.getAutowireCandidateResolver() instanceof QualifierAnnotationAutowireCandidateResolver)) {
097                                dlbf.setAutowireCandidateResolver(new QualifierAnnotationAutowireCandidateResolver());
098                        }
099                        QualifierAnnotationAutowireCandidateResolver resolver =
100                                        (QualifierAnnotationAutowireCandidateResolver) dlbf.getAutowireCandidateResolver();
101                        for (Object value : this.customQualifierTypes) {
102                                Class<? extends Annotation> customType = null;
103                                if (value instanceof Class) {
104                                        customType = (Class<? extends Annotation>) value;
105                                }
106                                else if (value instanceof String) {
107                                        String className = (String) value;
108                                        customType = (Class<? extends Annotation>) ClassUtils.resolveClassName(className, this.beanClassLoader);
109                                }
110                                else {
111                                        throw new IllegalArgumentException(
112                                                        "Invalid value [" + value + "] for custom qualifier type: needs to be Class or String.");
113                                }
114                                if (!Annotation.class.isAssignableFrom(customType)) {
115                                        throw new IllegalArgumentException(
116                                                        "Qualifier type [" + customType.getName() + "] needs to be annotation type");
117                                }
118                                resolver.addQualifierType(customType);
119                        }
120                }
121        }
122
123}