BeanFactory和FactoryBean

1.BeanFactory

对于BeanFactory,它本质上是一个Factory,是一个容器,它是spring中最基本的容器,它的作用是配置,新建,管理各种bean以及它们之间的依赖关系。

看下源码

  1 public interface BeanFactory {
  2 
  3     /**
  4      * Used to dereference a {@link FactoryBean} instance and distinguish it from
  5      * beans <i>created</i> by the FactoryBean. For example, if the bean named
  6      * {@code myJndiObject} is a FactoryBean, getting {@code &myJndiObject}
  7      * will return the factory, not the instance returned by the factory.
  8      */
  9     String FACTORY_BEAN_PREFIX = "&";
 10 
 11 
 12     /** 
 13      * Return an instance, which may be shared or independent, of the specified bean.
 14      * <p>This method allows a Spring BeanFactory to be used as a replacement for the
 15      * Singleton or Prototype design pattern. Callers may retain references to
 16      * returned objects in the case of Singleton beans.
 17      * <p>Translates aliases back to the corresponding canonical bean name.
 18      * Will ask the parent factory if the bean cannot be found in this factory instance.
 19      * @param name the name of the bean to retrieve
 20      * @return an instance of the bean
 21      * @throws NoSuchBeanDefinitionException if there is no bean definition
 22      * with the specified name
 23      * @throws BeansException if the bean could not be obtained
 24      */ 根据指定的beanName获取对应的bean对象
 25     Object getBean(String name) throws BeansException;
 26 
 27     /**
 28      * Return an instance, which may be shared or independent, of the specified bean.
 29      * <p>Behaves the same as {@link #getBean(String)}, but provides a measure of type
 30      * safety by throwing a BeanNotOfRequiredTypeException if the bean is not of the
 31      * required type. This means that ClassCastException can't be thrown on casting
 32      * the result correctly, as can happen with {@link #getBean(String)}.
 33      * <p>Translates aliases back to the corresponding canonical bean name.
 34      * Will ask the parent factory if the bean cannot be found in this factory instance.
 35      * @param name the name of the bean to retrieve
 36      * @param requiredType type the bean must match. Can be an interface or superclass
 37      * of the actual class, or {@code null} for any match. For example, if the value
 38      * is {@code Object.class}, this method will succeed whatever the class of the
 39      * returned instance.
 40      * @return an instance of the bean
 41      * @throws NoSuchBeanDefinitionException if there is no such bean definition
 42      * @throws BeanNotOfRequiredTypeException if the bean is not of the required type
 43      * @throws BeansException if the bean could not be created
 44      */根据名字和指定的类型获取bean对象
 45     <T> T getBean(String name, Class<T> requiredType) throws BeansException;
 46 
 47     /**
 48      * Return an instance, which may be shared or independent, of the specified bean.
 49      * <p>Allows for specifying explicit constructor arguments / factory method arguments,
 50      * overriding the specified default arguments (if any) in the bean definition.
 51      * @param name the name of the bean to retrieve
 52      * @param args arguments to use when creating a bean instance using explicit arguments
 53      * (only applied when creating a new instance as opposed to retrieving an existing one)
 54      * @return an instance of the bean
 55      * @throws NoSuchBeanDefinitionException if there is no such bean definition
 56      * @throws BeanDefinitionStoreException if arguments have been given but
 57      * the affected bean isn't a prototype
 58      * @throws BeansException if the bean could not be created
 59      * @since 2.5
 60      */根据名字和创建对象时可能用到的参数来获取bean对象
 61     Object getBean(String name, Object... args) throws BeansException;
 62 
 63     /**
 64      * Return the bean instance that uniquely matches the given object type, if any.
 65      * <p>This method goes into {@link ListableBeanFactory} by-type lookup territory
 66      * but may also be translated into a conventional by-name lookup based on the name
 67      * of the given type. For more extensive retrieval operations across sets of beans,
 68      * use {@link ListableBeanFactory} and/or {@link BeanFactoryUtils}.
 69      * @param requiredType type the bean must match; can be an interface or superclass.
 70      * {@code null} is disallowed.
 71      * @return an instance of the single bean matching the required type
 72      * @throws NoSuchBeanDefinitionException if no bean of the given type was found
 73      * @throws NoUniqueBeanDefinitionException if more than one bean of the given type was found
 74      * @throws BeansException if the bean could not be created
 75      * @since 3.0
 76      * @see ListableBeanFactory
 77      */
 78     <T> T getBean(Class<T> requiredType) throws BeansException;
 79 
 80     /**
 81      * Return an instance, which may be shared or independent, of the specified bean.
 82      * <p>Allows for specifying explicit constructor arguments / factory method arguments,
 83      * overriding the specified default arguments (if any) in the bean definition.
 84      * <p>This method goes into {@link ListableBeanFactory} by-type lookup territory
 85      * but may also be translated into a conventional by-name lookup based on the name
 86      * of the given type. For more extensive retrieval operations across sets of beans,
 87      * use {@link ListableBeanFactory} and/or {@link BeanFactoryUtils}.
 88      * @param requiredType type the bean must match; can be an interface or superclass.
 89      * {@code null} is disallowed.
 90      * @param args arguments to use when creating a bean instance using explicit arguments
 91      * (only applied when creating a new instance as opposed to retrieving an existing one)
 92      * @return an instance of the bean
 93      * @throws NoSuchBeanDefinitionException if there is no such bean definition
 94      * @throws BeanDefinitionStoreException if arguments have been given but
 95      * the affected bean isn't a prototype
 96      * @throws BeansException if the bean could not be created
 97      * @since 4.1
 98      */
 99     <T> T getBean(Class<T> requiredType, Object... args) throws BeansException;
100 
101 
102     /**
103      * Does this bean factory contain a bean definition or externally registered singleton
104      * instance with the given name?
105      * <p>If the given name is an alias, it will be translated back to the corresponding
106      * canonical bean name.
107      * <p>If this factory is hierarchical, will ask any parent factory if the bean cannot
108      * be found in this factory instance.
109      * <p>If a bean definition or singleton instance matching the given name is found,
110      * this method will return {@code true} whether the named bean definition is concrete
111      * or abstract, lazy or eager, in scope or not. Therefore, note that a {@code true}
112      * return value from this method does not necessarily indicate that {@link #getBean}
113      * will be able to obtain an instance for the same name.
114      * @param name the name of the bean to query
115      * @return whether a bean with the given name is present
116      */
117     boolean containsBean(String name);
118 
119     /**
120      * Is this bean a shared singleton? That is, will {@link #getBean} always
121      * return the same instance?
122      * <p>Note: This method returning {@code false} does not clearly indicate
123      * independent instances. It indicates non-singleton instances, which may correspond
124      * to a scoped bean as well. Use the {@link #isPrototype} operation to explicitly
125      * check for independent instances.
126      * <p>Translates aliases back to the corresponding canonical bean name.
127      * Will ask the parent factory if the bean cannot be found in this factory instance.
128      * @param name the name of the bean to query
129      * @return whether this bean corresponds to a singleton instance
130      * @throws NoSuchBeanDefinitionException if there is no bean with the given name
131      * @see #getBean
132      * @see #isPrototype
133      */
134     boolean isSingleton(String name) throws NoSuchBeanDefinitionException;
135 
136     /**
137      * Is this bean a prototype? That is, will {@link #getBean} always return
138      * independent instances?
139      * <p>Note: This method returning {@code false} does not clearly indicate
140      * a singleton object. It indicates non-independent instances, which may correspond
141      * to a scoped bean as well. Use the {@link #isSingleton} operation to explicitly
142      * check for a shared singleton instance.
143      * <p>Translates aliases back to the corresponding canonical bean name.
144      * Will ask the parent factory if the bean cannot be found in this factory instance.
145      * @param name the name of the bean to query
146      * @return whether this bean will always deliver independent instances
147      * @throws NoSuchBeanDefinitionException if there is no bean with the given name
148      * @since 2.0.3
149      * @see #getBean
150      * @see #isSingleton
151      */
152     boolean isPrototype(String name) throws NoSuchBeanDefinitionException;
153 
154     /**
155      * Check whether the bean with the given name matches the specified type.
156      * More specifically, check whether a {@link #getBean} call for the given name
157      * would return an object that is assignable to the specified target type.
158      * <p>Translates aliases back to the corresponding canonical bean name.
159      * Will ask the parent factory if the bean cannot be found in this factory instance.
160      * @param name the name of the bean to query
161      * @param typeToMatch the type to match against (as a {@code ResolvableType})
162      * @return {@code true} if the bean type matches,
163      * {@code false} if it doesn't match or cannot be determined yet
164      * @throws NoSuchBeanDefinitionException if there is no bean with the given name
165      * @since 4.2
166      * @see #getBean
167      * @see #getType
168      */
169     boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException;
170 
171     /**
172      * Check whether the bean with the given name matches the specified type.
173      * More specifically, check whether a {@link #getBean} call for the given name
174      * would return an object that is assignable to the specified target type.
175      * <p>Translates aliases back to the corresponding canonical bean name.
176      * Will ask the parent factory if the bean cannot be found in this factory instance.
177      * @param name the name of the bean to query
178      * @param typeToMatch the type to match against (as a {@code Class})
179      * @return {@code true} if the bean type matches,
180      * {@code false} if it doesn't match or cannot be determined yet
181      * @throws NoSuchBeanDefinitionException if there is no bean with the given name
182      * @since 2.0.1
183      * @see #getBean
184      * @see #getType
185      */
186     boolean isTypeMatch(String name, Class<?> typeToMatch) throws NoSuchBeanDefinitionException;
187 
188     /**
189      * Determine the type of the bean with the given name. More specifically,
190      * determine the type of object that {@link #getBean} would return for the given name.
191      * <p>For a {@link FactoryBean}, return the type of object that the FactoryBean creates,
192      * as exposed by {@link FactoryBean#getObjectType()}.
193      * <p>Translates aliases back to the corresponding canonical bean name.
194      * Will ask the parent factory if the bean cannot be found in this factory instance.
195      * @param name the name of the bean to query
196      * @return the type of the bean, or {@code null} if not determinable
197      * @throws NoSuchBeanDefinitionException if there is no bean with the given name
198      * @since 1.1.2
199      * @see #getBean
200      * @see #isTypeMatch
201      */
202     Class<?> getType(String name) throws NoSuchBeanDefinitionException;
203 
204     /**
205      * Return the aliases for the given bean name, if any.
206      * All of those aliases point to the same bean when used in a {@link #getBean} call.
207      * <p>If the given name is an alias, the corresponding original bean name
208      * and other aliases (if any) will be returned, with the original bean name
209      * being the first element in the array.
210      * <p>Will ask the parent factory if the bean cannot be found in this factory instance.
211      * @param name the bean name to check for aliases
212      * @return the aliases, or an empty array if none
213      * @see #getBean
214      */
215     String[] getAliases(String name);
216 
217 }

