SpringBean的配置详解
基于xml配置的预览
下面是基于xml开发Spring应用的常用配置。
其中:
lazy-init属性如果为true,则表示Bean延迟加载,并且如果容器时BeanFactory时这个属性的配置是无效的,因为BeanFactory加载bean就是当调用getBean方法时才加载bean,而ApplicationContext容器是xml文件加载时就加载好全部的bean。
init-method属性指定当bean构造完成后执行哪个方法作为初始化方法,destroy-method则指定bean实例销毁前执行的方法。
autowire属性,这里涉及到上一篇中提到的依赖注入,设置autowire=“byType”表示按类型自动注入,byName表示按名字自动注入。
beanName和别名配置
在xml中配置bean时,一般我们会给出bean的id,也就是bean在xml文件中的唯一标识,而实际上实例化bean即调用getBean时,参数是beanName而非beanId,这是Spring自动将beanId作为beanName为bean工厂进行bean的实例化。
当然,也可以在xml文件中不写id,但是不写id的话,Spring会默认将实体类的全限定名(也就是class属性的值)作为beanName,如applicationContext.getBean("com.itheima.dao.impl.UserDaoImpl");
bean的别名,没什么好说的,配置name属性后(也就是别名),别名会指向实际的beanName(也就是id属性)。
如果id都不配,Spring会默认将name属性中的第一个作为beanName
bean的范围配置
singleton,单例的,在服务器加载xml文件时就实例化所有的Bean并存储到容器内部的单例池中,每次getBean都是从单例池中获取相同的Bean实例。
prototype,原型的,Spring容器初始化时不创建Bean实例,而是到调用getBean时才实例化Bean,每次实例化都会创建一个新的Bean实例。
在只引入Spring依赖的项目环境中,scope的取值是只有singleton和prototype的,但是引入其他依赖如SpringMVC时,scope的取值有:singleton、prototype、request(将实例化的Bean放在request域中)和session(将实例化的Bean放在session域中)
Bean的延迟加载
Bean的初始化方法和销毁方法的配置
init方法会在Bean被构造出来后执行,destory方法会在Bean容器销毁时执行。
值得注意的是,一般情况下ApplicationContext不会显性销毁,这样就不会执行destory方法,我们需要用ApplicationContext的实现类ClassPathXmlApplicationContext提供的close方法就会显性销毁,这样就能看到destory的效果。
我们也可以让Bean实体类实现InitializingBean接口,完成Bean的一些初始化操作,接口要求实现afterPropertiesSet方法,方法内可以编写一些初始化操作。
所以执行顺序是:Bean构造 --> Bean属性、依赖注入 --> afterPropertiesSet方法 --> init方法
Bean的实例化方式的配置
构造方法实例化
默认情况下,Bean通过实体类的无参构造进行实例化,如果没有提供也没有配置,Spring会报错说Bean实例化时找不到空构造器。
当然也可以配置有参构造进行实例化,使用constructor-arg子标签
工厂方式实例化
1、静态工厂方法实例化Bean
静态工厂方法实例化Bean实际上就是将工厂类的静态方法的返回值作为Bean加入到Spring容器中。
如下,有一个工厂类,其中有一个返回UserDaoImpl的静态方法。
在xml配置文件中配置工厂类,配置id="userDao1",加入factory-method属性为静态方法名,即配置完成,之后getBean("userDao1")会拿到静态工厂方法返回的Bean。即,不是工厂对象被加载为Bean进入Spring容器,而是配置的静态工厂方法返回的实例作为Bean进入Spring容器。
2、实例工厂方法实例化bean
如下有一个实例工厂及实例化方法
首先配置工厂对象,即将工厂类配置为bean
其次要配置实例化方法返回对象为bean,factory-bean属性指定bean容器中的工厂类bean,factory-method指定该工厂类的实例化方法。
3、有参数的静态工厂和实例工厂方法
静态工厂方法:
加constructor-arg子标签,name属性对应形参名,value属性对应形参的值。
实例工厂方法:
4、实现FactoryBean规范延迟实例化Bean
FactoryBean实际上是一个规范接口
如下,一个类实现FactoryBean接口,泛型为需要加入容器的bean对象的接口(UserDao),重写getObject和getObjectType方法,返回值为实际被Bean管理的实现类(UserDaoImpl)
配置如下,可以看到配置和普通bean配置一样
执行getBean,得到UserDaoImpl实例
但是我们在调试中,在BeanFactory的single单例池中可以看到,key为userDao1、userDao2对应的value实例都是UserDaoImpl
但key为userDao3对应的实例却是MyBeanFacory3,也就是刚刚那个实现ApplicationContext接口的工厂,直觉上我们会觉得实例并不是我们需要的UserDaoImpl实例
但其实我们在factoryBeanObjectCache这个缓存池中可以看到,userDao3对应的就是UserDaoImpl实例
即:当ApplicationContext这些Bean容器加载时,在xml中配置的实现FactoryBean接口的bean加载实例化进入Bean容器,但是只有当调用getBean时才会运行FactoryBean接口的getObject方法,才会将Impl实例加载返回,并存入factoryBeanObjectCache缓存中。
Bean的依赖注入配置
Bean的依赖注入有set方法和构造方法注入,如果是注入简单对象(如int,String)就用name-value属性,如果要注入引用对象实例(其他Bean)则用name-ref,ref属性引用其他Bean的id
集合属性的注入时,就不用value和ref属性了,而用子标签:
List集合:
如果集合泛型是简单类型数据:
property标签的name属性指定注入对象,List --> value 为集合注入值。
如果集合的泛型是引用对象实例:
方式一:将bean直接配置在list标签中
方式二:ref标签引用Bean
Set集合:
简单类型注入和引用类型注入和list的注入一样,只不过list子标签改成了set子标签
Map集合:
键值对,键和值都可以为简单类型或引用类型
配置时使用map子标签,entry(键值对)子标签来指定键值对的值
当键为简单类型时用key属性,为引用类型时用key-ref属性;
同理值也有两种配置,为value和value-ref
Properties集合:
properties也是键值对,只不过键值对都必须为字符串
自动装配方式
像我们之前要注入依赖是bean的话,需要应用子标签properties指定name和ref属性,ref为bean容器中要注入的beanId
如果注入的属性类型是bean容器中的bean的话,可以在bean标签中使用autowire属性进行自动注入,autowire注入有byName和byType两种,如下:
byName,根据属性名自动装配,要求被装配的bean提供setter方法,Spring会自动根据setter方法名去匹配bean容器中id与之匹配的bean;
byType,根据类型自动装配,Spring会根据注入的类型去bean容器中匹配对应类型的bean
如果bean容器中出现了多个相同类型的bean,byType就会报错
Spring其他标签配置
Spring的xml标签分为默认标签和自定义标签,使用自定义标签需要额外引入其他命名空间。
如下,
xmlns:context=".../context"
xsi:schemaLocation=".../context .../context/spring-context.xsd"就是自定义标签,
其中,xmlns:context这里加粗的context规定了自定义标签的前缀,相应使用时要有对应的前缀
Spring的默认标签:
beans标签
beans标签除了作为根标签外,还可以直接嵌套在根标签中,以profile属性规定不同的开发环境,如下:
默认情况下Spring使用默认环境,如果要指定配置的环境,可以用代码的方式:
值得注意的时,指定了环境依然会加载默认环境。
import标签
例如:
user.xml和orders.xml中分别配置了UserService和UserDao的bean,通过在主配置文件中import另外两个配置文件,使得bean容器在加载主配置文件的时候可以加载到另外两个配置文件中的bean。
alias标签:
自定义标签: