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