spring中Bean的装配方式及bean的生命周期(二)

Spring中Bean的配置方式:注解配置,xml配置,基于java的配置

  1.注解配置(自动化装配bean)

Spring从两个角度来实现自动化装配:

   1.1 组件扫描(component scanning):Spring会自动发现应用上下文中所创建的bean。

            使用@Component注解表明该类会作为组件类,并告知Spring要为这个类创建bean。使用时记得启用组件扫描,方法有两种:

   方法一:创建配置类,通过ComponentScan启用组件扫描

   方法二:通过xml文件配置启用组件扫描<context:component-scan base-package="被扫描的组件"/>

    1.2 自动装配(autowiring):Spring自动满足bean之间的依赖。

            我们将bean自动添加到Spring容器中,只需用注解自动装配来满足bean之间的依赖关系。 如:@Autowired

2.基于java的配置

先介绍这个,最后着重介绍基于xml配置。、

其实在SpringBoot中就采用了Java类的配置方式。Java类的配置方式就是声明一个Java类来配置bean。

创建配置类,@Configuration注解表明这个类是一个注解类,该类包含了在Spring应用上下文中如何创建bean的细节。

简单的示例:

@Configuration
public class SpringBeanConfig{
    /**
     *配置bean时,在该方法上使用@Bean注解,可以自动注入到spring容器中
     *相当于xml中的<bean>标签
     */
    @Bean
    public EmployeeDao getEmployeeDao(){
        return new EmployeeDao();
    }

}

3.xml配置方式:

     基于xml的配置方式,我们需要借助于<bean>标签。

​
<bean id="唯一标识" name="别名" class="类的全路径" ></bean>

​

此时若要注入bean,方法有两种:

 方法一:构造注入

​
<bean id="唯一标识" name="别名" class="类的全路径" >
    <constructor-arg ref="注入的bean的标识"/>
</bean>

​

方法三:属性注入

​
<bean id="唯一标识" name="别名" class="类的全路径" >
    <property name="属性名" ref="属性名所对应的对象的标识"/>
</bean>

​

 实例化Bean的三种方式

1.1 使用构造方法

1.2 使用静态工厂方法【(直接创建)】

1.3 使用实例工厂方法【(需要先创建工厂,在创建实体)】

简单的示例:

要创建的对象:

package com.dsx.spring_bean;

public class Employee {
	private Integer emp_id;
	private String name;
	private String phone;
	private String email;
	public Integer getEmp_id() {
		return emp_id;
	}
	public void setEmp_id(Integer emp_id) {
		this.emp_id = emp_id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getPhone() {
		return phone;
	}
	public void setPhone(String phone) {
		this.phone = phone;
	}
	public String getEmail() {
		return email;
	}
	public void setEmail(String email) {
		this.email = email;
	}
	
	
}

静态工厂

package com.dsx.spring_bean;
/**
* @ClassName: StaticFactory  
* @Description: 模拟静态工厂  
* @author 曰业而安  
 */
public class StaticFactory {
	public static Employee getEmp() {
		return new Employee();
	}
}

实例工厂

package com.dsx.spring_bean;
/**
* @ClassName: StaticFactory  
* @Description: 模拟实例工厂  
* @author 曰业而安  
 */
public class InstanceFactory {
	public Employee getEmp() {
		return new Employee();
	}
}

配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
  xmlns="http://www.springframework.org/schema/beans" 
  xmlns:p="http://www.springframework.org/schema/p" 
  xsi:schemaLocation="http://www.springframework.org/schema/beans 
  http://www.springframework.org/schema/beans/spring-beans-4.2.xsd ">
<!--
第一种方式:使用默认构造函数创建
                  在spring的配置文件中使用bean标签,配以id和class属性之后,且没有其他属性和标签时
                  采用的就是默认构造函数创建bean对象,此时如果类中没有默认构造函数,则对象无法创建
  -->
<bean id="employee_constructor" class="com.dsx.spring_bean.Employee">
	<property name="phone" value="13101778369"></property>
</bean>
<!--
        第二种方式: 使用普通工厂中的方法创建对象(使用某个类中的方法创建对象,并存入spring容器)
    -->
    <bean id="instanceFactory" class="com.dsx.spring_bean.InstanceFactory"></bean>
    <bean id="employee_instanceFactory" factory-method="getEmp" factory-bean="instanceFactory"></bean>
<!--
        第三种方式:使用工厂中的静态方法创建对象(使用某个类中的静态方法创建对象,并存入spring容器)
    -->
    <bean id="employee_staticFactory" class="com.dsx.spring_bean.StaticFactory" factory-method="getEmp"></bean>
<!--
        bean的作用范围调整
            bean标签的scope属性:
                作用:用于指定bean的作用范围
                取值:常用的就是单例的和多例的
                     singleton:单例的(默认值)
                     prototype:多例的
                     request:  作用于web应用的请求范围
                     session:  作用于web应用的会话范围
                     global-session:作用于集群环境的会话范围(全局会话范围),当不是集群环境时,它就是session
    -->
</bean>

此时bean就被实例化并注入到了spring容器中。注意要确保有无参构造方法。

静态工厂,动态工厂(实例工厂)的介绍与区别

       静态工厂直接可以通过静态方法来实例化一个对象。

       动态工厂要先创建类对象,在通过工厂对象来调用创建实例对象的方法。

       区别:

             静态工厂初始化之前,工厂中的类已经被实例化放在工厂容器中

