10、Spring源码分析:Spring实例化Bean的五种方式源码解析

一,概述

对于我们Java来说,创建对象无非就是new或者通过反射两种方式。

Spring中实例化对象一般是通过反射来实现的,但是Spring的强大之处不仅仅在于它为Java开发者提供了极大便利,更在于它的开放式架构,使得用户可以拥有最大扩展Spring的能力。

我们大致可以总结出以下五种实例化bean的方式:

1、 实现InstantiationAwareBeanPostProcessor接口;
2、 实现FactoryBean接口;
3、 通过Supplier接口;
4、 工厂方法factory-method;
5、 通过反射;

二,实现InstantiationAwareBeanPostProcessor接口

MyInstantiationAwareBeanPostProcessor.java

public class MyInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
   
     
    @Override
    public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
   
     
        if (beanName.equals("a")) {
   
     
            return new B();
        }
        return null;
    }
}

applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
    <bean id="a" class="com.bobo.A"></bean>
    <bean class="com.bobo.MyInstantiationAwareBeanPostProcessor"></bean>
</beans>

测试代码:

public class Test {
   
     
    public static void main(String[] args) {
   
     
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("boboTest.xml");
        System.out.println(context.getBean("a"));
    }
}

运行输出:

com.bobo.B@490ab905

三,实现FactoryBean接口

MyFactoryBean.java

@Component
public class MyFactoryBean implements FactoryBean<A> {
   
     
    @Override
    public A getObject() throws Exception {
   
     
        return new A();
    }

    @Override
    public Class<?> getObjectType() {
   
     
        return A.class;
    }
}

测试代码

public class Test {
   
     
    public static void main(String[] args) {
   
     
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("boboTest.xml");
        System.out.println(context.getBean("myFactoryBean"));
    }
}

运行输出:

com.bobo.A@61230f6a

原理:请移步到这里查看:

Spring中FactoryBean真相揭秘

四,通过Supplier接口

CreateSupplierB.java

public class CreateSupplierB {
   
     
    public static B createB(){
   
     
        return new B();
    }
}

MyBeanFactoryPostProcessor.java

@Component
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
   
     
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
   
     
        BeanDefinition beanDefinition = beanFactory.getBeanDefinition("a");
        GenericBeanDefinition genericBeanDefinition = (GenericBeanDefinition) beanDefinition;
        genericBeanDefinition.setInstanceSupplier(CreateSupplierB::createB);
    }
}

测试代码:

public class Test {
   
     
    public static void main(String[] args) {
   
     
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("boboTest.xml");
        System.out.println(context.getBean("a"));
    }
}

运行输出:

com.bobo.B@cd3fee8

原理:请移步这里

Spring实例化(createBeanInstance)源码解析

五,工厂方法factory-method

1,静态工厂

MyStaticFactory.java

public class MyStaticFactory {
   
     
    public static A getA() {
   
     
        return new A();
    }
}

applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
    <bean id="a" class="com.bobo.MyStaticFactory" factory-method="getA"></bean>
</beans>

测试:

public class Test {
   
     
    public static void main(String[] args) {
   
     
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("boboTest.xml");
        System.out.println(context.getBean("a"));
    }
}

运行输出:

com.bobo.A@5702b3b1

2,实例工厂

MyInstanceFactory.java

public class MyInstanceFactory {
   
     
    public A getA() {
   
     
        return new A();
    }
}

aoolicationContext.xml

<?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 http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
    <bean id="myInstanceFactory" class="com.bobo.MyInstanceFactory"></bean>
    <bean id="a" class="com.bobo.MyStaticFactory" factory-bean="myInstanceFactory" factory-method="getA"></bean>
</beans>

测试代码:

public class Test {
   
     
    public static void main(String[] args) {
   
     
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("boboTest.xml");
        System.out.println(context.getBean("a"));
    }
}

运行输出:

com.bobo.A@5702b3b1

3,原理

请移步这里:

Spring实例化(createBeanInstance)源码解析

六,通过反射

<?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 http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
    <bean id="a" class="com.bobo.A"></bean>
</beans>

测试代码:

public class Test {
   
     
    public static void main(String[] args) {
   
     
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("boboTest.xml");
        System.out.println(context.getBean("a"));
    }
}

运行输出:

com.bobo.A@5bcab519