2.FactoryBean

factoryBean,它本质上是一个bean,工厂bean,可以用来生成其它bean对象。如果需要获取该工厂bean对象它自己,则需要在该beanName前面加上 & 符号。

2.1 用法

新建一个工厂bean,该bean实现了FactoryBean接口

package com.demo.spring.entity;

import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Component;

/**
 * @author chenyk
 * @date 2018年6月22日
 */

@Component("carFactoryBean")
public class CarFactoryBean implements FactoryBean<Car>,InitializingBean{

    private Car car;

    public void afterPropertiesSet() throws Exception {
        this.car = new Car();
    }
    //此处就是返回的对象
    public Car getObject() throws Exception {
        return this.car;
    }

    public Class<?> getObjectType() {
        return Car.class;
    }

    public boolean isSingleton() {
        return true;
    }

}

创建一个car类

public class Car {
    public void run(){
        System.out.println("run fast...");
    }
}

运行发现:

public void testApplicationContext(){
        //在启动容器时,解析注册beanDefinition,实例化bean,然后完成依赖注入,最后初始化bean
        @SuppressWarnings("resource")
        ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-context.xml");
        System.out.println(applicationContext.getBean("carFactoryBean").getClass()); //获取的是Car
        System.out.println( applicationContext.getBean("&carFactoryBean").getClass()); //获取的是CarFactoryBean
    }

