preface

It is essential to understand FactoryBean, because one of the most typical applications of FactoryBean in Spring is to create AOP proxy objects. It is also very helpful to understand the core source code of Mybatis. If willing to crud, do a happy farmer, then I can o o o o o o o o o o o o o o o…

BeanFactory and FactoryBean are both spring interfaces, and their names look similar, but I think it’s hard to confuse them! Although the author of Spring Secrets likes to write this line.

Don’t confuse BeanFactory with FactoryBean.

1, the BeanFactory

BeanFactory, which ends with Factory, indicates that it is a Factory (interface) that is responsible for producing and managing beans. In Spring, BeanFactory is the top-level interface of the factory and the core interface of the IOC container. Therefore, BeanFactory defines general methods for managing beans, such as getBean and containsBean. Its responsibilities include: Instantiate, locate, configure objects in your application, and establish dependencies between these objects. The BeanFactory is just an interface, not the implementation of the IOC container, so the Spring container is given a lot of kinds of implementation, such as DefaultListableBeanFactory, XmlBeanFactory, ApplicationContext, etc., A common one is XmlBeanFactory, which describes in XML the objects that make up the application and the dependencies between them.

1.1 the BeanFactory source

public interface BeanFactory {
	// Escape the FactoryBean definition, because if a FactoryBean is retrieved using the bean name, the result is a factory-generated object,
	// If you want to get the factory itself, you need to escape
	String FACTORY_BEAN_PREFIX = "&";

	// Based on the bean name, get the bean instance in the IOC container
	Object getBean(String name) throws BeansException;

	// Get the bean instance according to the bean name and Class type, add type safety verification mechanism.
	<T> T getBean(String name, @Nullable Class<T> requiredType) throws BeansException;

	Object getBean(String name, Object. args) throws BeansException; <T> T getBean(Class<T> requiredType) throws BeansException; <T> T getBean(Class<T> requiredType,Object. args) throws BeansException;// Provide a retrieval of the bean to see if there is a bean with this name in the IOC container
	boolean containsBean(String name);

	// Get the bean instance based on the bean name and determine whether the bean is a singleton
	boolean isSingleton(String name) throws NoSuchBeanDefinitionException;

	boolean isPrototype(String name) throws NoSuchBeanDefinitionException;

	boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException;

	boolean isTypeMatch(Stringname, @Nullable Class<? > typeToMatch) throws NoSuchBeanDefinitionException;// Get the Class type of the bean instance@Nullable Class<? > getType(String name) throws NoSuchBeanDefinitionException;

	// Get the alias of the bean, and its original name will also be retrieved if retrieved by the alias
	String[] getAliases(String name);
}
Copy the code

1.2. Usage Scenario of BeanFactory

Get Bean(byName or byType) from Ioc container

3. Determine whether the Bean is a singleton

2, FactoryBean

First of all, a FactoryBean is a Bean, but not just a Bean. This may sound like an oxymoron, but why is it so? In Spring, all beans are managed by the BeanFactory (i.e. IOC container). However, for a FactoryBean, this FactoryBean is not a simple Bean, but a FactoryBean that can produce or modify the generation of objects. Its implementation is similar to the factory and decorator patterns in the design pattern

2.1. Why are FactoryBeans?

In general, Spring specifies the implementation class instantiation Bean through the class attribute that the reflection mechanism utilizes. As for why factoryBeans exist? There are two reasons:

1. In some cases, the process of instantiating beans is complex and requires a lot of configuration information in. The flexibility of configuration is limited, and coding may yield a simple solution. Spring provides a org. Springframework. Beans. Factory. FactoryBean factory class interface, users can customize by implementing the interface logic instantiation of the bean. The FactoryBean interface plays an important role in the Spring framework. Spring itself provides over 70 FactoryBean implementations. They hide the details of instantiating complex beans for the benefit of upper-layer applications.

2, due to the third party libraries cannot register directly to the spring container, and can realize org. Springframework. Beans. Factory. FactoryBean interface, then present his object instantiation code.

2.2 FactoryBean source code

public interface FactoryBean<T> {
	// Get the bean from the factory.
	@Nullable
	T getObject() throws Exception;
	
	This method returns the type matched by the getBean in the IOC container.@Nullable Class<? > getObjectType();// Whether the object created by the Bean factory is a singleton
	default boolean isSingleton() {
		return true; }}Copy the code

The getobject () method returns an instance of the object “produced” by this FactoryBean. We need to implement this method to give our own object instantiation logic. 2. GetobjectTYype () only returns the type of the object returned by getobject (), or null if it cannot be determined in advance; GetobjectTYype () = getobjectTYype () = getobjectTYype () = getobjectTYype () = getobjectTYype () = getobjectTYype () = getobjectTYype () = getobjectTYype () = getobjectTYype () Well, let me give you an example

