模板Beans是实现SF核心技术(IoC容器)的模块,也是SF中最复杂的模块。如果能完整的了解关于Bean的知识,非常有利于后续阅读Spring Beans部分的实现源码。
概述
控制反转(IoC)也称为依赖注入(DI),IoC是解决对象(即bean)的创建以及管理的问题。正常情况下,对象实例是由使用者通过new来创建,但当对象很多且关系复杂的时候,这种方法不仅繁琐,而且复杂(需关注对象的作用范围及生命周期)。
在SF中,由Spring的IoC容器来管理对象的创建、配置和生命周期,不需要人工来管理对象之间复杂的依赖关系,这样做的好处有:
1、使用者不需要手工创建对象实例,直接使用即可,简单直接;
2、对象定义和使用分离,达到解耦目的。
SF中的IoC容器包括BeanFactory和ApplicationContext,前者提供Bean实例化相关功能,后者提供在应用中使用Bean的功能。
本文主要介绍Bean相关知识。
bean概念
在Spring中,构成应用程序主干并由Spring IoC容器管理的对象称为bean。bean是一个由Spring IoC容器实例化、组装和管理的对象。bean以及它们之间的依赖关系反映在容器使用的配置元数据中。
bean的命名
bean的命名标识符包括id,name和alias。通常情况下,id是识别一个bean的属性标识符,容器内必须唯一。name是bean的名称,易于bean被使用。alias是bean的别名,适用同一个bean需要多个名字的场合,因此一个bean可以有多个alias。三者定义时关系如下:
1、只定义一个id,此时name即为id。
<bean id="HelloSFService" class="com.learnsf.service.HelloSFService"/>
2、只定义name,不定义id,此时id即为name,且必须容器内唯一。
<bean name="helloSFService" class="com.learnsf.service.HelloSFService"/>
3、定义alias
格式1如下,其中hsf1为name,hsf2,hsf3为别名。
<bean id="HelloSFService" name="hsf1,hsf2,hsf3" class="com.learnsf.service.HelloSFService"/>
格式2如下,其中name为hsf,hsf2,hsf3为别名。
<bean id="HelloSFService" name="hsf" class="com.learnsf.service.HelloSFService"/>
<alias alias="hsf1" name="hsf"/>
<alias alias="hsf2" name="hsf"/>
4、实际使用过程中,name和alias不需要严格区分。spring中获取对象的方法叫做getBean(String name),Spring在获取对象时,会统一将参数name视为别名。获取过程就是:根据name参数获取beanId,再根据beanId从单例池中获取bean。
bean定义
bean定义(BeanDefinition)就是一个bean的元数据配置。一个BeanDefinition可看作一个配方,容器根据这个配方来实例化对应的类。
bean依赖注入
一个典型的应用程序不可能仅由一个对象组成。即使是最简单的应用程序,也有几个对象可以一起工作。依赖注入(DI-Dependency Injection)指spring可根据元数据配置自动建立Bean之间的协作关系。
依赖注入实现有如下几种方式:
1、通过构造函数参数传入对依赖对象
2、通过工厂方法参数传入对依赖对象
3、从工厂方法返回时通过set方法在对象实例上设置的属性依赖对象
使用DI,代码更干净,解耦更有效。对象使用依赖对象时,不需查找依赖对象,也不需知道依赖对象的位置或类。
bean自动装配
bean之间关系建立可以通过DI方式,但如果协作对象很多,用起来就很不方便,可通过自动装配(autowire)方式进行。
自动装配四种模式:
no:默认为非自动装配模式。
byName:按属性名称自动装配-Spring查找与需要自动连接的属性同名的bean。
byType:按属性类型自动装配-如果容器中只存在一个同属性类型的bean,则对属性进行自动连接;如果存在多个,则会引发致命异常;如果没有匹配的bean,则不会发生任何事情(属性则未设置)。
constructor:类似于byType,但适只用于构造函数参数。
xml配置:autowire-candidate=“false” (bean标签属性)
注解配置:@Autowired
bean延迟加载
默认情况下,ApplicationContext在启动过程中,会立即创建和配置所有单例bean。但spring提供延迟加载(Lazy-initialized)功能:即bean实例不是在启动时创建,而是延迟到第一次请求该bean时才创建bean实例。
xml配置:lazy-init=“true” (bean标签属性)
注解配置:@Lazy
bean种类
Spring 中有两种类型的 Bean,一种是普通Bean, 另一种是工厂Bean。
普通Bean:默认就是框架利用反射new出来的bean实例
工厂Bean:用于创建一种bean的bean,通常继承接口FactoryBean。注意不是Spring中的BeanFactory。
bean的范围
通过BeanDefinition可以控制bean创建对象的范围。spring支持六种范围模式:
singleton(单例模式):一个BeanDefinition只创建唯一一个 Bean实例,在整个 IOC 容器范围内都能共享该实例。在元数据中未特别声明的Bean,默认为singleton模式。
prototype(原型模式):一个BeanDefinition可创建唯多个 Bean实例。每次调用都会产生一个新的Bean实例。
request:对于每次HTTP请求,使用request的BeanDefinition都将产生一个新实例。仅在WebApplicationContext容器中有效。
session:在同一个HTTP Session中,一个BeanDefinition创建一个实例,在session有效期内共享使用;但不同HTTP session使用的Bean实例是不同的。仅在WebApplicationContext容器中有效。
application:在一个ServletContext生命周期内,一个BeanDefinition只创建一个 Bean实例。仅在具备web-aware能力应用容器中有效。
websocket:在一个websocket生命周期内,一个BeanDefinition只创建一个 Bean实例。仅在具备web-aware能力应用容器中有效。
bean的生命周期
bean的生命周期包括创建、使用和销毁。
创建:spring容器创建bean,包括无参构建、有参构建、引用关系建立。
使用:应用程序直接使用bean。
销毁:容器关闭或GC处理无引用的bean。
bean的生命周期由spring容器完成管理,应用只需要正常使用bean即可,bean的创建和销毁对应用程序来说基本无感。
bean创建过程
bean的创建过程非常复杂,核心创建过程的顺序如下:
1、根据beanDefinition创建Bean对象;
2、装配Bean-设置Bean的属性;
3、如果bean实现了Aware接口,则会给Bean注入容器中的基础设施层对象。如bean实现了ApplicationContextAware接口,则会注入当前ApplicationContext;-扩展点
4、执行BeanPostProcessor.postProcessBeforeInitialization。-扩展点
5、调用Bean自定义的的init方法(@PostConstruct标注)。-扩展点
6、如果Bean实现了InitializingBean接口,则会调用afterPropertiesSet方法。-扩展点
7、调用BeanPostProcessor.postProcessAfterInitialization。-扩展点
8、创建完毕;
如果应用中有Bean需要介入应用启动过程,扩展点就是框架预留的介入点。
BeanPostProcessor
bean创建过程中,可在bean的初始化前后进行额外处理。接口BeanPostProcessor包括两个方法:
public interface BeanPostProcessor {
@Nullable
default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
//实例化前处理
return bean;
}
@Nullable
default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
//实例化后处理
return bean;
}
}
bean销毁过程
1、执行bean中@PreDestory标注的方法(做销毁前处理);-扩展点
2、bean实现了接口DisposableBean,则执行实现的destory()方法;-扩展点
3、释放bean实例内存;
4、销毁完毕。
外部bean
spring通过引用第三方包,生成对应的bean供应用程序使用。以数据源为例,步骤如下:
1、引入外部包,pom文件中加入:
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.17</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.alibaba/druid -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.3</version>
</dependency>
2、根据外部包要求创建对应的属性文件(appdb.properties),设置数据库连接参数(仅体现部分参数属性)。
appdb.driverClass=com.mysql.jdbc.Driver
appdb.url=jdbc:mysql://localhost:3306/test
appdb.userName=test
appdb.password=123456
3、应用xml配置文章来源:https://www.toymoban.com/news/detail-475685.html
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!--引入根据外部包要求创建的属性文件-->
<context:property-placeholder location="classpath:appdb.properties"></context:property-placeholder>
<!--配置数据源-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="${appdb.driverClass}"></property>
<property name="url" value="${appdb.url}"></property>
<property name="username" value="${appdb.userName}"></property>
<property name="password" value="${appdb.password}"></property>
</bean>
</beans>
在应用中从容器中getBean(“dataSource” )即可使用。文章来源地址https://www.toymoban.com/news/detail-475685.html
到了这里,关于一起学SF框架系列5.1-模块Beans-bean概述的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!