Can Spring's BeanFactory and FactoryBean be confused?

ApplicationContext interface, which is derived from BeanFactory interface.

ApplicationContext contains all the functions of BeanFactory. It is generally recommended to take precedence over BeanFactory.

Difference between BeanFactory and FactoryBean
BeanFactory is an interface, which provides the most basic form of OC container and provides specifications for the implementation of specific IOC container. FactoryBean is also an interface, which provides a more flexible way for the implementation of beans in IOC container, FactoryBean adds a simple factory pattern and decoration pattern to the implementation of Bean on the basis of IOC container (if you want to understand decoration pattern reference: decorator pattern (Decoration), we can flexibly configure it in getObject() method. In fact, there are many FactoryBean implementation classes in the Spring source code

Difference: BeanFactory is a Factory, that is, IOC container or object Factory, and FactoryBean is a Bean. In Spring, all beans are managed by BeanFactory (that is, IOC container).

However, for FactoryBean, this Bean is not a simple Bean, but a factory Bean that can produce or modify objects. Its implementation is similar to the factory pattern and modifier pattern in design pattern.

1,BeanFactory
BeanFactory, ending with Factory, indicates that it is a Factory class (Interface), which is responsible for producing and managing a Factory of beans. In Spring, BeanFactory is the core interface of IOC container. Its responsibilities include instantiating, locating, configuring objects in the application and establishing dependencies between these objects.

BeanFactory is only an interface, not a specific implementation of IOC container. However, Spring container provides many implementations, such as DefaultListableBeanFactory, XmlBeanFactory, ApplicationContext, etc., among which XmlBeanFactory is a common one. This implementation will describe the objects constituting the application and the dependencies between objects in XML. The XmlBeanFactory class will hold this XML configuration metadata and use it to build a fully configurable system or application.

Are the implementation of some additional function. It provides the most basic specifications for other specific IOC containers, such as DefaultListableBeanFactory,XmlBeanFactory,ApplicationContext, etc. specific containers implement BeanFactory and add other functions on it.

BeanFactory and ApplicationContext are two IOC containers of the spring framework. Now ApplicationContext is generally used, which not only includes the role of BeanFactory, but also makes more extensions.

BeanFactory is a relatively primitive Factory in spring. For example, XMLBeanFactory is a typical BeanFactory.

The original BeanFactory cannot support many spring plug-ins, such as AOP function, Web application, etc. ApplicationContext interface, which is derived from BeanFactory interface.

ApplicationContext contains all the functions of BeanFactory. It is generally recommended to take precedence over BeanFactory

ApplicationContext works in a more framework oriented way, layering and implementing inheritance of context. The ApplicationContext package also provides the following functions:

MessageSource, which provides international message access

Resource access, such as URL s and files

Event propagation

Load multiple (inherited) contexts so that each context focuses on a specific level, such as the web layer of the application;

Before using the spring framework, if we want to use dao layer objects in our service layer, we have to create a new object in the service layer.

Existing problems: the dependence between layers. To use dao layer objects in the service layer, they need to be configured in the xml configuration file. How to create objects and how to combine relationships are all left to the spring framework.

Mode 1

Resource resource = new FileSystemResource("beans.xml");
BeanFactory factory = new XmlBeanFactory(resource);
Mode 2

ClassPathResource resource = new ClassPathResource("beans.xml");
BeanFactory factory = new XmlBeanFactory(resource);
Mode 3

ApplicationContext context = new ClassPathXmlApplicationContext(new String[] {"applicationContext.xml", "applicationContext-part2.xml"});
BeanFactory factory = (BeanFactory) context;
That's basically all. Then you can get the bean instance by using the getBean(String beanName) method; The methods provided by BeanFactory are extremely simple, and only six methods are provided for customers to call:

boolean containsBean(String beanName) determines whether the factory contains the bean definition with the given name. If so, it returns true

Object getBean(String) returns the bean instance registered with the given name. According to the bean configuration, if it is singleton mode, it will return a shared instance, otherwise it will return a new instance. If the specified bean is not found, the method may throw an exception.

Object getBean(String, Class) returns the bean instance registered with the given name and converts it to the given class type.

Class getType(String name) returns the class of the bean with the given name. If the specified bean instance is not found, the NoSuchBeanDefinitionException exception is excluded

Boolean is singleton (string) determines whether the bean definition with a given name is in singleton mode

String[] getAliases(String name) returns all aliases for a given bean name

package org.springframework.beans.factory;
import org.springframework.beans.BeansException;
public interface BeanFactory {

String FACTORY_BEAN_PREFIX = "&";
Object getBean(String name) throws BeansException;
<T> T getBean(String name, Class<T> requiredType) throws BeansException;
<T> T getBean(Class<T> requiredType) throws BeansException;
Object getBean(String name, Object... args) throws BeansException;
boolean containsBean(String name);
boolean isSingleton(String name) throws NoSuchBeanDefinitionException;
boolean isPrototype(String name) throws NoSuchBeanDefinitionException;
boolean isTypeMatch(String name, Class<?> targetType) throws NoSuchBeanDefinitionException;
Class<?> getType(String name) throws NoSuchBeanDefinitionException;
String[] getAliases(String name);

}

2,FactoryBean
In general, Spring uses the class attribute of the reflection mechanism to specify and implement class instantiation beans. In some cases, the process of instantiating beans is complex. If you follow the traditional way, you need to provide a lot of configuration information in. The flexibility of configuration mode is limited. At this time, a simple scheme may be obtained by coding.

Spring provides an org. Org for this purpose springframework. bean. factory. The factory class interface of factorybean. Users can customize the logic of instantiating the bean by implementing this interface. Why do beans default to singletons? I recommend it. WeChat official account: Java technology stack, back in the background: spring, can get my N Spring tutorial, all dry cargo.

FactoryBean interface occupies an important position for spring framework. Spring itself provides the implementation of more than 70 factorybeans. They hide the details of instantiating some complex beans and bring convenience to the upper application.

From spring 3 Starting from 0, FactoryBean began to support generics, that is, the interface declaration was changed to the form of FactoryBean and ended with a Bean, indicating that it is a Bean. Unlike ordinary beans, it is a Bean that implements the FactoryBean interface. According to the ID of the Bean, the object obtained from the BeanFactory is actually the object returned by the getObject() of the FactoryBean, not the FactoryBean itself, If you want to get the FactoryBean object, add an & symbol before the ID to get it.

For example, implement a FactoryBean by yourself, which is used to proxy an object, intercept all methods of the object, and output a line of LOG before and after the call, imitating the function of ProxyFactoryBean.

/**

  • my factory bean<p>
  • Proxy a class, intercept all the methods of the class, and output the log before and after the method call
  • @author daniel.zhao
    *
    */

public class MyFactoryBean implements FactoryBean<Object>, InitializingBean, DisposableBean {

private static final Logger logger = LoggerFactory.getLogger(MyFactoryBean.class);
private String interfaceName;
private Object target;
private Object proxyObj;
@Override
public void destroy() throws Exception {
    logger.debug("destroy......");
}
@Override
public void afterPropertiesSet() throws Exception {
    proxyObj = Proxy.newProxyInstance(
            this.getClass().getClassLoader(),
            new Class[] { Class.forName(interfaceName) },
            new InvocationHandler() {
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            logger.debug("invoke method......" + method.getName());
            logger.debug("invoke method before......" + System.currentTimeMillis());
            Object result = method.invoke(target, args);
            logger.debug("invoke method after......" + System.currentTimeMillis());
            return result; }
    });
    logger.debug("afterPropertiesSet......");
}

@Override
public Object getObject() throws Exception {
    logger.debug("getObject......");
    return proxyObj;
}

@Override
public Class<?> getObjectType() {
    return proxyObj == null ? Object.class : proxyObj.getClass();
}

@Override
public boolean isSingleton() {
    return true;
}

public String getInterfaceName() {
    return interfaceName;
}

public void setInterfaceName(String interfaceName) {
    this.interfaceName = interfaceName;
}

public Object getTarget() {
    return target;
}

public void setTarget(Object target) {
    this.target = target;
}

public Object getProxyObj() {
    return proxyObj;
}

public void setProxyObj(Object proxyObj) {
    this.proxyObj = proxyObj;
}

}
The XML bean configuration is as follows

