zoukankan      html  css  js  c++  java
  • Spring的BeanFactory和FactoryBean

    官方定义

    • BeanFactory:Spring Bean容器的根接口
    • FactoryBean:各个对象的工厂接口,如果bean实现了这个接口,它将被用作对象的工厂,而不是直接作为bean实例。

    源码解析

    BeanFactory

    public interface BeanFactory {
        //标注是获取FactoryBean的实现类,而不是调用getObject()获取的实例
    	String FACTORY_BEAN_PREFIX = "&";
    	Object getBean(String name) throws BeansException;
    	<T> T getBean(String name, 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;
    	boolean containsBean(String name);
    	boolean isSingleton(String name) throws NoSuchBeanDefinitionException;
    	boolean isPrototype(String name) throws NoSuchBeanDefinitionException;
    	boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException;
    	boolean isTypeMatch(String name, Class<?> typeToMatch) throws NoSuchBeanDefinitionException;
    	Class<?> getType(String name) throws NoSuchBeanDefinitionException;
    	String[] getAliases(String name);
    }
    

    从源码的方法定义上,就可以看出,BeanFactory作为bean的容器管理器,提供了一系列获取bean以及获取bean属性的方法。

    写一个小例子试验下:

    SimpleBean:

    public class SimpleBean {
        public void send() {
            System.out.println("Hello Spring Bean!");
        }
    }
    

    Spring配置文件config.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
    						http://www.springframework.org/schema/context/spring-context.xsd">
        <bean id="simpleBean" class="base.SimpleBeanFactoryBean"/>
    </beans>
    

    测试方法:

        public static void main(String[] args) throws Exception {
            ApplicationContext context = new ClassPathXmlApplicationContext("config.xml");
            BeanFactory beanFactory = context.getAutowireCapableBeanFactory();
            System.out.println("通过名称获取bean");
            SimpleBean simpleBean = (SimpleBean) beanFactory.getBean("simpleBean");
            simpleBean.send();
            System.out.println("通过名称和类型获取bean");
            simpleBean = beanFactory.getBean("simpleBean", SimpleBean.class);
            simpleBean.send();
            System.out.println("通过类型获取bean");
            simpleBean = beanFactory.getBean(SimpleBean.class);
            simpleBean.send();
            boolean containsBean = beanFactory.containsBean("simpleBean");
            System.out.println("是否包含 simpleBean ? " + containsBean);
            boolean singleton = beanFactory.isSingleton("simpleBean");
            System.out.println("是否是单例? " + singleton);
            boolean match = beanFactory.isTypeMatch("simpleBean", ResolvableType.forClass(SimpleBean.class));
            System.out.println("是否是SimpleBean类型 ? " + match);
            match = beanFactory.isTypeMatch("simpleBean", SimpleBean.class);
            System.out.println("是否是SimpleBean类型 ? " + match);
            Class<?> aClass = beanFactory.getType("simpleBean");
            System.out.println("simpleBean 的类型是 " + aClass.getName());
            String[] aliases = beanFactory.getAliases("simpleBean");
            System.out.println("simpleBean 的别名 : " + Arrays.toString(aliases));
        }
    

    控制台结果:

    通过名称获取bean
    Hello Spring Bean!
    通过名称和类型获取bean
    Hello Spring Bean!
    通过类型获取bean
    Hello Spring Bean!
    是否包含 simpleBean ? true
    是否是单例? true
    是否是SimpleBean类型 ? true
    是否是SimpleBean类型 ? true
    simpleBean 的类型是 base.SimpleBean
    simpleBean 的别名 : []
    

    FactoryBean

    public interface FactoryBean<T> {
        
        /**
         * 获取一个bean,如果配置了工厂bean,在getBean的时候,将会调用此方法,获取一个bean
         */
        T getObject() throws Exception;
    
        /**
         * 获取bean的类型
         */
        Class<?> getObjectType();
    
        /**
         * 是否是单例
         */
        boolean isSingleton();
    
    }
    

    接口是泛型,定义了三个方法,其中getObject()是工厂模式的体现,将会通过此方法返回一个bean的实例。

    一个小例子:

    public class SimpleBeanFactoryBean implements FactoryBean<SimpleBean> {
        @Override
        public SimpleBean getObject() throws Exception {
            System.out.println("MyFactoryBean getObject");
            return new SimpleBean();
        }
    
        @Override
        public Class<?> getObjectType() {
            System.out.println("MyFactoryBean getObjectType");
            return SimpleBean.class;
        }
    
        @Override
        public boolean isSingleton() {
            return false;
        }
    }
    

    以上可以修改为单例模式,可以做成线程安全的单例,可塑性较高。

    配置文件config.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
    						http://www.springframework.org/schema/context/spring-context.xsd">
        <bean id="simple" class="base.SimpleBeanFactoryBean"/>
    </beans>
    

    注意,我们在这里只配置了SimpleBeanFactoryBean,并没有配置SimpleBean,接下来看下getBean方法的输出。

    ApplicationContext context = new ClassPathXmlApplicationContext("config.xml");
    SimpleBean simpleBean = context.getBean(SimpleBean.class);
    simpleBean.send();
    

    控制台输出:

    MyFactoryBean getObjectType
    MyFactoryBean getObject
    Hello Spring Bean!
    

    由此我们可以看出FactoryBean的执行流程

    1. 通过getObjectType获取bean的类型
    2. 调用getObject方法获取bean的实例

    总结

    BeanFactoryFactoryBean其实没有关系,只是名称比较像而已。

    • BeanFactory是IOC最基本的容器,负责生产和管理bean,它为其他具体的IOC容器提供了最基本的规范。
    • FactoryBean是一个接口,当在IOC容器中的Bean实现了FactoryBean后,通过getBean(String BeanName)获取到的Bean对象并不是FactoryBean的实现类对象,而是这个实现类中的getObject()方法返回的对象。要想获取FactoryBean的实现类,就要getBean(&BeanName),在BeanName之前加上&。
  • 相关阅读:
    PHP 开发 APP 接口 学习笔记与总结
    Java实现 LeetCode 43 字符串相乘
    Java实现 LeetCode 43 字符串相乘
    Java实现 LeetCode 43 字符串相乘
    Java实现 LeetCode 42 接雨水
    Java实现 LeetCode 42 接雨水
    Java实现 LeetCode 42 接雨水
    Java实现 LeetCode 41 缺失的第一个正数
    Java实现 LeetCode 41 缺失的第一个正数
    Java实现 LeetCode 41 缺失的第一个正数
  • 原文地址:https://www.cnblogs.com/gcdd/p/12292360.html
Copyright © 2011-2022 走看看