1 /*
2  * Copyright 2002-2012 the original author or authors.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package org.springframework.context.annotation;
18 
19 import java.util.LinkedHashSet;
20 import java.util.Set;
21 
22 import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
23 import org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor;
24 import org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor;
25 import org.springframework.beans.factory.config.BeanDefinition;
26 import org.springframework.beans.factory.config.BeanDefinitionHolder;
27 import org.springframework.beans.factory.support.AbstractBeanDefinition;
28 import org.springframework.beans.factory.support.BeanDefinitionRegistry;
29 import org.springframework.beans.factory.support.RootBeanDefinition;
30 import org.springframework.core.type.AnnotationMetadata;
31 import org.springframework.util.ClassUtils;
32 
33 import static org.springframework.context.annotation.MetadataUtils.*;
34 
35 /**
36  * Utility class that allows for convenient registration of common
37  * {@link org.springframework.beans.factory.config.BeanPostProcessor} and
38  * {@link org.springframework.beans.factory.config.BeanFactoryPostProcessor}
39  * definitions for annotation-based configuration.
40  *
41  * @author Mark Fisher
42  * @author Juergen Hoeller
43  * @author Chris Beams
44  * @since 2.5
45  * @see CommonAnnotationBeanPostProcessor
46  * @see org.springframework.context.annotation.ConfigurationClassPostProcessor
47  * @see org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor
48  * @see org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor
49  * @see org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor
50  */
51 public class AnnotationConfigUtils {
52 
53 	/**
54 	 * The bean name of the internally managed Configuration annotation processor.
55 	 */
56 	public static final String CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME =
57 			"org.springframework.context.annotation.internalConfigurationAnnotationProcessor";
58 
59 	/**
60 	 * The bean name of the internally managed BeanNameGenerator for use when processing
61 	 * {@link Configuration} classes. Set by {@link AnnotationConfigApplicationContext}
62 	 * and {@code AnnotationConfigWebApplicationContext} during bootstrap in order to make
63 	 * any custom name generation strategy available to the underlying
64 	 * {@link ConfigurationClassPostProcessor}.
65 	 * @since 3.1.1
66 	 */
67 	public static final String CONFIGURATION_BEAN_NAME_GENERATOR =
68 			"org.springframework.context.annotation.internalConfigurationBeanNameGenerator";
69 
70 	/**
71 	 * The bean name of the internally managed Autowired annotation processor.
72 	 */
73 	public static final String AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME =
74 			"org.springframework.context.annotation.internalAutowiredAnnotationProcessor";
75 
76 	/**
77 	 * The bean name of the internally managed Required annotation processor.
78 	 */
79 	public static final String REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME =
80 			"org.springframework.context.annotation.internalRequiredAnnotationProcessor";
81 
82 	/**
83 	 * The bean name of the internally managed JSR-250 annotation processor.
84 	 */
85 	public static final String COMMON_ANNOTATION_PROCESSOR_BEAN_NAME =
86 			"org.springframework.context.annotation.internalCommonAnnotationProcessor";
87 
88 	/**
89 	 * The bean name of the internally managed Scheduled annotation processor.
90 	 */
91 	public static final String SCHEDULED_ANNOTATION_PROCESSOR_BEAN_NAME =
92 			"org.springframework.context.annotation.internalScheduledAnnotationProcessor";
93 
94 	/**
95 	 * The bean name of the internally managed Async annotation processor.
96 	 */
97 	public static final String ASYNC_ANNOTATION_PROCESSOR_BEAN_NAME =
98 			"org.springframework.context.annotation.internalAsyncAnnotationProcessor";
99 
100 	/**
101 	 * The bean name of the internally managed AspectJ async execution aspect.
102 	 */
103 	public static final String ASYNC_EXECUTION_ASPECT_BEAN_NAME =
104 			"org.springframework.scheduling.config.internalAsyncExecutionAspect";
105 
106 	/**
107 	 * The class name of the AspectJ async execution aspect.
108 	 */
109 	public static final String ASYNC_EXECUTION_ASPECT_CLASS_NAME =
110 			"org.springframework.scheduling.aspectj.AnnotationAsyncExecutionAspect";
111 
112 	/**
113 	 * The name of the AspectJ async execution aspect @{@code Configuration} class.
114 	 */
115 	public static final String ASYNC_EXECUTION_ASPECT_CONFIGURATION_CLASS_NAME =
116 			"org.springframework.scheduling.aspectj.AspectJAsyncConfiguration";
117 
118 	/**
119 	 * The bean name of the internally managed cache advisor.
120 	 */
121 	public static final String CACHE_ADVISOR_BEAN_NAME =
122 			"org.springframework.cache.config.internalCacheAdvisor";
123 
124 	/**
125 	 * The bean name of the internally managed cache aspect.
126 	 */
127 	public static final String CACHE_ASPECT_BEAN_NAME =
128 			"org.springframework.cache.config.internalCacheAspect";
129 
130 	/**
131 	 * The class name of the AspectJ caching aspect.
132 	 */
133 	public static final String CACHE_ASPECT_CLASS_NAME =
134 			"org.springframework.cache.aspectj.AnnotationCacheAspect";
135 
136 	/**
137 	 * The name of the AspectJ caching aspect @{@code Configuration} class.
138 	 */
139 	public static final String CACHE_ASPECT_CONFIGURATION_CLASS_NAME =
140 			"org.springframework.cache.aspectj.AspectJCachingConfiguration";
141 
142 	/**
143 	 * The bean name of the internally managed JPA annotation processor.
144 	 */
145 	public static final String PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME =
146 			"org.springframework.context.annotation.internalPersistenceAnnotationProcessor";
147 
148 
149 	private static final String PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME =
150 			"org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor";
151 
152 
153 	private static final boolean jsr250Present =
154 			ClassUtils.isPresent("javax.annotation.Resource", AnnotationConfigUtils.class.getClassLoader());
155 
156 	private static final boolean jpaPresent =
157 			ClassUtils.isPresent("javax.persistence.EntityManagerFactory", AnnotationConfigUtils.class.getClassLoader()) &&
158 			ClassUtils.isPresent(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, AnnotationConfigUtils.class.getClassLoader());
159 
160 
161 	/**
162 	 * Register all relevant annotation post processors in the given registry.
163 	 * @param registry the registry to operate on
164 	 */
registerAnnotationConfigProcessors(BeanDefinitionRegistry registry)165 	public static void registerAnnotationConfigProcessors(BeanDefinitionRegistry registry) {
166 		registerAnnotationConfigProcessors(registry, null);
167 	}
168 
169 	/**
170 	 * Register all relevant annotation post processors in the given registry.
171 	 * @param registry the registry to operate on
172 	 * @param source the configuration source element (already extracted)
173 	 * that this registration was triggered from. May be <code>null</code>.
174 	 * @return a Set of BeanDefinitionHolders, containing all bean definitions
175 	 * that have actually been registered by this call
176 	 */
registerAnnotationConfigProcessors( BeanDefinitionRegistry registry, Object source)177 	public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
178 			BeanDefinitionRegistry registry, Object source) {
179 
180 		Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<BeanDefinitionHolder>(4);
181 
182 		if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
183 			RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
184 			def.setSource(source);
185 			beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
186 		}
187 
188 		if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
189 			RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
190 			def.setSource(source);
191 			beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
192 		}
193 
194 		if (!registry.containsBeanDefinition(REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
195 			RootBeanDefinition def = new RootBeanDefinition(RequiredAnnotationBeanPostProcessor.class);
196 			def.setSource(source);
197 			beanDefs.add(registerPostProcessor(registry, def, REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
198 		}
199 
200 		// Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor.
201 		if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {
202 			RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
203 			def.setSource(source);
204 			beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
205 		}
206 
207 		// Check for JPA support, and if present add the PersistenceAnnotationBeanPostProcessor.
208 		if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) {
209 			RootBeanDefinition def = new RootBeanDefinition();
210 			try {
211 				ClassLoader cl = AnnotationConfigUtils.class.getClassLoader();
212 				def.setBeanClass(cl.loadClass(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME));
213 			}
214 			catch (ClassNotFoundException ex) {
215 				throw new IllegalStateException(
216 						"Cannot load optional framework class: " + PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, ex);
217 			}
218 			def.setSource(source);
219 			beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME));
220 		}
221 
222 		return beanDefs;
223 	}
224 
registerPostProcessor( BeanDefinitionRegistry registry, RootBeanDefinition definition, String beanName)225 	private static BeanDefinitionHolder registerPostProcessor(
226 			BeanDefinitionRegistry registry, RootBeanDefinition definition, String beanName) {
227 
228 		definition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
229 		registry.registerBeanDefinition(beanName, definition);
230 		return new BeanDefinitionHolder(definition, beanName);
231 	}
232 
processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd)233 	static void processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd) {
234 		AnnotationMetadata metadata = abd.getMetadata();
235 		if (metadata.isAnnotated(Primary.class.getName())) {
236 			abd.setPrimary(true);
237 		}
238 		if (metadata.isAnnotated(Lazy.class.getName())) {
239 			abd.setLazyInit(attributesFor(metadata, Lazy.class).getBoolean("value"));
240 		}
241 		if (metadata.isAnnotated(DependsOn.class.getName())) {
242 			abd.setDependsOn(attributesFor(metadata, DependsOn.class).getStringArray("value"));
243 		}
244 		if (abd instanceof AbstractBeanDefinition) {
245 			if (metadata.isAnnotated(Role.class.getName())) {
246 				Integer role = attributesFor(metadata, Role.class).getNumber("value");
247 				((AbstractBeanDefinition)abd).setRole(role);
248 			}
249 		}
250 	}
251 
applyScopedProxyMode( ScopeMetadata metadata, BeanDefinitionHolder definition, BeanDefinitionRegistry registry)252 	static BeanDefinitionHolder applyScopedProxyMode(
253 			ScopeMetadata metadata, BeanDefinitionHolder definition, BeanDefinitionRegistry registry) {
254 
255 		ScopedProxyMode scopedProxyMode = metadata.getScopedProxyMode();
256 		if (scopedProxyMode.equals(ScopedProxyMode.NO)) {
257 			return definition;
258 		}
259 		boolean proxyTargetClass = scopedProxyMode.equals(ScopedProxyMode.TARGET_CLASS);
260 		return ScopedProxyCreator.createScopedProxy(definition, registry, proxyTargetClass);
261 	}
262 
263 
264 }
265