<bean id="fbHelloWorldService" class="com.ebao.xxx.MyFactoryBean">
<property name="interfaceName" value="com.ebao.xxx.HelloWorldService" />
<property name="target" ref="helloWorldService" />
</bean>
Junit Test class

@RunWith(JUnit4ClassRunner.class)
@ContextConfiguration(classes = { MyFactoryBeanConfig.class })
public class MyFactoryBeanTest {

@Autowired
private ApplicationContext context;
/**
 * Test and verify the principle of FactoryBean. Before and after a servcie proxy calls its method, the print log can also be used for other processing
 * Get the custom FactoryBean from ApplicationContext
 * context.getBean(String beanName) ---> The Object finally obtained is factorybean getObejct(),
 * Use proxy Newinstance generates the proxy class of the service
 */
@Test
public void testFactoryBean() {
    HelloWorldService helloWorldService = (HelloWorldService) context.getBean("fbHelloWorldService");
    helloWorldService.getBeanName();
    helloWorldService.sayHello();
}

}
FactoryBean is an interface. After the FactoryBean is implemented by the Bean in the IOC container, the Bean object obtained through getBean(String BeanName) is not the implementation class object of FactoryBean, but the object returned by the getObject() method in this implementation class. To get the implementation class of FactoryBean, you need to getBean (& BeanName) and add &.

