Spring何时初始化bean

来源:互联网 发布:苹果屏幕录像软件 编辑:程序博客网 时间:2024/05/22 20:38

今天在看《spring源码深度解析》第五章关于bean加载的部分,跟踪源码的过程中产生一个困惑。就是在我的代码中调用getBean以前,在加载xml配置文件的时候对应的bean就已经进行了初始化。
代码如下:
Main.java

public class Main {    public static void main(String[] args) {        ApplicationContext ac = new ClassPathXmlApplicationContext("factorybean.xml");        Car car = (Car) ac.getBean("somecar");        System.out.println(car);        Person person = (Person) ac.getBean("person");        System.out.println(person);    }}

Car.java

public   class  Car  {      private   int maxSpeed ;      private  String brand ;      private   double price ;      public   int  getMaxSpeed ()   {          return   this . maxSpeed ;      }      public   void  setMaxSpeed ( int  maxSpeed )   {          this . maxSpeed  = maxSpeed;      }      public  String getBrand ()   {          return   this . brand ;      }      public   void  setBrand ( String brand )   {          this . brand  = brand;      }      public   double  getPrice ()   {          return   this . price ;      }      public   void  setPrice ( double  price )   {          this . price  = price;     }    @Override    public String toString() {        return "Car [maxSpeed=" + maxSpeed + ", brand=" + brand + ", price=" + price + "]";    } }

CarFactoryBean.java

public   class  CarFactoryBean  implements  FactoryBean<Car>  {      private  String carInfo ;      public  Car getObject ()   throws  Exception  {          Car car =  new  Car () ;          String []  infos =  carInfo .split ( "," ) ;          car.setBrand ( infos [ 0 ]) ;          car.setMaxSpeed ( Integer. valueOf ( infos [ 1 ])) ;          car.setPrice ( Double. valueOf ( infos [ 2 ])) ;          return  car;      }      public  Class<Car> getObjectType ()   {          return  Car. class ;      }      public   boolean  isSingleton ()   {          return   false ;      }      public  String getCarInfo ()   {          return   this . carInfo ;      }      // 接受逗号分割符设置属性信息      public   void  setCarInfo ( String carInfo )   {          this . carInfo  = carInfo;      }    @Override    public String toString() {        return "CarFactoryBean [carInfo=" + carInfo + "]";    }  }   

bean配置文件

<?xml version="1.0" encoding="UTF-8"?><beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"    xmlns="http://www.springframework.org/schema/beans"    xsi:schemaLocation="http://www.springframework.org/schema/beans    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">    <bean id="car" class="factorybean.CarFactoryBean" p:carInfo="法拉利,400,2000000" />    <bean id="person" class="code.Person">        <property name="name" value="xingoo"/>        <property name="age" value="12"/>    </bean>    <alias name="car" alias="somecar"/><!-- 别名 --></beans>

注意包名
针对Main.java,当运行完ApplicationContext ac = new ClassPathXmlApplicationContext(“factorybean.xml”);这句话时,内存中加载了CarFactoryBean和person对应的bean。之后调用getBean(“somecar”),通过CarFactoryBean的getObject()方法获取到了Car的bean。调用getBean(“person”)直接从内从中获取到对应的bean。

通过此例,掌握了Spring加载bean的时机

Spring什么时候实例化bean,首先要分2种情况

第一:如果你使用BeanFactory作为Spring Bean的工厂类,则所有的bean都是在第一次使用该Bean的时候实例化 (不管bean是否实现了FactoryBean)

第二:如果你使用ApplicationContext作为Spring Bean的工厂类,则又分为以下几种情况:
(1):如果bean的scope是singleton的,并且lazy-init为false(默认是false,所以可以不用设置),则ApplicationContext启动的时候就实例化该Bean,并且将实例化的Bean放在一个map结构的缓存中,下次再使用该Bean的时候,直接从这个缓存中取 (但是如果bean实现了FactoryBean,则ApplicationContext启动的时候先实例化对应的FactoryBean,当第一次使用bean的时候,在通过FactoryBean的getObject方法实例化bean)
(2):如果bean的scope是singleton的,并且lazy-init为true,则该Bean的实例化是在第一次使用该Bean的时候进行实例化
(3):如果bean的scope是prototype的,则该Bean的实例化是在第一次使用该Bean的时候进行实例化

0 0
原创粉丝点击