public class XXX implements FactoryBean {
    @Override
    public Object getObject() throws Exception {
        return newYYY; } @Override public Class<? >getObjectType() {  // Note that the main effect of this method is that it returns the type matched by getBean in the IOC container
        returnAAA.class; }} To find a bean of class XXX in ioc (which is actually YYY), use the public notation for getBeanclass Demo1 {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext annotationConfigApplicationContext = 
                new AnnotationConfigApplicationContext(Appconfig.class);
                
        annotationConfigApplicationContext.getBean( AAA.class ); // [AAA. Class]}}Copy the code

3. The isSingleton () method returns a result that indicates whether the object “produced” by the factory method (Getobject ()) will exist in the container as a Singleton. Return true if it exists as a singleton, false otherwise;

A FactoryBean represents the responsibilities of a factory. That is, if A Bean A implements the FactoryBean interface, then A becomes A factory. The name of A is actually the object returned by the factory call to getObject(), not A itself. If you want to get an instance of factory A itself, you need to prefix the name with an am&. In a more general way

GetObject (‘ &name ‘) returns an instance in the factory. GetObject (‘ & Name ‘) returns an instance of the factory itself

In general, beans don’t have to implement the factory pattern themselves; the Spring container acts as the factory; But in rare cases, the beans in the container are factories themselves, producing other bean instances. Other bean instances produced by the factory bean are no longer produced by the Spring container, so class elements are no longer required, unlike normal bean configurations.

2.3. FactoryBean Code examples

1. Create an Appconfig class and scan all subpackages under com.yichun

@Configuration
@ComponentScan("com.yichun")
public class Appconfig {}Copy the code

2. Create a StudentBean class and implement FactoryBean and override its two methods

@Component("studentBean")
public class StudentBean implements FactoryBean {
    @Override
    public Object getObject() throws Exception {
        return newTeacherBean(); } @Override public Class<? >getObjectType() {  // Note that the main effect of this method is that it returns the type matched by getBean in the IOC container
        return StudentBean.class;
    }
    // A student learning method
    public void study(){
        System.out.println("Students learn..."); }}Copy the code

3. Create a TeacherBean class

public class TeacherBean {
    public void teacher(){
        System.out.println("Teachers teach..."); }}Copy the code

4. Test the StudentBean type

public class Demo1 {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(Appconfig.class);
        StudentBean studentBean = (StudentBean)annotationConfigApplicationContext.getBean("studentBean"); studentBean.study(); }}Copy the code

Add”&“Symbol

public class Demo1 {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(Appconfig.class);
        // Add the ampersand symbol
        StudentBean studentBean = (StudentBean)annotationConfigApplicationContext.getBean("&studentBean"); studentBean.study(); }}Copy the code

The successful running

5. Test the teacherBean type

public class Demo1 {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(Appconfig.class);    
        TeacherBean teacherBean = (TeacherBean) annotationConfigApplicationContext.getBean("studentBean"); teacherBean.teacher(); }}Copy the code

The successful running

2.4 FactoryBean Usage Scenarios

Use Scenario 1: One of the most typical uses of FactoryBeans in Spring is to create proxy objects for AOP. We know that AOP actually means that Spring creates a proxy object at run time, that is, the object is created at run time rather than defined from the start, which fits nicely with the factory method pattern. More graphically, AN AOP proxy object creates a proxy object at run time through Java’s reflection mechanism, with methods woven into the target methods of the proxy object based on business requirements. This object in Spring is ProxyFactoryBean.

So, FactoryBeans give us a more flexible way to instantiate beans, and we can create more complex Bean instances from FactoryBeans.

Of course, in Spring, factoryBeans are used in many places inside the Spring container. Here are some of the more common FactoryBean implementations:

JndiobjectFactoryBean

LocalSessionFactoryBean SqlMapClientFactoryBean ProxyFactoryBean TransactionProxyFactoryBean

Use Scenario 2: SqlSessionFactoryBean in Mybatis

<bean id="tradeSqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="trade" />
        <property name="mapperLocations" value="classpath*:mapper/trade/*Mapper.xml" />
        <property name="configLocation" value="classpath:mybatis-config.xml" />
        <property name="typeAliasesPackage" value="com.bytebeats.mybatis3.domain.trade" />
    </bean>
Copy the code

package org.mybatis.spring;

public class SqlSessionFactoryBean implements FactoryBean<SqlSessionFactory>, InitializingBean.ApplicationListener<ApplicationEvent> {
private staticfinal Log LOGGER = LogFactory.getLog(SqlSessionFactoryBean.class); . }Copy the code

FactoryBean is also used by Consumer in Dubbo, Alibaba’s open-source distributed services framework,

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
    xsi:schemaLocation="Http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd "> <! -- Current application configuration --><dubbo:application name="demo-consumer" /><! Expose service protocol configuration --><dubbo:protocol name="dubbo" port="20813" /><! Expose service configuration --><dubbo:reference id="demoService" interface="com.alibaba.dubbo.config.spring.api.DemoService"  />
     
</beans>
Copy the code

< dubbo: reference corresponding beans are com. Alibaba. The dubbo. Config. Spring. ReferenceBean class.

Use Scenario 3: SessionFactoryBean in Hibernate. I won’t outline it here.

Finally, this article will inevitably have errors, welcome to criticize! Welcome to comment! Welcome to comment!!

Reference: “the Spring revelation” Wang Fuqiang zhuanlan.zhihu.com/p/87382038 www.cnblogs.com/aspirant/p/…