spring学习之---深入理解容器中的Bean

来源:互联网 发布:淘宝网的域名怎么设置 编辑:程序博客网 时间:2024/06/14 08:42

1.抽象Bean与子Bean

抽象bean:把多个<bean.../>配置中相同的信息提取出来,集中成配置模板—这个模板并不是真正的Bean,因此spring不应该创建该配置模板。于是需要为该<bean.../>配置增加abstract=”true”。抽象Bean不能被实例化,spring容器不会创建抽象bean实例。抽象Bean的价值在于被继承,抽象Bean通常作为父Bean被继承。
子Bean定义可以从父Bean继承实现类、构造器参数、属性值等配置信息,子Bean可以增加新的配置信息,并可指定新的配置信息覆盖父Bean的定义。
指定parent属性即可指定该Bean是一个子Bean。
子Bean无法从父Bean继承如下属性:depends-on、autowire、singleton、scope、lazy-init。

2.Bean继承与Java继承的区别

  • spring中的子Bean和父Bean可以是不同类型,但Java中的继承则可保证子类是一种特殊的父类。
  • spring中的Bean的继承是实例之间的关系,因此主要表现为参数值的延续;Java中的继承是类之间的关系,只要表现为方法、属性的延续。
  • spring中的子Bean不可作为父Bean使用,不具备多态性;Java中的子类实例完全可当成父类实例使用。

3.容器中的工厂Bean

工厂Bean是spring的一种特殊Bean,这种工厂Bean必须实现FactoryBean接口。
FactoryBean接口是工厂Bean的标准接口,把工厂Bean部署在容器中之后,如果程序通过getBean()方法来获取它时,容器返回的不是FactoryBean实现类的实例,而是返回FactoryBean的产品(即该工厂Bean的getObject()方法的返回值)
FactoryBean接口提供如下三个方法:

  • T getObject():实现该方法负责返回该工厂Bean生成的Java实例。
  • Class<?> getObjectType():实现该方法返回该工厂Bean生成的Java实例的实现类。
  • boolean isSingleton():实现该方法表示该工厂Bean生成的Java实例是否为单例模式。
    FactoryBean最大作用:spring容器并不是简单地返回该Bean的实例,而是返回该Bean实例的getObject()方法的返回值,而该方法则由开发者负责实现。
    public class GetFieldFactoryBean implements FactoryBean{        private String targetClass;        private String targetField;        setter方法;        public Oject getObject() throws Exception{            Class<?> clazz = Class.forName(targetClass);            Field field = clazz.getField(targetField);            return field.get(null);        }        public Class<? extends Object> getObjectType(){            return Object.class;        }        public boolean isSingleton(){            return false;        }    }    <bean id="north" class="...GetFieldFactoryBean">        <property name="targetClass" value="java.awt.BorderLayout"/>        <property name="targetField" value="north"/>    </bean>

getObject方法的执行体使用反射先获取targetClass对应的Class对象,再获取targetField对应的类变量的值。
spring容器会自动检测容器中的所有Bean,如果发现某个Bean实现类实现了FactoryBean接口,spring容器就会在实例化该Bean、根据<property.../>执行setter方法之后,额外调用该Bean的getObejct()方法,并为该方法的返回值作为容器中的Bean。

    System.out.printl(ctx.getBean(&north));

在Bean id前增加&符号,这将会让spring返回FactoryBean本身。

4.获得Bean本身的id

在某些极端情况下,业务要求程序员在开发Bean类时能预先知道该Bean的配置id,此时可借助spring提供的BeanNameAware接口,通过该接口即可提前预知该Bean的配置id。
BeanNameAware接口提供了一个方法:setBeanName(String name),该方法的name参数就是Bean的id,实现该方法的Bean类就可通过该方法来获得部署该Bean的id了。
当spring容器调用这个setter方法时,会把部署该Bean的id属性作为参数传入。

    public class Chinese implements BeanNameAware{        private String beanName;        public void setBeanName(String name){            this.beanName = name;        }        public void info(){            System.out.println("部署该Bean时指定的id为:" + beanName);        }    }

5.强制初始化Bean

在极端的情况下,Bean之间的依赖不够直接。比如,某个类的初始化块中使用其他Bean,spring总是先初始化主调Bean,当执行初始化块时,被依赖Bean可能还没实例化,此时将引发异常。
为了显示指定被依赖Bean在目标Bean之前初始化,可以使用depends-on属性,该属性可以在初始化主调Bean之前,强制初始化一个或多个Bean。

    <bean id="beanOne" class="" depends-on="beanTwo"/>    <bean id="beanTwo" class=""/>