001/* 002 * Copyright 2002-2017 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.beans.factory.config; 018 019import java.util.LinkedHashMap; 020import java.util.Map; 021 022import org.springframework.beans.BeanUtils; 023import org.springframework.beans.BeansException; 024import org.springframework.beans.factory.BeanClassLoaderAware; 025import org.springframework.core.Ordered; 026import org.springframework.util.Assert; 027import org.springframework.util.ClassUtils; 028 029/** 030 * Simple {@link BeanFactoryPostProcessor} implementation that registers 031 * custom {@link Scope Scope(s)} with the containing {@link ConfigurableBeanFactory}. 032 * 033 * <p>Will register all of the supplied {@link #setScopes(java.util.Map) scopes} 034 * with the {@link ConfigurableListableBeanFactory} that is passed to the 035 * {@link #postProcessBeanFactory(ConfigurableListableBeanFactory)} method. 036 * 037 * <p>This class allows for <i>declarative</i> registration of custom scopes. 038 * Alternatively, consider implementing a custom {@link BeanFactoryPostProcessor} 039 * that calls {@link ConfigurableBeanFactory#registerScope} programmatically. 040 * 041 * @author Juergen Hoeller 042 * @author Rick Evans 043 * @since 2.0 044 * @see ConfigurableBeanFactory#registerScope 045 */ 046public class CustomScopeConfigurer implements BeanFactoryPostProcessor, BeanClassLoaderAware, Ordered { 047 048 private Map<String, Object> scopes; 049 050 private int order = Ordered.LOWEST_PRECEDENCE; 051 052 private ClassLoader beanClassLoader = ClassUtils.getDefaultClassLoader(); 053 054 055 /** 056 * Specify the custom scopes that are to be registered. 057 * <p>The keys indicate the scope names (of type String); each value 058 * is expected to be the corresponding custom {@link Scope} instance 059 * or class name. 060 */ 061 public void setScopes(Map<String, Object> scopes) { 062 this.scopes = scopes; 063 } 064 065 /** 066 * Add the given scope to this configurer's map of scopes. 067 * @param scopeName the name of the scope 068 * @param scope the scope implementation 069 * @since 4.1.1 070 */ 071 public void addScope(String scopeName, Scope scope) { 072 if (this.scopes == null) { 073 this.scopes = new LinkedHashMap<String, Object>(1); 074 } 075 this.scopes.put(scopeName, scope); 076 } 077 078 079 public void setOrder(int order) { 080 this.order = order; 081 } 082 083 @Override 084 public int getOrder() { 085 return this.order; 086 } 087 088 @Override 089 public void setBeanClassLoader(ClassLoader beanClassLoader) { 090 this.beanClassLoader = beanClassLoader; 091 } 092 093 094 @Override 095 public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { 096 if (this.scopes != null) { 097 for (Map.Entry<String, Object> entry : this.scopes.entrySet()) { 098 String scopeKey = entry.getKey(); 099 Object value = entry.getValue(); 100 if (value instanceof Scope) { 101 beanFactory.registerScope(scopeKey, (Scope) value); 102 } 103 else if (value instanceof Class) { 104 Class<?> scopeClass = (Class<?>) value; 105 Assert.isAssignable(Scope.class, scopeClass, "Invalid scope class"); 106 beanFactory.registerScope(scopeKey, (Scope) BeanUtils.instantiateClass(scopeClass)); 107 } 108 else if (value instanceof String) { 109 Class<?> scopeClass = ClassUtils.resolveClassName((String) value, this.beanClassLoader); 110 Assert.isAssignable(Scope.class, scopeClass, "Invalid scope class"); 111 beanFactory.registerScope(scopeKey, (Scope) BeanUtils.instantiateClass(scopeClass)); 112 } 113 else { 114 throw new IllegalArgumentException("Mapped value [" + value + "] for scope key [" + 115 scopeKey + "] is not an instance of required type [" + Scope.class.getName() + 116 "] or a corresponding Class or String value indicating a Scope implementation"); 117 } 118 } 119 } 120 } 121 122}