Spring BeanFactory和FactoryBean

Spring BeanFactory和FactoryBean

1、BeanFactory

BeanFactory defines the most basic form of the IOC container, and provides the most basic interface that the IOC container should comply with, that is, the lowest level and the most basic programming specification that Spring IOC complies with. In the Spring code, BeanFactory is just an interface, not a specific implementation of the IOC container, but the Spring container provides many implementations, such as DefaultListableBeanFactory , XmlBeanFactory , ApplicationContext, etc., all of which are implementations with additional functions.

public interface BeanFactory {

	String FACTORY_BEAN_PREFIX = "&";

	/**
	 * Return an instance, which may be shared or independent, of the specified bean.
	 */
	Object getBean(String name) throws BeansException;

	/**
	 * Return an instance, which may be shared or independent, of the specified bean.
	 */
	<T> T getBean(String name, Class<T> requiredType) throws BeansException;

	/**
	 * Return the bean instance that uniquely matches the given object type, if any.
	 * @param requiredType type the bean must match; can be an interface or superclass.
	 * {@code null} is disallowed.
	 */
	<T> T getBean(Class<T> requiredType) throws BeansException;

	/**
	 * Return an instance, which may be shared or independent, of the specified bean.
	
	 */
	Object getBean(String name, Object... args) throws BeansException;

	/**
	 * Does this bean factory contain a bean definition or externally registered singleton
	 * instance with the given name?
	 */
	boolean containsBean(String name);

	/**
	 * Is this bean a shared singleton? That is, will {@link #getBean} always
	 * return the same instance?
	 */
	boolean isSingleton(String name) throws NoSuchBeanDefinitionException;

	/**
	 * Is this bean a prototype? That is, will {@link #getBean} always return
	 * independent instances?
	 */
	boolean isPrototype(String name) throws NoSuchBeanDefinitionException;

	/**
	 * Check whether the bean with the given name matches the specified type.
	 * More specifically, check whether a {@link #getBean} call for the given name
	 * would return an object that is assignable to the specified target type.
	 */
	boolean isTypeMatch(String name, Class<?> targetType) throws NoSuchBeanDefinitionException;

	/**
	 */
	Class<?> getType(String name) throws NoSuchBeanDefinitionException;

	/**
	 * Return the aliases for the given bean name, if any.
	 * All of those aliases point to the same bean when used in a {@link #getBean} call.
	 */
	String[] getAliases(String name);

}

 

2、FactoryBean

In general, Spring uses the class attribute of <bean> to specify the implementation class to instantiate the bean through the reflection mechanism. In some cases, the process of instantiating a bean is complicated, and in the traditional way, a lot of configuration information needs to be provided in the <bean>. The flexibility of the configuration method is limited, and a simple solution may be obtained by using the encoding method. Spring provides a factory class interface of org.springframework.bean.factory.FactoryBean for this purpose, and users can customize the logic of instantiating beans by implementing this interface.

The FactoryBean interface occupies an important position for the Spring framework, and Spring itself provides more than 70 FactoryBean implementations. They hide the details of instantiating some complex beans and bring convenience to upper-layer applications. Since Spring 3.0, FactoryBean has begun to support generics, that is, the interface declaration is changed to the form of FactoryBean<T>:

public interface FactoryBean<T> {

	/**
	 * Return an instance (possibly shared or independent) of the object
	 * managed by this factory.
	 */
	T getObject() throws Exception;

	/**
	 * Return the type of object that this FactoryBean creates,
	 * or <code>null</code> if not known in advance.
	 */
	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)?
	 */
	boolean isSingleton();

}

The following three methods are also defined in this interface:

T getObject(): Returns the Bean instance created by FactoryBean. If isSingleton() returns true , the instance will be placed in the single-instance cache pool in the Spring container;

boolean isSingleton(): Returns whether the scope of the Bean instance created by FactoryBean is singleton or prototype ;

Class<T> getObjectType(): Returns the bean type created by FactoryBean.

When the implementation class configured by the class attribute of <bean> in the configuration file is FactoryBean, what is returned by the getBean() method is not the FactoryBean itself, but the object returned by the FactoryBean#getObject() method, which is equivalent to the FactoryBean#getObject() proxy the getBean() method.

Example: If you use the traditional way to configure the <bean> of Car below, each property of Car corresponds to a <property> element tag.

public class Car {
    private int maxSpeed;
    private String brand;
    private double price;

    public int getMaxSpeed() {
        return this.maxSpeed;
    }

    public void setMaxSpeed(int maxSpeed) {
        this.maxSpeed = maxSpeed;
    }

    public String getBrand() {
        return this.brand;
    }

    public void setBrand(String brand) {
        this.brand = brand;
    }

    public double getPrice() {
        return this.price;
    }

    public void setPrice(double price) {
        this.price = price;
    }
}   

If it is implemented in the way of FactoryBean, it will be more flexible. The following example specifies configuration values ​​for all properties of Car at one time through comma separators:

public class CarFactoryBean implements FactoryBean<Car> {
    private String carInfo;

    public Car getObject() throws Exception {
        Car car = new Car();
        String[] infos = carInfo.split(",");
        car.setBrand(infos[0]);
        car.setMaxSpeed(Integer.valueOf(infos[1]));
        car.setPrice(Double.valueOf(infos[2]));
        return car;
    }

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

    public boolean isSingleton() {
        return false;
    }

    public String getCarInfo() {
        return this.carInfo;
    }

    // 接受逗号分割符设置属性信息  
    public void setCarInfo(String carInfo) {
        this.carInfo = carInfo;
    }
}   

With this CarFactoryBean, you can configure the Car Bean using the following custom configuration in the configuration file:

<bean id="car" class="com.baobaotao.factorybean.CarFactoryBean" p:carInfo="法拉利,400,2000000"/>

When calling getBean("car"), Spring finds that CarFactoryBean implements the interface of FactoryBean through the reflection mechanism, and then the Spring container calls the interface method CarFactoryBean#getObject() method to return. If you want to get an instance of CarFactoryBean, you need to add a "&" prefix before the beanName when using the getBean(beanName) method: such as getBean("&car");

 

3. Difference

BeanFactory is a Factory, which is an IOC container or object factory, and FactoryBean is a Bean. In Spring, all beans are managed by the BeanFactory (that is, the IOC container). But for FactoryBean, this bean is not a simple bean, but a factory bean that can produce or decorate objects. Its implementation is similar to the factory pattern and decorator pattern in the design pattern.

=====END=====

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324518768&siteId=291194637