1. FactoryBean
- Spring中有两种类型的bean,一种是普通bean,另一种是
工厂bean,即FactoryBean。
使用场景:对一些对象想让spring去管理,但是又不希望spring默认去创建,就可以使用FactoryBean。- 工厂bean跟普通bean不同,其返回的对象不是指定类的一个实例,其返回的是该工厂bean的getObject方法所返回的对象。
- 工厂bean必须实现org.springframework.beans.factory.FactoryBean接口
1.1 bean的作用域
高频面试问题!
- singleton
- prototype
- request
- session
在Spring中,可以在<bean>元素的scope属性里设置bean的作用域,以决定这个bean是单实例的还是多实例的。
/**
singleton :单例的,默认作用域:
特点:单例的bean在ioc容器被创建的时候就会创建。
prototype:多例的。
特点:多例的bean不会在ioc容器创建的时候创建对象。 bean的对象会被创建多次。每次通过getBean方法获取对象的时候都会返回一个新的bean对象
request:一次请求期间只创建一次bean对象,该作用域仅适用于WebApplicationContext环境。
session:一次会话期间只会创建一个bean对象,该作用域仅适用于WebApplicationContext环境。
* */
- 默认情况下,Spring只为每个在IOC容器里声明的bean创建唯一一个实例,整个IOC容器范围内都能共享该实例:所有后续的getBean()调用和bean引用都将返回这个唯一的bean实例。
1.2 bean的生命周期
Spring IOC容器可以管理bean的生命周期,Spring允许在bean生命周期内特定的时间点执行指定的任务。
Spring IOC容器对bean的生命周期进行管理的过程
-
①通过构造器或工厂方法创建bean实例
public Employee(){ System.out.println("第一步,调用构造器创建对象"); }
-
②为bean的属性设置值和对其他bean的引用
public void setUsername(String username) { System.out.println("第二步,调用set方法给对象赋值"); this.username = username; }
-
③将bean实例传递给bean后置处理器的
postProcessBeforeInitialization()
方法 -
④调用bean的初始化方法
public void init(){ System.out.println("第三步,调用初始化方法"); }
-
⑤将bean实例传递给bean后置处理器的
postProcessAfterInitialization()
方法 -
⑥bean可以使用了(第五步省略)
-
⑦当容器关闭时调用bean的销毁方法
public void destroy(){ System.out.println("第五步,调用销毁方法"); }
注意:
-
在配置bean时,通过init-method和destroy-method 属性为bean指定初始化和销毁方法
<bean id="employee"class="cn.justweb.lifecycle.Employee" p:age="18" p:username="taoge1" init-method="init" destroy-method="destroy"></bean>
-
bean的后置处理器
- bean后置处理器允许在调用初始化方法前后对bean进行额外的处理
- bean后置处理器对IOC容器里的所有bean实例逐一处理,而非单一实例。其典型应用是:检查bean属性的正确性或根据特定的标准更改bean的属性。
- bean后置处理器时需要实现接口:
org.springframework.beans.factory.config.BeanPostProcessor
。在初始化方法被调用前后,Spring将把每个bean实例分别传递给上述接口的以下两个方法postProcessBeforeInitialization(Object, String)
postProcessAfterInitialization(Object, String)
public class MyBeanPostProcessor implements BeanPostProcessor { @Override public Object postProcessBeforeInitialization(Object o, String s) throws BeansException { System.out.println("init初始化方法之前"); System.out.println( "o = " + o ); System.out.println( "s = " + s ); return o; } @Override public Object postProcessAfterInitialization(Object o, String s) throws BeansException { System.out.println("init初始化方法之后"); System.out.println( "o = " + o ); System.out.println( "s = " + s ); return o; } }
1.3 读取配置文件
//原始我们创建dataSource的方式
//德鲁伊的连接池对象
DruidDataSource dataSource = new DruidDataSource();
//设置驱动
dataSource.setDriverClassName( "com.mysql.jdbc.Driver" );
//设置连接地址
dataSource.setUrl( "jdbc:mysql://cdb-o6r75r3m.bj.tencentcdb.com:10015/day" );
//设置用户名
dataSource.setUsername( "root" );
//设置密码
dataSource.setPassword( "root" );
现在通过Spring来完成!注意xml文件中要引入
context名称空间
<!--
classpath: 从当前的工程的类路径下查找
classpath*: 从当前的工程路径下和当前工程依赖的工程类路径下,从当前工程和工程的jar包中查找。
-->
<!--加载配置文件-->
<context:property-placeholder location="classpath:db.properties" ></context:property-placeholder>
<!--这里使用justweb是因为db.properties配置文件里面 格式是这样的 justweb.driver=com.mysql.jdbc.Driver-->
<bean id="datasource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="${justweb.driver}"></property>
<property name="url" value="${justweb.url}"></property>
<property name="username" value="${justweb.username}"></property>
<property name="password" value="${justweb.password}"></property>
</bean>
<!--这样我们就通过Spring的 IOC容器 创建dataSource对象-->