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.io.Serializable; 020 021import javax.inject.Provider; 022 023import org.springframework.beans.BeansException; 024import org.springframework.beans.factory.BeanFactory; 025import org.springframework.lang.Nullable; 026import org.springframework.util.Assert; 027 028/** 029 * A {@link org.springframework.beans.factory.FactoryBean} implementation that 030 * returns a value which is a JSR-330 {@link javax.inject.Provider} that in turn 031 * returns a bean sourced from a {@link org.springframework.beans.factory.BeanFactory}. 032 * 033 * <p>This is basically a JSR-330 compliant variant of Spring's good old 034 * {@link ObjectFactoryCreatingFactoryBean}. It can be used for traditional 035 * external dependency injection configuration that targets a property or 036 * constructor argument of type {@code javax.inject.Provider}, as an 037 * alternative to JSR-330's {@code @Inject} annotation-driven approach. 038 * 039 * @author Juergen Hoeller 040 * @since 3.0.2 041 * @see javax.inject.Provider 042 * @see ObjectFactoryCreatingFactoryBean 043 */ 044public class ProviderCreatingFactoryBean extends AbstractFactoryBean<Provider<Object>> { 045 046 @Nullable 047 private String targetBeanName; 048 049 050 /** 051 * Set the name of the target bean. 052 * <p>The target does not <i>have</i> to be a non-singleton bean, but realistically 053 * always will be (because if the target bean were a singleton, then said singleton 054 * bean could simply be injected straight into the dependent object, thus obviating 055 * the need for the extra level of indirection afforded by this factory approach). 056 */ 057 public void setTargetBeanName(String targetBeanName) { 058 this.targetBeanName = targetBeanName; 059 } 060 061 @Override 062 public void afterPropertiesSet() throws Exception { 063 Assert.hasText(this.targetBeanName, "Property 'targetBeanName' is required"); 064 super.afterPropertiesSet(); 065 } 066 067 068 @Override 069 public Class<?> getObjectType() { 070 return Provider.class; 071 } 072 073 @Override 074 protected Provider<Object> createInstance() { 075 BeanFactory beanFactory = getBeanFactory(); 076 Assert.state(beanFactory != null, "No BeanFactory available"); 077 Assert.state(this.targetBeanName != null, "No target bean name specified"); 078 return new TargetBeanProvider(beanFactory, this.targetBeanName); 079 } 080 081 082 /** 083 * Independent inner class - for serialization purposes. 084 */ 085 @SuppressWarnings("serial") 086 private static class TargetBeanProvider implements Provider<Object>, Serializable { 087 088 private final BeanFactory beanFactory; 089 090 private final String targetBeanName; 091 092 public TargetBeanProvider(BeanFactory beanFactory, String targetBeanName) { 093 this.beanFactory = beanFactory; 094 this.targetBeanName = targetBeanName; 095 } 096 097 @Override 098 public Object get() throws BeansException { 099 return this.beanFactory.getBean(this.targetBeanName); 100 } 101 } 102 103}