Bean的作用域

作用域

singleton

单例(默认值), 在每个SpringIOC容器中,一个bean定义对应一个对象实例

prototype

一个bean定义对应多个对象实例

request

在一次HTTP请求中,一个bean定义对应一个实例,即每次HTTP请求将会有各自的bean实例,它们依据某个bean定义创建而成。该作用域仅在基于Web的Spring ApplicationContext的情况下有效。

session

在一个HTTP Session 中,一个bean定义对应一个实例。该作用域仅在基于Web 的SpringApplicationContext的情况下有效

global session

在一个全局的HTTP Session中,一个bean定义对应一个实例。典型情况下,仅在使用portlet context的时候有效。该作用域仅在基于Web的Spring ApplicationContext的情况下有效

注解形式

1
@Bean ("stu")

配置文件形式

1
2
3
4
5
6
7
8
<bean id="student" class=" com.ehshyee.entity.Student">
value :简单类型
<property name="stuNo"value="1"></property>
<property name="stuName" value="张三"></property>
<property name="stuAge" value="23"></ property>
ref:其他类型
<property name="address" ref="myaddress"></property>
</bean>

分别对其获取两个学生 查看是否为同一个

1
2
3
Student stul = (Student) context.getBean(S:"student") ;
Student stu2 = (Student) context.getBean(S:"student") ;
System.out.println(stul =stu2) ;

均返回true

在xml中scope默认是singleton 可改为prototype

1
<bean id="student" class=" top.ehshyee.entity.Student" scope="prototype">

改后返回false

注解中添加

1
@scope("prototype")//默认singleton

对于实例产生的时机

一些测试

1
2
3
4
5
6
7
8
9
10
public Student() {
System.out.println("student无参构造") ;
}
public Student(int stuNo, String stuName, int stuAge) {
super();
this.stuNo = stuNo;
this.stuName = stuName;
this.stuAge = stuAge;
//有参构造
}

singleton | prototype

执行时机(产生bean的时机) :

default)singleton:容器在初始化时,就会创建对象(唯一的一个);以后再getBean时,不再产生新的bean.singleton也支持延迟加载(懒加载) :在第一次使用时产生。

prototype:容器在初始化时,不创建对象;只是在每次使用时(每次从容器获取对象时,context.getBean(Xxxx)),再创建对象,并且,每次getBean()都会创建一个新的对象。

延迟加载(注解形式)

1
@lazy

条件注解 –>SpringBoot

可以让某一个Bean在某些条件下加入Ioc容器,其他情况下不加IoC容器。

a.准备bean

1
2
3
4
5
6
7
public interface Car {

}
public class EnegerCar implements Car {
}
public class OilCar implements Car{
}

b.增加条件Bean:给每个Bean设置条件,必须实现Condition接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class OilCarCondition implements Condition {
@Override
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
//如果当前环境的车类型是Oil,则加入OilCar
//获取环境
Environment environment=conditionContext.getEnvironment();
String carType=environment.getProperty("car.type");

return carType.contains("oil");
}
}
public class EnergyCarCondition implements Condition {
@Override
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
//如果当前环境的车类型是energy,则加入energyCar
//获取环境
Environment environment = conditionContext.getEnvironment();
String carType = environment.getProperty("car.type");

return carType.contains("energy");
}
}

c.根据条件加入IOC容器

1
2
3
4
5
6
7
8
@Bean
@Conditional (OilCarCondition.class)
public Car oilCar ()
{return new oilCar()}
@Bean
@Conditional (EnergyCarCondition.class)
public Car energyCar ()
{return new EnergyCar ()}

测试

在VM option中添加参数为oil-Dcar.type=oil

1
2
3
4
5
6
7
public static void testAnnotation {
//注解方式
ApplicationContext context = new AnnotationConfigApplicationContext (MyConfig.class);
String[] beanDefinitionNames = context.getBeanDefinitionNames();
for (String name : beanDefinitionNames) {
System.out.println(name) ;
}}

给IoC加入Bean的方法

注解:

​ 三层组件: 扫描器+三层注解

​ 非三层组件@Confiquration:

  1. @Bean+返回值
  2. @import
  3. FactoryBean(工厂 Bean)

@import使用:

①直接编写到@Import中

1
2
3
@Confiquration
@Import ( {Apple.class, Banana.class} )
//bean是id 是全类名

②自定义ImportSelector接口的实现类,通过selectimports方法实现,方法的返回值就是要纳入IoC容器的Bean),并告知系统自己编写的实现类。

1
2
3
4
5
6
public class MyImportSelector implements ImportSelector {
@Override
public String[] selectImports (AnnotationMetadata importingClassMetadata) {
//return new string[0] ;//返回值就是要加入IOC容器的bean的全类名
return new String[]{ "top.eshyee.entity.Apple", "top.eshyee.entity.Banana"}
}
1
@Import(Orage.class,MyImportSelector.class)

③编写ImportBeanDefinitionRegistrar接口的实现类,重写方法

1
2
3
4
5
6
7
8
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar{
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
BeanDefinition beanDefinition new RootBeanDefinition(Orange.class) ;
// or BeanDefinition beanDefinition new RootBeanDefinition("top.eshyee.entity.Orange") ;
registry.registerBeanDefinition("myorange",beanDefinition);
}
}
1
@Import(MyImportBeanDefinitionRegistrar)

FactoryBean(工厂 Bean)

写注册类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class MyEactoryBean implements FactoryBean
{
@Override
public Object getobject() throws Exception {

return new Apple;
}
@Override
public Class<?> getobjectType() {
return Apple.class ;
}
@Override
public boolean isSingleton() {
return true;
}
}

bean中实现

1
2
3
4
@Bean
public FactoryBean<Apple> myFactoryBean() {
return new MyFactoryBean() ;
}

拿myFactoryBean中的值

1
2
3
4
object obj (context. getBean( "myFactoryBean") );
System.out.println(obj) ;
object obj (context. getBean( "&myFactoryBean") );
System.out.println(obj) ;

&:不加&获取的是最内部真实的Apple;

Bean的生命周期

创建(new …)、 初始化(赋初值)、….销毁(servlet)

方法一:

init destroy

xml :

1
<bean id="StudentDao" class="top.eshyee.dao.impl.StudentDaoImpl" init-method="" destroy-method=""></bean>

注解:

1
@Bean(value="stu", initMethod ="myInit", destroyMethod="myDestroy")

IoC容器在初始化时,会自动创建对象(构造方法) ->init ->…..-> 当容器关闭时调用destroy..

方法二:

三层组件: 扫描器+三层注解(功能性注解+MyIntToStringConverter. java转换器)@Controller、@Service、@Repository、@Component

JAVA规范:JSR250

@PostConstruct:相当于方法一的init

@PreDestroy:相当于方法- - 的destroy

1.将响应组件加入@Component注解、给初始化方法加@PostConstruct、给销毁方法加@PreDestroy

如果要获取@Component注解中的bean,那么该Bean的名字就是@Component (value= “xxx”)的value值

调用

1
MyIntToStringConverter converter= (MyIntToStringConverter) context.getBean

方法三:

双接口

三层组件

InitializingBean初始化
DisposableBean销毁

初始化:只需要实现InitializingBean中 的afterPropertiesSet()方法

销毁:实现DisposableBean 中的destroy()方法

如果是注解形式,随便写一个方法,然后加上相应注解即可

如果是接口形式,必须实现接口中规定的方法

方法四:

三层组件

单接口:

接口BeanPostProcessor:拦截了所有容器中的Bean