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}