Spring Bean管理
Spring的核心在于Ioc,我们上一篇已经提到了Ioc的概念,把对象的控制权较给容器来管理。在Spring中,凡是被Spring创建和管理的对象都叫做Bean。
BeanSpring管理的Bean,一般是由你提供的配置来创建,如Java配置,注解配置,XML配置。在容器内部,这些Bean表现为BeanDefinition对象。
Bean的配置
基于XML的配置
在xml中,我们可以更了解Bean的配置,一个配置案例如下:
常见xml配置
分别解说各个参数的作用:
- class: 要实例化的类。所谓的bean在内存中就是实例化后的对象。class指的是要实例化那个类。
- name: Bean的名称,便于记忆
- scope: 下面会提到
- constructor arguments: 构造器参数
- properties 属性
- autowiring模式,Bean依赖其它Bean时候的模式
- lazy-initialization 懒加载模式
- initialization 初始化方法
- destruction 销毁方法
直接拿一个XML注解的案例来说明:
还记得上一篇文章需要的几个类吗,这里我们再用一次。
- 准备好Java对象
public interface HelloWord {
void sayHello();
}
public class HelloWordImpl1 implements HelloWord {
@Override
public void sayHello() {
System.out.println("hello1");
}
}
public class HelloWordImpl2 implements HelloWord {
@Override
public void sayHello() {
System.out.println("hello2");
}
}
- 根据不同的XML配置,获得不同的结果
2.1 scope的作用
scope为prototype时,每次从容器中获取bean,相应的对象都会重新实例化一次,也就是每次拿到的都是新创建的对象。
scope为singleton的时候,bean一直在容器中存在,直接容器销毁之前销毁,每次获取bean,获取到的是同一个bean
//准备好App文件
public class App {
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("app.xml");
HelloWord helloWord = applicationContext.getBean(HelloWord.class);
HelloWord helloWord2 = applicationContext.getBean(HelloWord.class);
helloWord.sayHello();
System.out.println(helloWord2);
}
}
<bean id="helloworld" class="me.aihe.HelloWordImpl2" scope="prototype"/>
//运行结果
me.aihe.HelloWordImpl2@6a2bcfcb
me.aihe.HelloWordImpl2@4de8b406
<bean id="helloworld" class="me.aihe.HelloWordImpl2" scope="singleton"/>
//运行结果
me.aihe.HelloWordImpl2@6d8a00e3
me.aihe.HelloWordImpl2@6d8a00e3
Spring默认bean的scope为singleton。
2.2 construct-arg参数
这个参数是构造bean对象的时候,提供构造参数
[图片上传失败...(image-d2cf54-1526781442058)]
- ref指的是,当构造某个bean的时候,这个bean依赖其它的bean,使用ref来指向依赖的bean
- type: 构造器参数中,精确的类型是什么,String或其它等等
- index: 构造器参数具体的索引
//还是给一个简单运行的案例
//改造HelloWordImp2
public class HelloWordImpl2 implements HelloWord {
String str;
public HelloWordImpl2(String str) {
this.str = str;
System.out.println("实例化str:" + str);
}
public void sayHello() {
System.out.println("hello2");
}
}
//XML配置
<bean id="helloworld" class="me.aihe.HelloWordImpl2">
<constructor-arg type="java.lang.String" value="你好" />
</bean>
<bean id="helloworld" class="me.aihe.HelloWordImpl2">
<constructor-arg index="0" value="你好" />
</bean>
<bean id="helloworld" class="me.aihe.HelloWordImpl2">
<constructor-arg name="str" value="你好" />
</bean>
// 以上三个bean只需要其中一个就好了,这里演示的是三个的运行结果都是一样的
//运行结果都是
实例化str:你好
me.aihe.HelloWordImpl2@d8355a8
me.aihe.HelloWordImpl2@d8355a8
2.3 property属性
property主要配置Java对象中有setter和getter方法的属性。
2.4 autowiring模式,保持默认就好,bean解析的方式,byType,byName
2.5 lazy-init赖加载模式
当设置为true的时候,只有在我们需要这个对象的时候,才会被实例化。
public class App {
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("app.xml");
System.out.println("初始化applicationContext完成");
HelloWord helloWord = applicationContext.getBean(HelloWord.class);
System.out.println(helloWord);
}
}
public class HelloWordImpl2 implements HelloWord {
public HelloWordImpl2() {
System.out.println("实例化中");
}
public void sayHello() {
System.out.println("hello2");
}
}
<bean id="helloworld" class="me.aihe.HelloWordImpl2" lazy-init="true" />
// 运行结果
初始化applicationContext完成
实例化中
me.aihe.HelloWordImpl2@573f2bb1
<bean id="helloworld" class="me.aihe.HelloWordImpl2" lazy-init="false" />
//运行结果
实例化中
初始化applicationContext完成
me.aihe.HelloWordImpl2@6d8a00e3
可以看到,使用lay-init为true之后,在应用初始化完成后,只有再调用的时候才会实例化具体的bean。而设置为false则在初始化applicationContext的时候就实例化了。
2.6 init-method
在实例化该对象的后,调用此方法
<bean id="helloworld" class="me.aihe.HelloWordImpl2" lazy-init="false" init-method="sayHello"/>
//运行结果
实例化中
hello2
初始化applicationContext完成
me.aihe.HelloWordImpl2@6d8a00e3
2.7 destroy-method
容器销毁该bean的时候,调用此方法
public class App {
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("app.xml");
System.out.println("初始化applicationContext完成");
HelloWord helloWord = applicationContext.getBean(HelloWord.class);
System.out.println(helloWord);
((ClassPathXmlApplicationContext) applicationContext).destroy();
}
}
public class HelloWordImpl2 implements HelloWord {
public HelloWordImpl2() {
System.out.println("实例化中");
}
public void sayHello() {
System.out.println("hello2");
}
public void sayGoodBye(){
System.out.println("拜拜");
}
}
<bean id="helloworld" class="me.aihe.HelloWordImpl2" lazy-init="false" init-method="sayHello" destroy-method="sayGoodBye"/>
// 运行结果
实例化中
hello2
初始化applicationContext完成
me.aihe.HelloWordImpl2@6d8a00e3
拜拜
基于注解与基于Java的配置
了解了XML配置之后,注解的配置更加简单,关键的几个注解如下
-
@Bean, 可以指定name,init-method,destroy-method,autowire
-
@Lazy 指定bean是否要懒加载
-
@Scope 指定scope
-
@Primary 当有多个bean类型相同的时候,指定优先使用带有@primary的bean,有多个@primary标记类型相同的bean的时候,会报错
-
@Component,@controller,@Service,@Reposotory 标记某个对象为bean
Bean的扫描
在XML配置中
// 开启注解配置
<context:annotation-config />
// 扫描bean所在的包
<context:component-scan base-package="me.aihe" />
Java配置
@ComponentScan(value = "me.aihe")
小结
这篇文章主要讲了Bean的常见配置,Bean的配置还有更深入的内容,等待我们去探索。
网友评论