             实例工厂在构造方法初始化时,会将类进行实例化放在工厂中。

bean属性注入的几种方式:

1. 使用构造函数注入(一般不用)

       在bean标签内部使用的标签:<constructor-arg name="" ref="指定其引用的bean" .../>

      标签中的属性:

                type:用于指定要注入的数据的数据类型,该数据类型也是构造函数中某个或某些参数的类型
                index:用于指定要注入的数据给构造函数中指定索引位置的参数赋值。索引的位置是从0开始
                name(常用的):用于指定给构造函数中指定名称的参数赋值
                =============以上三个用于指定给构造函数中哪个参数赋值============
                value:用于提供基本类型和String类型的数据
                ref:用于指定其他的bean类型数据,在spring的Ioc核心容器中出现过的bean对象
            优势:
                在获取bean对象时,注入数据是必须的操作,否则对象无法创建成功
            弊端:
                改变了bean对象的实例化方式,使我们在创建对象时,如果用不到这些数据,也必须提供

2. 使用set方法注入

       bean标签内部使用标签:property

      标签的属性
                name:用于指定注入时所调用的set方法名称,去掉set之后首字母小写
                value:用于提供基本类型和String类型的数据
                ref:用于指定其他的bean类型数据。它指的就是在spring的Ioc核心容器中出现过的bean对象
            优势:
                创建对象时没有明确的限制,可以直接使用默认构造函数
            弊端:
                如果有某个成员必须有值,则获取对象时有可能set方法没有执行

 3. p命名空间注入

注意:p名称空间注入,需要有无参构造方法

 4. 使用注解注入

      @Value、@Resource、@Qualifier

bean的作用域:

类别说明
singleton默认值,在Spring容器中仅存在一个Bean实例,Bean以单例模式存在
prototype每次从容器中调用Bean时,都返回一个新的实例。
request每次HTTP请求都会创建一个新的Bean,该作用域仅适用于WebApplicationContext环境
session同一个Http Session共享一个Bean,不同Session使用不同的Bean,仅适用于WebApplicationContext环境
globalSession一般用于Protlet应用环境,该作用域仅适用于WebApplicationContext环境

     注意:

        当作用域为prototype时,Spring容器不能够对Bean的整个生命周期进行管理(当bean为多例时,其自定义的destroy方法是不会被调用的,但初始化方法会被调用),最终对象的销毁和资源回收由使用者负责。singleton则整个生命周期由容器负责。

Bean的生命周期

生命周期图解释

1.instantiate bean对象实例化

2.populate properties 封装属性

3.如果Bean实现BeanNameAware 执行 setBeanName

4.如果Bean实现BeanFactoryAware 执行setBeanFactory ,获取Spring容器

5.如果存在类实现 BeanPostProcessor(后处理Bean) ,执行postProcessBeforeInitialization

6.如果Bean实现InitializingBean 执行 afterPropertiesSet

7.调用<bean init-method="init"> 指定初始化方法 init

8.如果存在类实现 BeanPostProcessor(处理Bean) ,执行postProcessAfterInitialization执行业务处理

9.如果Bean实现 DisposableBean 执行 destroy

10.调用<bean destroy-method="customerDestroy"> 指定销毁方法 customerDestroy

 Spring上下文中的Bean生命周期总结如下:

(1)实例化Bean:

        对于BeanFactory容器,当客户向容器请求一个尚未初始化的bean时,或初始化bean的时候需要注入另一个尚未初始化的依赖时,容器就会调用createBean进行实例化。对于ApplicationContext容器,当容器启动结束后,通过获取BeanDefinition对象中的信息,实例化所有的bean。

(2)设置对象属性(依赖注入)

      实例化后的对象被封装在BeanWrapper对象中,紧接着,Spring根据BeanDefinition中的信息 以及 通过BeanWrapper提供的设置属性的接口完成依赖注入。

(3)处理Aware接口

   接着,Spring会检测该对象是否实现了xxxAware接口,并将相关的xxxAware实例注入给Bean:

   ①如果这个Bean已经实现了BeanNameAware接口,会调用它实现的setBeanName(String beanId)方法,此处传递的就是Spring配置文件中Bean的id值;

  ②如果这个Bean已经实现了BeanFactoryAware接口,会调用它实现的setBeanFactory()方法,传递的是Spring工厂自身。

 ③如果这个Bean已经实现了ApplicationContextAware接口,会调用setApplicationContext(ApplicationContext)方法,传入Spring上下文;

(4)BeanPostProcessor

       如果想对Bean进行一些自定义的处理,那么可以让Bean实现了BeanPostProcessor接口,那将会调用postProcessBeforeInitialization(Object obj, String s)方法。由于这个方法是在Bean初始化结束时调用的,所以可以被应用于内存或缓存技术;

(5)InitializingBean 与 init-method(bean的初始化):

      如果Bean在Spring配置文件中配置了 init-method 属性,则会自动调用其配置的初始化方法。

(6)如果这个Bean实现了BeanPostProcessor接口,将会调用postProcessAfterInitialization(Object obj, String s)方法;

以上几个步骤完成后,Bean就已经被正确创建了,之后就可以使用这个Bean了

(7)DisposableBean:

当Bean不再需要时,会经过清理阶段,如果Bean实现了DisposableBean这个接口,会调用其实现的destroy()方法;

(8)destroy-method:

最后,如果这个Bean的Spring配置中配置了destroy-method属性,会自动调用其配置的销毁方法。

如有不足,欢迎留言指正。望不吝赐教。。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值