美文网首页
Spring中 BeanFactory与FactoryBean的

Spring中 BeanFactory与FactoryBean的

作者: 敲程序的人生 | 来源:发表于2018-10-24 09:30 被阅读29次

    1. BeanFactory

    BeanFactory,以Factory结尾,表示它是一个工厂类(接口),用于管理Bean的一个工厂。在Spring中,BeanFactory是IOC容器的核心接口,它的职责包括:实例化、定位、配置应用程序中的对象及建立这些对象间的依赖。
      Spring为我们提供了许多易用的BeanFactory实现,XmlBeanFactory就是常用的一个,该实现将以XML方式描述组成应用的对象及对象间的依赖关系。XmlBeanFactory类将持有此XML配置元数据,并用它来构建一个完全可配置的系统或应用。
    实例化容器

    Resource resource = new FileSystemResource("beans.xml");
    BeanFactory factory = new XmlBeanFactory(resource);
    
    ClassPathResource resource = new ClassPathResource("beans.xml");
    BeanFactory factory = new XmlBeanFactory(resource);
    
    ApplicationContext context = new ClassPathXmlApplicationContext(new String[] {"applicationContext.xml", "applicationContext-part2.xml"});
    BeanFactory factory = (BeanFactory) context;
    

    基本就是这些了,接着使用getBean(String beanName)方法就可以取得bean的实例;BeanFactory提供的方法及其简单,仅提供了六种方法供客户调用:
      1 boolean containsBean(String beanName) 判断工厂中是否包含给定名称的bean定义,若有则返回true。
    2 Object getBean(String) 返回给定名称注册的bean实例。根据bean的配置情况,如果是singleton模式将返回一个共享实例,否则将返回一个新建的实例,如果没有找到指定bean,该方法可能会抛出异常。
     3 Object getBean(String, Class) 返回以给定名称注册的bean实例,并转换为给定class类型。
     4 Class getType(String name) 返回给定名称的bean的Class,如果没有找到指定的bean实例,则排除NoSuchBeanDefinitionException异常。
     5 boolean isSingleton(String) 判断给定名称的bean定义是否为单例模式。
     6 String[] getAliases(String name) 返回给定bean名称的所有别名。

    2. FactoryBean

    一般情况下,Spring通过反射机制利用<bean>的class属性指定实现类实例化Bean,在某些情况下,实例化Bean过程比较复杂,如果按照传统的方式,则需要在<bean>中提供大量的配置信息。配置方式的灵活性是受限的,这时采用编码的方式可能会得到一个简单的方案。Spring为此提供了一个org.springframework.bean.factory.FactoryBean的工厂类接口,用户可以通过实现该接口定制实例化Bean的逻辑。FactoryBean接口对于Spring框架来说占用重要的地位,Spring自身就提供了70多个FactoryBean的实现。它们隐藏了实例化一些复杂Bean的细节,给上层应用带来了便利。从Spring3.0开始,FactoryBean开始支持泛型,即接口声明改为FactoryBean<T>的形式。
      例如自己实现一个FactoryBean,功能:用来代理一个对象,对该对象的所有方法做一个拦截,在调用前后都输出一行LOG,模仿ProxyFactoryBean的功能。

    /**
     * my factory bean<p>
     * 代理一个类,拦截该类的所有方法,在方法的调用前后进行日志的输出
     * @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;
        }
    
    }
    

    XML-Bean配置如下

    <bean id="fbHelloWorldService" class="com.ebao.xxx.MyFactoryBean">
        <property name="interfaceName" value="com.ebao.xxx.HelloWorldService" />
       <property name="target" ref="helloWorldService" />
     </bean>
    
    @RunWith(JUnit4ClassRunner.class)
    @ContextConfiguration(classes = { MyFactoryBeanConfig.class })
    public class MyFactoryBeanTest {
    
        @Autowired
        private ApplicationContext context;
        
        /**
         * 测试验证FactoryBean原理,代理一个servcie在调用其方法的前后,打印日志亦可作其他处理
         * 从ApplicationContext中获取自定义的FactoryBean
         * context.getBean(String beanName) ---> 最终获取到的Object是FactoryBean.getObejct(), 
         * 使用Proxy.newInstance生成service的代理类
         */
        @Test
        public void testFactoryBean() {
            HelloWorldService helloWorldService = (HelloWorldService) context.getBean("fbHelloWorldService");
            helloWorldService.getBeanName();
            helloWorldService.sayHello();
        }
    }
    

    FactoryBean是一个接口,当在IOC容器中的Bean实现了FactoryBean后,通过getBean(String BeanName)获取到的Bean对象并不是FactoryBean的实现类对象,而是这个实现类中的getObject()方法返回的对象。要想获取FactoryBean的实现类即本身,就要getBean(&BeanName),在BeanName之前加上&。

    package org.springframework.beans.factory;  
    public interface FactoryBean<T> {  
        T getObject() throws Exception;  
        Class<?> getObjectType();  
        boolean isSingleton();  
    }
    

    TgetObject():返回由FactoryBean创建的Bean实例,如果isSingleton()返回true,则该实例会放到Spring容器中单实例缓存池中;
    booleanisSingleton():返回由FactoryBean创建的Bean实例的作用域是singleton还是prototype;
    Class<T>getObjectType():返回FactoryBean创建的Bean类型。
    当配置文件中<bean>的class属性配置的实现类是FactoryBean时,通过getBean()方法返回的不是FactoryBean本身,而是FactoryBean#getObject()方法所返回的对象,相当于FactoryBean#getObject()代理了getBean()方法。

    相关文章

      网友评论

          本文标题:Spring中 BeanFactory与FactoryBean的

          本文链接:https://www.haomeiwen.com/subject/ajhttqtx.html