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.support; 018 019import org.springframework.beans.factory.config.RuntimeBeanReference; 020import org.springframework.util.ObjectUtils; 021 022/** 023 * Programmatic means of constructing 024 * {@link org.springframework.beans.factory.config.BeanDefinition BeanDefinitions} 025 * using the builder pattern. Intended primarily for use when implementing Spring 2.0 026 * {@link org.springframework.beans.factory.xml.NamespaceHandler NamespaceHandlers}. 027 * 028 * @author Rod Johnson 029 * @author Rob Harrop 030 * @author Juergen Hoeller 031 * @since 2.0 032 */ 033public class BeanDefinitionBuilder { 034 035 /** 036 * Create a new {@code BeanDefinitionBuilder} used to construct a {@link GenericBeanDefinition}. 037 */ 038 public static BeanDefinitionBuilder genericBeanDefinition() { 039 BeanDefinitionBuilder builder = new BeanDefinitionBuilder(); 040 builder.beanDefinition = new GenericBeanDefinition(); 041 return builder; 042 } 043 044 /** 045 * Create a new {@code BeanDefinitionBuilder} used to construct a {@link GenericBeanDefinition}. 046 * @param beanClass the {@code Class} of the bean that the definition is being created for 047 */ 048 public static BeanDefinitionBuilder genericBeanDefinition(Class<?> beanClass) { 049 BeanDefinitionBuilder builder = new BeanDefinitionBuilder(); 050 builder.beanDefinition = new GenericBeanDefinition(); 051 builder.beanDefinition.setBeanClass(beanClass); 052 return builder; 053 } 054 055 /** 056 * Create a new {@code BeanDefinitionBuilder} used to construct a {@link GenericBeanDefinition}. 057 * @param beanClassName the class name for the bean that the definition is being created for 058 */ 059 public static BeanDefinitionBuilder genericBeanDefinition(String beanClassName) { 060 BeanDefinitionBuilder builder = new BeanDefinitionBuilder(); 061 builder.beanDefinition = new GenericBeanDefinition(); 062 builder.beanDefinition.setBeanClassName(beanClassName); 063 return builder; 064 } 065 066 /** 067 * Create a new {@code BeanDefinitionBuilder} used to construct a {@link RootBeanDefinition}. 068 * @param beanClass the {@code Class} of the bean that the definition is being created for 069 */ 070 public static BeanDefinitionBuilder rootBeanDefinition(Class<?> beanClass) { 071 return rootBeanDefinition(beanClass, null); 072 } 073 074 /** 075 * Create a new {@code BeanDefinitionBuilder} used to construct a {@link RootBeanDefinition}. 076 * @param beanClass the {@code Class} of the bean that the definition is being created for 077 * @param factoryMethodName the name of the method to use to construct the bean instance 078 */ 079 public static BeanDefinitionBuilder rootBeanDefinition(Class<?> beanClass, String factoryMethodName) { 080 BeanDefinitionBuilder builder = new BeanDefinitionBuilder(); 081 builder.beanDefinition = new RootBeanDefinition(); 082 builder.beanDefinition.setBeanClass(beanClass); 083 builder.beanDefinition.setFactoryMethodName(factoryMethodName); 084 return builder; 085 } 086 087 /** 088 * Create a new {@code BeanDefinitionBuilder} used to construct a {@link RootBeanDefinition}. 089 * @param beanClassName the class name for the bean that the definition is being created for 090 */ 091 public static BeanDefinitionBuilder rootBeanDefinition(String beanClassName) { 092 return rootBeanDefinition(beanClassName, null); 093 } 094 095 /** 096 * Create a new {@code BeanDefinitionBuilder} used to construct a {@link RootBeanDefinition}. 097 * @param beanClassName the class name for the bean that the definition is being created for 098 * @param factoryMethodName the name of the method to use to construct the bean instance 099 */ 100 public static BeanDefinitionBuilder rootBeanDefinition(String beanClassName, String factoryMethodName) { 101 BeanDefinitionBuilder builder = new BeanDefinitionBuilder(); 102 builder.beanDefinition = new RootBeanDefinition(); 103 builder.beanDefinition.setBeanClassName(beanClassName); 104 builder.beanDefinition.setFactoryMethodName(factoryMethodName); 105 return builder; 106 } 107 108 /** 109 * Create a new {@code BeanDefinitionBuilder} used to construct a {@link ChildBeanDefinition}. 110 * @param parentName the name of the parent bean 111 */ 112 public static BeanDefinitionBuilder childBeanDefinition(String parentName) { 113 BeanDefinitionBuilder builder = new BeanDefinitionBuilder(); 114 builder.beanDefinition = new ChildBeanDefinition(parentName); 115 return builder; 116 } 117 118 119 /** 120 * The {@code BeanDefinition} instance we are creating. 121 */ 122 private AbstractBeanDefinition beanDefinition; 123 124 /** 125 * Our current position with respect to constructor args. 126 */ 127 private int constructorArgIndex; 128 129 130 /** 131 * Enforce the use of factory methods. 132 */ 133 private BeanDefinitionBuilder() { 134 } 135 136 /** 137 * Return the current BeanDefinition object in its raw (unvalidated) form. 138 * @see #getBeanDefinition() 139 */ 140 public AbstractBeanDefinition getRawBeanDefinition() { 141 return this.beanDefinition; 142 } 143 144 /** 145 * Validate and return the created BeanDefinition object. 146 */ 147 public AbstractBeanDefinition getBeanDefinition() { 148 this.beanDefinition.validate(); 149 return this.beanDefinition; 150 } 151 152 153 /** 154 * Set the name of the parent definition of this bean definition. 155 */ 156 public BeanDefinitionBuilder setParentName(String parentName) { 157 this.beanDefinition.setParentName(parentName); 158 return this; 159 } 160 161 /** 162 * Set the name of a static factory method to use for this definition, 163 * to be called on this bean's class. 164 */ 165 public BeanDefinitionBuilder setFactoryMethod(String factoryMethod) { 166 this.beanDefinition.setFactoryMethodName(factoryMethod); 167 return this; 168 } 169 170 /** 171 * Set the name of a non-static factory method to use for this definition, 172 * including the bean name of the factory instance to call the method on. 173 * @since 4.3.6 174 */ 175 public BeanDefinitionBuilder setFactoryMethodOnBean(String factoryMethod, String factoryBean) { 176 this.beanDefinition.setFactoryMethodName(factoryMethod); 177 this.beanDefinition.setFactoryBeanName(factoryBean); 178 return this; 179 } 180 181 /** 182 * Add an indexed constructor arg value. The current index is tracked internally 183 * and all additions are at the present point. 184 * @deprecated since Spring 2.5, in favor of {@link #addConstructorArgValue}. 185 * This variant just remains around for Spring Security 2.x compatibility. 186 */ 187 @Deprecated 188 public BeanDefinitionBuilder addConstructorArg(Object value) { 189 return addConstructorArgValue(value); 190 } 191 192 /** 193 * Add an indexed constructor arg value. The current index is tracked internally 194 * and all additions are at the present point. 195 */ 196 public BeanDefinitionBuilder addConstructorArgValue(Object value) { 197 this.beanDefinition.getConstructorArgumentValues().addIndexedArgumentValue( 198 this.constructorArgIndex++, value); 199 return this; 200 } 201 202 /** 203 * Add a reference to a named bean as a constructor arg. 204 * @see #addConstructorArgValue(Object) 205 */ 206 public BeanDefinitionBuilder addConstructorArgReference(String beanName) { 207 this.beanDefinition.getConstructorArgumentValues().addIndexedArgumentValue( 208 this.constructorArgIndex++, new RuntimeBeanReference(beanName)); 209 return this; 210 } 211 212 /** 213 * Add the supplied property value under the given name. 214 */ 215 public BeanDefinitionBuilder addPropertyValue(String name, Object value) { 216 this.beanDefinition.getPropertyValues().add(name, value); 217 return this; 218 } 219 220 /** 221 * Add a reference to the specified bean name under the property specified. 222 * @param name the name of the property to add the reference to 223 * @param beanName the name of the bean being referenced 224 */ 225 public BeanDefinitionBuilder addPropertyReference(String name, String beanName) { 226 this.beanDefinition.getPropertyValues().add(name, new RuntimeBeanReference(beanName)); 227 return this; 228 } 229 230 /** 231 * Set the init method for this definition. 232 */ 233 public BeanDefinitionBuilder setInitMethodName(String methodName) { 234 this.beanDefinition.setInitMethodName(methodName); 235 return this; 236 } 237 238 /** 239 * Set the destroy method for this definition. 240 */ 241 public BeanDefinitionBuilder setDestroyMethodName(String methodName) { 242 this.beanDefinition.setDestroyMethodName(methodName); 243 return this; 244 } 245 246 247 /** 248 * Set the scope of this definition. 249 * @see org.springframework.beans.factory.config.BeanDefinition#SCOPE_SINGLETON 250 * @see org.springframework.beans.factory.config.BeanDefinition#SCOPE_PROTOTYPE 251 */ 252 public BeanDefinitionBuilder setScope(String scope) { 253 this.beanDefinition.setScope(scope); 254 return this; 255 } 256 257 /** 258 * Set whether or not this definition is abstract. 259 */ 260 public BeanDefinitionBuilder setAbstract(boolean flag) { 261 this.beanDefinition.setAbstract(flag); 262 return this; 263 } 264 265 /** 266 * Set whether beans for this definition should be lazily initialized or not. 267 */ 268 public BeanDefinitionBuilder setLazyInit(boolean lazy) { 269 this.beanDefinition.setLazyInit(lazy); 270 return this; 271 } 272 273 /** 274 * Set the autowire mode for this definition. 275 */ 276 public BeanDefinitionBuilder setAutowireMode(int autowireMode) { 277 beanDefinition.setAutowireMode(autowireMode); 278 return this; 279 } 280 281 /** 282 * Set the depency check mode for this definition. 283 */ 284 public BeanDefinitionBuilder setDependencyCheck(int dependencyCheck) { 285 beanDefinition.setDependencyCheck(dependencyCheck); 286 return this; 287 } 288 289 /** 290 * Append the specified bean name to the list of beans that this definition 291 * depends on. 292 */ 293 public BeanDefinitionBuilder addDependsOn(String beanName) { 294 if (this.beanDefinition.getDependsOn() == null) { 295 this.beanDefinition.setDependsOn(beanName); 296 } 297 else { 298 String[] added = ObjectUtils.addObjectToArray(this.beanDefinition.getDependsOn(), beanName); 299 this.beanDefinition.setDependsOn(added); 300 } 301 return this; 302 } 303 304 /** 305 * Set the role of this definition. 306 */ 307 public BeanDefinitionBuilder setRole(int role) { 308 this.beanDefinition.setRole(role); 309 return this; 310 } 311 312}