001/*
002 * Copyright 2002-2018 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.context.annotation;
018
019import java.util.Collections;
020import java.util.LinkedHashSet;
021import java.util.Map;
022import java.util.Set;
023
024import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
025import org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor;
026import org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor;
027import org.springframework.beans.factory.config.BeanDefinition;
028import org.springframework.beans.factory.config.BeanDefinitionHolder;
029import org.springframework.beans.factory.support.AbstractBeanDefinition;
030import org.springframework.beans.factory.support.BeanDefinitionRegistry;
031import org.springframework.beans.factory.support.DefaultListableBeanFactory;
032import org.springframework.beans.factory.support.RootBeanDefinition;
033import org.springframework.context.event.DefaultEventListenerFactory;
034import org.springframework.context.event.EventListenerMethodProcessor;
035import org.springframework.context.support.GenericApplicationContext;
036import org.springframework.core.annotation.AnnotationAttributes;
037import org.springframework.core.annotation.AnnotationAwareOrderComparator;
038import org.springframework.core.type.AnnotatedTypeMetadata;
039import org.springframework.core.type.AnnotationMetadata;
040import org.springframework.util.ClassUtils;
041
042/**
043 * Utility class that allows for convenient registration of common
044 * {@link org.springframework.beans.factory.config.BeanPostProcessor} and
045 * {@link org.springframework.beans.factory.config.BeanFactoryPostProcessor}
046 * definitions for annotation-based configuration. Also registers a common
047 * {@link org.springframework.beans.factory.support.AutowireCandidateResolver}.
048 *
049 * @author Mark Fisher
050 * @author Juergen Hoeller
051 * @author Chris Beams
052 * @author Phillip Webb
053 * @author Stephane Nicoll
054 * @since 2.5
055 * @see ContextAnnotationAutowireCandidateResolver
056 * @see ConfigurationClassPostProcessor
057 * @see CommonAnnotationBeanPostProcessor
058 * @see org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor
059 * @see org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor
060 * @see org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor
061 */
062public class AnnotationConfigUtils {
063
064        /**
065         * The bean name of the internally managed Configuration annotation processor.
066         */
067        public static final String CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME =
068                        "org.springframework.context.annotation.internalConfigurationAnnotationProcessor";
069
070        /**
071         * The bean name of the internally managed BeanNameGenerator for use when processing
072         * {@link Configuration} classes. Set by {@link AnnotationConfigApplicationContext}
073         * and {@code AnnotationConfigWebApplicationContext} during bootstrap in order to make
074         * any custom name generation strategy available to the underlying
075         * {@link ConfigurationClassPostProcessor}.
076         * @since 3.1.1
077         */
078        public static final String CONFIGURATION_BEAN_NAME_GENERATOR =
079                        "org.springframework.context.annotation.internalConfigurationBeanNameGenerator";
080
081        /**
082         * The bean name of the internally managed Autowired annotation processor.
083         */
084        public static final String AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME =
085                        "org.springframework.context.annotation.internalAutowiredAnnotationProcessor";
086
087        /**
088         * The bean name of the internally managed Required annotation processor.
089         */
090        public static final String REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME =
091                        "org.springframework.context.annotation.internalRequiredAnnotationProcessor";
092
093        /**
094         * The bean name of the internally managed JSR-250 annotation processor.
095         */
096        public static final String COMMON_ANNOTATION_PROCESSOR_BEAN_NAME =
097                        "org.springframework.context.annotation.internalCommonAnnotationProcessor";
098
099        /**
100         * The bean name of the internally managed JPA annotation processor.
101         */
102        public static final String PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME =
103                        "org.springframework.context.annotation.internalPersistenceAnnotationProcessor";
104
105        private static final String PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME =
106                        "org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor";
107
108        /**
109         * The bean name of the internally managed @EventListener annotation processor.
110         */
111        public static final String EVENT_LISTENER_PROCESSOR_BEAN_NAME =
112                        "org.springframework.context.event.internalEventListenerProcessor";
113
114        /**
115         * The bean name of the internally managed EventListenerFactory.
116         */
117        public static final String EVENT_LISTENER_FACTORY_BEAN_NAME =
118                        "org.springframework.context.event.internalEventListenerFactory";
119
120        private static final boolean jsr250Present =
121                        ClassUtils.isPresent("javax.annotation.Resource", AnnotationConfigUtils.class.getClassLoader());
122
123        private static final boolean jpaPresent =
124                        ClassUtils.isPresent("javax.persistence.EntityManagerFactory", AnnotationConfigUtils.class.getClassLoader()) &&
125                        ClassUtils.isPresent(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, AnnotationConfigUtils.class.getClassLoader());
126
127
128        /**
129         * Register all relevant annotation post processors in the given registry.
130         * @param registry the registry to operate on
131         */
132        public static void registerAnnotationConfigProcessors(BeanDefinitionRegistry registry) {
133                registerAnnotationConfigProcessors(registry, null);
134        }
135
136        /**
137         * Register all relevant annotation post processors in the given registry.
138         * @param registry the registry to operate on
139         * @param source the configuration source element (already extracted)
140         * that this registration was triggered from. May be {@code null}.
141         * @return a Set of BeanDefinitionHolders, containing all bean definitions
142         * that have actually been registered by this call
143         */
144        public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
145                        BeanDefinitionRegistry registry, Object source) {
146
147                DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
148                if (beanFactory != null) {
149                        if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
150                                beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
151                        }
152                        if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {
153                                beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
154                        }
155                }
156
157                Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<BeanDefinitionHolder>(8);
158
159                if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
160                        RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
161                        def.setSource(source);
162                        beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
163                }
164
165                if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
166                        RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
167                        def.setSource(source);
168                        beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
169                }
170
171                if (!registry.containsBeanDefinition(REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
172                        RootBeanDefinition def = new RootBeanDefinition(RequiredAnnotationBeanPostProcessor.class);
173                        def.setSource(source);
174                        beanDefs.add(registerPostProcessor(registry, def, REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
175                }
176
177                // Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor.
178                if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {
179                        RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
180                        def.setSource(source);
181                        beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
182                }
183
184                // Check for JPA support, and if present add the PersistenceAnnotationBeanPostProcessor.
185                if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) {
186                        RootBeanDefinition def = new RootBeanDefinition();
187                        try {
188                                def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME,
189                                                AnnotationConfigUtils.class.getClassLoader()));
190                        }
191                        catch (ClassNotFoundException ex) {
192                                throw new IllegalStateException(
193                                                "Cannot load optional framework class: " + PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, ex);
194                        }
195                        def.setSource(source);
196                        beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME));
197                }
198
199                if (!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) {
200                        RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class);
201                        def.setSource(source);
202                        beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME));
203                }
204
205                if (!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) {
206                        RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class);
207                        def.setSource(source);
208                        beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME));
209                }
210
211                return beanDefs;
212        }
213
214        private static BeanDefinitionHolder registerPostProcessor(
215                        BeanDefinitionRegistry registry, RootBeanDefinition definition, String beanName) {
216
217                definition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
218                registry.registerBeanDefinition(beanName, definition);
219                return new BeanDefinitionHolder(definition, beanName);
220        }
221
222        private static DefaultListableBeanFactory unwrapDefaultListableBeanFactory(BeanDefinitionRegistry registry) {
223                if (registry instanceof DefaultListableBeanFactory) {
224                        return (DefaultListableBeanFactory) registry;
225                }
226                else if (registry instanceof GenericApplicationContext) {
227                        return ((GenericApplicationContext) registry).getDefaultListableBeanFactory();
228                }
229                else {
230                        return null;
231                }
232        }
233
234        public static void processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd) {
235                processCommonDefinitionAnnotations(abd, abd.getMetadata());
236        }
237
238        static void processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd, AnnotatedTypeMetadata metadata) {
239                if (metadata.isAnnotated(Lazy.class.getName())) {
240                        abd.setLazyInit(attributesFor(metadata, Lazy.class).getBoolean("value"));
241                }
242                else if (abd.getMetadata() != metadata && abd.getMetadata().isAnnotated(Lazy.class.getName())) {
243                        abd.setLazyInit(attributesFor(abd.getMetadata(), Lazy.class).getBoolean("value"));
244                }
245
246                if (metadata.isAnnotated(Primary.class.getName())) {
247                        abd.setPrimary(true);
248                }
249                if (metadata.isAnnotated(DependsOn.class.getName())) {
250                        abd.setDependsOn(attributesFor(metadata, DependsOn.class).getStringArray("value"));
251                }
252
253                if (abd instanceof AbstractBeanDefinition) {
254                        AbstractBeanDefinition absBd = (AbstractBeanDefinition) abd;
255                        if (metadata.isAnnotated(Role.class.getName())) {
256                                absBd.setRole(attributesFor(metadata, Role.class).getNumber("value").intValue());
257                        }
258                        if (metadata.isAnnotated(Description.class.getName())) {
259                                absBd.setDescription(attributesFor(metadata, Description.class).getString("value"));
260                        }
261                }
262        }
263
264        static BeanDefinitionHolder applyScopedProxyMode(
265                        ScopeMetadata metadata, BeanDefinitionHolder definition, BeanDefinitionRegistry registry) {
266
267                ScopedProxyMode scopedProxyMode = metadata.getScopedProxyMode();
268                if (scopedProxyMode.equals(ScopedProxyMode.NO)) {
269                        return definition;
270                }
271                boolean proxyTargetClass = scopedProxyMode.equals(ScopedProxyMode.TARGET_CLASS);
272                return ScopedProxyCreator.createScopedProxy(definition, registry, proxyTargetClass);
273        }
274
275        static AnnotationAttributes attributesFor(AnnotatedTypeMetadata metadata, Class<?> annotationClass) {
276                return attributesFor(metadata, annotationClass.getName());
277        }
278
279        static AnnotationAttributes attributesFor(AnnotatedTypeMetadata metadata, String annotationClassName) {
280                return AnnotationAttributes.fromMap(metadata.getAnnotationAttributes(annotationClassName, false));
281        }
282
283        static Set<AnnotationAttributes> attributesForRepeatable(AnnotationMetadata metadata,
284                        Class<?> containerClass, Class<?> annotationClass) {
285
286                return attributesForRepeatable(metadata, containerClass.getName(), annotationClass.getName());
287        }
288
289        @SuppressWarnings("unchecked")
290        static Set<AnnotationAttributes> attributesForRepeatable(
291                        AnnotationMetadata metadata, String containerClassName, String annotationClassName) {
292
293                Set<AnnotationAttributes> result = new LinkedHashSet<AnnotationAttributes>();
294
295                // Direct annotation present?
296                addAttributesIfNotNull(result, metadata.getAnnotationAttributes(annotationClassName, false));
297
298                // Container annotation present?
299                Map<String, Object> container = metadata.getAnnotationAttributes(containerClassName, false);
300                if (container != null && container.containsKey("value")) {
301                        for (Map<String, Object> containedAttributes : (Map<String, Object>[]) container.get("value")) {
302                                addAttributesIfNotNull(result, containedAttributes);
303                        }
304                }
305
306                // Return merged result
307                return Collections.unmodifiableSet(result);
308        }
309
310        private static void addAttributesIfNotNull(Set<AnnotationAttributes> result, Map<String, Object> attributes) {
311                if (attributes != null) {
312                        result.add(AnnotationAttributes.fromMap(attributes));
313                }
314        }
315
316}