package org.springframework.beans.factory;
public interface FactoryBean<T> {

T getObject() throws Exception;
Class<?> getObjectType();
boolean isSingleton();

}
The interface also defines the following three methods:

TgetObject(): 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;

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

ClassgetObjectType(): returns the Bean type created by FactoryBean.

When the implementation class configured by the class attribute in the configuration file is FactoryBean, the object returned by the FactoryBean#getObject() method is not the FactoryBean itself, which is equivalent to that FactoryBean#getObject() represents the getBean() method. Example: if the following Car is configured in the traditional way, each attribute of the Car corresponds to an element label.

package com.baobaotao.factorybean;

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 is more flexible. In the following example, the configuration values are specified for all attributes of Car at one time by means of comma separator:

package com.baobaotao.factorybean;
import org.springframework.beans.factory.FactoryBean;
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 ;
}

// Accept comma separator to set property information
public   void  setCarInfo ( String carInfo )   {
    this . carInfo = carInfo;
}

}
With this CarFactoryBean, you can configure the CarBean in the configuration file using the following custom configuration method:

<bean d="car"class="com.baobaotao.factorybean.CarFactoryBean"
P:carInfo = "Ferrari, 4002000000" / >
When calling getBean("car"), Spring finds that CarFactoryBean implements the interface of FactoryBean through the reflection mechanism. At this time, the Spring container calls the interface method CarFactoryBean#getObject() to return.

If you want to obtain the instance of CarFactoryBean, you need to prefix the displayed before beanName with "&" when using getBean(beanName) method: such as getBean("& car");

The following is an example of applying FactoryBean

<beans xmlns="http://www.springframework.org/schema/beans"

         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns:context="http://www.springframework.org/schema/context"
         xmlns:aop="http://www.springframework.org/schema/aop"
         xmlns:tx="http://www.springframework.org/schema/tx"
         xsi:schemaLocation="http://www.springframework.org/schema/beans
                 http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
                 http://www.springframework.org/schema/context
                 http://www.springframework.org/schema/context/spring-context-3.0.xsd
                 http://www.springframework.org/schema/aop
                 http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
                 http://www.springframework.org/schema/tx
                 http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">

