This question is often asked in the interview. In fact, many people only memorize the answer by rote. Baidu's answer to this question is as follows:
BeanFactory, which ends with Factory, indicates that it is a Factory class (Interface) used to manage a Factory of a bean. It is the core interface of the IOC container, which is used to manage and assemble the IOC container of ordinary beans
FactoryBean, which ends with bean, indicates that it is a bean. On the basis of IOC container, a simple factory mode and decoration mode are added to the implementation of bean. It is a factory bean that can produce objects and decoration objects. After being managed by spring, the produced objects are determined by getObject() method.
Then Baidu spent a long time and came to a vague conclusion that both were used to generate bean s. Finally, the interview was ambiguous.
In fact, the concept is not wrong, but we don't understand its meaning. Now let's understand these two things from the code level.
In the era of traditional xml configuration files, our bean objects are configured in the form of xml configuration files. Here we define several classes. The project structure is as follows:
Here, we define two classes under dao package. The codes are as follows:
public class DaoFacrotyBean implements FactoryBean { private String name; private String sex; private Integer age; public void setName(String name) { this.name = name; } public void setSex(String sex) { this.sex = sex; } public void setAge(Integer age) { this.age = age; } @Override public Object getObject() throws Exception { UserFactoryBean userFactoryBean = new UserFactoryBean(); userFactoryBean.setName(name); userFactoryBean.setSex(sex); userFactoryBean.setAge(age); return userFactoryBean; } @Override public Class<?> getObjectType() { return null; } @Override public boolean isSingleton() { return false; } }
public class UserFactoryBean { private String name; private String sex; private Integer age; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } }
It can be seen that our DaoFactoryBean implements the FactoryBean interface and rewrites the three methods of the interface, focusing on the getObject method. It can be seen that we return the UserFactoryBean object and set the corresponding properties. The property values here are configured through xml. The configuration file is as follows:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="daoFactoryBean" class="com.rongdu.dao.DaoFacrotyBean"> <property name="name" value="Zhang San"></property> <property name="sex" value="male"></property> <property name="age" value="18"></property> </bean> </beans>
The AppConfig class code is as follows:
@Configuration @ComponentScan(value = "com.rongdu") @ImportResource("classpath:spring.xml") public class AppConfig { }
Let's write a test class:
public class Test { public static void main(String[] args) { AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class); DaoFacrotyBean daoFactoryBean = (DaoFacrotyBean) applicationContext.getBean("daoFactoryBean"); System.out.println(daoFactoryBean); } }
Here, we use the AnnotationConfigApplicationContext class to obtain the daoFactoryBean object defined in the xml configuration file. At this time, we have set the relevant properties. The final output results are as follows:
Through the above error report, we can know that the output here is the UserFactoryBean object. It can be imagined that the getBean method here is actually the getObject method in the called daofactorybean, which returns the UserFactoryBean object. At the same time, we have configured the corresponding properties through xml. This is a very important point.
The correct wording is:
public class Test { public static void main(String[] args) { AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class); UserFactoryBean userFactoryBean = (UserFactoryBean) applicationContext.getBean("daoFactoryBean"); System.out.println(userFactoryBean); System.out.println(userFactoryBean.getName()); System.out.println(userFactoryBean.getSex()); System.out.println(userFactoryBean.getAge()); } }
The results are as follows:
If we want to introduce a third-party dependency, and we want to hand it over to spring for management, we need to configure the corresponding beans in xml, which seems to be no problem, but think about it carefully. If there are too many third-party class dependencies, in other words, like the UserFactoryBean above, if there are too many attributes of the class, or too many other classes, configurations and other attributes introduced into the class, Then we cannot configure in xml, nor can we configure in xml ourselves. These tasks must be completed by a third party. We only need to obtain the configured objects of the third party by implementing the FactoryBean interface. for instance:
@Configuration @ComponentScan(value = "com.rongdu") @ImportResource("classpath:spring.xml") public class AppConfig { @Bean @Autowired public SqlSessionFactoryBean sqlSessionFactoryBean(DataSource dataSource){ SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean(); sqlSessionFactoryBean.setDataSource(dataSource); return sqlSessionFactoryBean; } @Bean public DataSource dataSource(){ //If you don't know how to write, just return empty return null; } }
Here, we configure an sqlSessionFactotyBean object by configuring the class. The sqlSessionFactotyBean here is actually a sqlsessionfactory object. We can see that it implements the FactoryBean interface by entering this class:
At the same time, we can see that sqlSessionFactotyBean has many properties to be configured, but we don't have to worry. It has been configured for us. We just need to give it a data source.
So FactoryBean is actually more powerful than BeanFactory, which may not be right. Back to the front, we said that FactoryBean is a bean. It should be understood now. We can define a bean object by inheriting the FactoryBean interface and using the getObject method. At the same time, we can define some properties of the bean in the xml configuration file or configuration class. Finally, we can obtain the configured bean object through ApplicationContext.
Now let's talk about BeanFactory. Why is it a factory class (Interface)? This is actually very easy to understand. There are many subclasses under it to obtain bean objects, such as ClassPathXmlApplicationContext, AnnotationConfigApplicationContext, etc. subclasses return different types of bean objects by implementing its getBean method, which is the embodiment of the factory pattern.
To sum up:
BeanFactory, why is it a factory class (Interface)? This is actually easy to understand. There are many subclasses under it to obtain bean objects, such as ClassPathXmlApplicationContext, AnnotationConfigApplicationContext, etc. subclasses return different types of bean objects by implementing its getBean method, which is the embodiment of the factory pattern.
To sum up:
BeanFactory is a factory interface in spring, which can produce and obtain objects. BeanFactory is a special bean interface in spring. It has three methods. Other classes return a bean object by implementing BeanFactory and overriding the getObject method. If it is necessary to return the current class object itself, it needs to be in ApplicationContext Add a & symbol to the getBean method, such as ApplicationContext getBean("&daoFactoryBean").