001/*
002 * Copyright 2002-2016 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.lang.annotation.Annotation;
020
021import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
022import org.springframework.beans.factory.config.BeanDefinition;
023import org.springframework.core.annotation.AnnotationAttributes;
024import org.springframework.util.Assert;
025
026/**
027 * A {@link ScopeMetadataResolver} implementation that by default checks for
028 * the presence of Spring's {@link Scope @Scope} annotation on the bean class.
029 *
030 * <p>The exact type of annotation that is checked for is configurable via
031 * {@link #setScopeAnnotationType(Class)}.
032 *
033 * @author Mark Fisher
034 * @author Juergen Hoeller
035 * @author Sam Brannen
036 * @since 2.5
037 * @see org.springframework.context.annotation.Scope
038 */
039public class AnnotationScopeMetadataResolver implements ScopeMetadataResolver {
040
041        private final ScopedProxyMode defaultProxyMode;
042
043        protected Class<? extends Annotation> scopeAnnotationType = Scope.class;
044
045
046        /**
047         * Construct a new {@code AnnotationScopeMetadataResolver}.
048         * @see #AnnotationScopeMetadataResolver(ScopedProxyMode)
049         * @see ScopedProxyMode#NO
050         */
051        public AnnotationScopeMetadataResolver() {
052                this.defaultProxyMode = ScopedProxyMode.NO;
053        }
054
055        /**
056         * Construct a new {@code AnnotationScopeMetadataResolver} using the
057         * supplied default {@link ScopedProxyMode}.
058         * @param defaultProxyMode the default scoped-proxy mode
059         */
060        public AnnotationScopeMetadataResolver(ScopedProxyMode defaultProxyMode) {
061                Assert.notNull(defaultProxyMode, "'defaultProxyMode' must not be null");
062                this.defaultProxyMode = defaultProxyMode;
063        }
064
065
066        /**
067         * Set the type of annotation that is checked for by this
068         * {@code AnnotationScopeMetadataResolver}.
069         * @param scopeAnnotationType the target annotation type
070         */
071        public void setScopeAnnotationType(Class<? extends Annotation> scopeAnnotationType) {
072                Assert.notNull(scopeAnnotationType, "'scopeAnnotationType' must not be null");
073                this.scopeAnnotationType = scopeAnnotationType;
074        }
075
076
077        @Override
078        public ScopeMetadata resolveScopeMetadata(BeanDefinition definition) {
079                ScopeMetadata metadata = new ScopeMetadata();
080                if (definition instanceof AnnotatedBeanDefinition) {
081                        AnnotatedBeanDefinition annDef = (AnnotatedBeanDefinition) definition;
082                        AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(
083                                        annDef.getMetadata(), this.scopeAnnotationType);
084                        if (attributes != null) {
085                                metadata.setScopeName(attributes.getString("value"));
086                                ScopedProxyMode proxyMode = attributes.getEnum("proxyMode");
087                                if (proxyMode == null || proxyMode == ScopedProxyMode.DEFAULT) {
088                                        proxyMode = this.defaultProxyMode;
089                                }
090                                metadata.setScopedProxyMode(proxyMode);
091                        }
092                }
093                return metadata;
094        }
095
096}