<bean id="student" class="com.spring.bean.Student">
<property name="name" value="zhangsan" />
</bean>

<bean id="school" class="com.spring.bean.School">
</bean>

<bean id="factoryBeanPojo" class="com.spring.bean.FactoryBeanPojo">

<property name="type" value="student" />

</bean>
</beans>
Implementation class of FactoryBean

import org.springframework.beans.factory.FactoryBean;

/**

  • @author Wang Biao
  • @parameter
  • @return
    */

public class FactoryBeanPojo implements FactoryBean{

private String type;

@Override
public Object getObject() throws Exception {
    if("student".equals(type)){
        return new Student();
    }else{
        return new School();
    }

}

@Override
public Class getObjectType() {
    return School.class;
}

@Override
public boolean isSingleton() {
    return true;
}

public String getType() {
    return type;
}

public void setType(String type) {
    this.type = type;
}

}
Ordinary bean

/**

  • @author Wang Biao
  • @parameter
  • @return
    */

public class School {

private String schoolName;
private String address;
private int studentNumber;
public String getSchoolName() {
    return schoolName;
}
public void setSchoolName(String schoolName) {
    this.schoolName = schoolName;
}
public String getAddress() {
    return address;
}
public void setAddress(String address) {
    this.address = address;
}
public int getStudentNumber() {
    return studentNumber;
}
public void setStudentNumber(int studentNumber) {
    this.studentNumber = studentNumber;
}
@Override
public String toString() {
    return "School [schoolName=" + schoolName + ", address=" + address
            + ", studentNumber=" + studentNumber + "]";
}

}
Test class

import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.spring.bean.FactoryBeanPojo;

/**

  • @author Wang Biao
  • @parameter
  • @return
    */

public class FactoryBeanTest {

public static void main(String[] args){
    String url = "com/spring/config/BeanConfig.xml";
    ClassPathXmlApplicationContext cpxa = new ClassPathXmlApplicationContext(url);
    Object school= cpxa.getBean("factoryBeanPojo");
    FactoryBeanPojo factoryBeanPojo= (FactoryBeanPojo) cpxa.getBean("&factoryBeanPojo");
    System.out.println(school.getClass().getName());
    System.out.println(factoryBeanPojo.getClass().getName());
}

}
Output results:

November 16, 2016 10:28:24 am org springframework. context. support. AbstractApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@1e8ee5c0: startup date [Wed Nov 16 10:28:24 CST 2016]; root of context hierarchy
November 16, 2016 10:28:24 am org springframework. beans. factory. xml. XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from class path resource [com/spring/config/BeanConfig.xml]
November 16, 2016 10:28:24 am org springframework. beans. factory. support. DefaultListableBeanFactory preInstantiateSingletons
INFO: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@35b793ee: defining beans [student,school,factoryBeanPojo]; root of factory hierarchy
com.spring.bean.Student
com.spring.bean.FactoryBeanPojo
From the results, we can see that when the FactoryBeanPojo object is obtained from the IOC container, we use getBean(String BeanName) to obtain the student object. We can see that when the type attribute in FactoryBeanPojo is set to student, the student object will be returned in the getObject() method.

Therefore, when obtaining the implementation class that implements FactoryBean from the IOC container, what is returned is the object returned by the getObject method in the implementation class. To obtain the implementation class of FactoryBean, add &, which is written as getBean (string & BeanName), before the BeanName in getBean(String BeanName).

last
If you think this article is a little helpful to you, give it a compliment. Or you can join my development exchange group: 1025263163 learn from each other, and we will have professional technical Q & A to solve doubts

If you think this article is useful to you, please click star: https://gitee.com/ZhongBangKe... esteem it a favor!

JAVA learning manual: https://doc.crmeb.com
Technical exchange forum: https://q.crmeb.com

Keywords: Javascript

Added by feddie1984 on Wed, 05 Jan 2022 07:19:13 +0200