输出:

class com.demo.spring.entity.Car
2018-06-25 09:08:41,469 DEBUG [AbstractBeanFactory.java:251] : Returning cached instance of singleton bean 'carFactoryBean'
class com.demo.spring.entity.CarFactoryBean

2.2 源码分析

public interface FactoryBean<T> {

    /**
     * Return an instance (possibly shared or independent) of the object
     * managed by this factory.
     * <p>As with a {@link BeanFactory}, this allows support for both the
     * Singleton and Prototype design pattern.
     * <p>If this FactoryBean is not fully initialized yet at the time of
     * the call (for example because it is involved in a circular reference),
     * throw a corresponding {@link FactoryBeanNotInitializedException}.
     * <p>As of Spring 2.0, FactoryBeans are allowed to return {@code null}
     * objects. The factory will consider this as normal value to be used; it
     * will not throw a FactoryBeanNotInitializedException in this case anymore.
     * FactoryBean implementations are encouraged to throw
     * FactoryBeanNotInitializedException themselves now, as appropriate.
     * @return an instance of the bean (can be {@code null})
     * @throws Exception in case of creation errors
     * @see FactoryBeanNotInitializedException
     */ 
     //获取bean对象 
T getObject()
throws Exception; /** * Return the type of object that this FactoryBean creates, * or {@code null} if not known in advance. * <p>This allows one to check for specific types of beans without * instantiating objects, for example on autowiring. * <p>In the case of implementations that are creating a singleton object, * this method should try to avoid singleton creation as far as possible; * it should rather estimate the type in advance. * For prototypes, returning a meaningful type here is advisable too. * <p>This method can be called <i>before</i> this FactoryBean has * been fully initialized. It must not rely on state created during * initialization; of course, it can still use such state if available. * <p><b>NOTE:</b> Autowiring will simply ignore FactoryBeans that return * {@code null} here. Therefore it is highly recommended to implement * this method properly, using the current state of the FactoryBean. * @return the type of object that this FactoryBean creates, * or {@code null} if not known at the time of the call * @see ListableBeanFactory#getBeansOfType */ //获取bean类型
   Class
<?> getObjectType(); /** * Is the object managed by this factory a singleton? That is, * will {@link #getObject()} always return the same object * (a reference that can be cached)? * <p><b>NOTE:</b> If a FactoryBean indicates to hold a singleton object, * the object returned from {@code getObject()} might get cached * by the owning BeanFactory. Hence, do not return {@code true} * unless the FactoryBean always exposes the same reference. * <p>The singleton status of the FactoryBean itself will generally * be provided by the owning BeanFactory; usually, it has to be * defined as singleton there. * <p><b>NOTE:</b> This method returning {@code false} does not * necessarily indicate that returned objects are independent instances. * An implementation of the extended {@link SmartFactoryBean} interface * may explicitly indicate independent instances through its * {@link SmartFactoryBean#isPrototype()} method. Plain {@link FactoryBean} * implementations which do not implement this extended interface are * simply assumed to always return independent instances if the * {@code isSingleton()} implementation returns {@code false}. * @return whether the exposed object is a singleton * @see #getObject() * @see SmartFactoryBean#isPrototype() */
//是否是单例模式
boolean isSingleton(); }
原文地址:https://www.cnblogs.com/51life/p/9214079.html