Spring 有两种类型 bean,一种是普通 bean,另一种是工厂 bean(FactoryBean)
工厂 Bean 的实现方式:
(1)创建类,实现 FactoryBean 接口,这个类即为工厂 bean 类
(2)实现接口内的方法,在 getObject() 方法中定义返回的 bean 类型
MyBean.java
package com.mcc.spring5.factoryBean;
import org.springframework.beans.factory.FactoryBean;
public class MyBean implements FactoryBean<OtherBean> {
@Override
public OtherBean getObject() throws Exception {
return new OtherBean();
}
@Override
public Class<OtherBean> getObjectType() {
return null;
}
}
OtherBean.java
package com.mcc.spring5.factoryBean;
public class OtherBean {
}
Spring 配置文件 factoryBean.xml
配置文件中配置的是 MyBean 类型的对象,但因为 MyBean 实现了 FactoryBean 接口,因此最后得到的对象是泛型中输入的类型的对象,即 OtherBean 对象
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="myBean" class="com.mcc.spring5.factoryBean.MyBean">bean>
beans>
测试
package com.mcc.test;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.mcc.spring5.factoryBean.OtherBean;
public class TestFactoryBean {
@Test
public void testUserService() {
ApplicationContext context = new ClassPathXmlApplicationContext("factoryBean.xml");
OtherBean otherBean = context.getBean("myBean", OtherBean.class);
System.out.println(otherBean);//com.mcc.spring5.factoryBean.OtherBean@4961f6af
}
}
<bean id="myBean" class="com.mcc.spring5.factoryBean.MyBean" scope="prototype">bean>
完整的生命周期有 7 步:
(1)Bean所在类的构造器方法
(2)调用set()方法注入属性
(3)配置文件初始化之前的操作
(后置处理器 postProcessBeforeInitialization)
(4)初始化方法
(在 bean 标签中使用属性:init-method 完成)
(5)配置文件初始化之后的操作
(后置处理器 postProcessAfterInitialization)
(6)获取Bean实例
(getBean() 方法)
(7)销毁 Bean 实例方法
(在 bean 标签中使用属性:destroy-method 完成,在方法内关闭 ApplicationContext 资源时自动调用)
其中,第(3)(5)步,需要创建一个类,实现 BeanPostProcessor 接口,进而实现接口内的两个方法 postProcessBeforeInitialization()、postProcessAfterInitialization(),实现后置处理器的创建,在 xml 文件中配置该类后,该类就可以供当前 xml 文件中的所有对象使用。
后置处理器类 MyBeanProcess.java
package com.mcc.spring5.life;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
public class MyBeanProcess implements BeanPostProcessor{
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("(第五步:)配置文件初始化之后的操作");
return BeanPostProcessor.super.postProcessAfterInitialization(bean, beanName);
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("(第三步:)配置文件初始化之前的操作");
return BeanPostProcessor.super.postProcessBeforeInitialization(bean, beanName);
}
}
BeanLife.java
package com.mcc.spring5.life;
/**
* 演示 Spring 中 Bean 的生命周期
* @author MCC
*
*/
public class BeanLife {
private String name;
/**
* 无参构造器
*/
public BeanLife() {
System.out.println("第一步:Bean所在类的构造器方法");
}
public String getName() {
return name;
}
/**
* set() 方法设置属性值
*/
public void setName(String name) {
System.out.println("第二步:调用set()方法注入属性");
this.name = name;
}
/**
* 初始化方法
*/
public void init() {
System.out.println("第三步:初始化方法");
}
/**
* 销毁 Bean 实例方法
*/
public void destory() {
System.out.println("第五步:销毁 Bean 实例方法");
}
@Override
public String toString() {
return "BeanLife [name=" + name + "]";
}
}
Spring 配置文件 beanLife.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="beanLife" class="com.mcc.spring5.life.BeanLife" init-method="init" destroy-method="destory">
<property name="name" value="beanLife">property>
bean>
<bean id="myProcess" class="com.mcc.spring5.life.MyBeanProcess">bean>
beans>
测试
@Test
public void testBeanLife() {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("beanLife.xml");
BeanLife bean = context.getBean("beanLife", BeanLife.class);
System.out.println("第四步:获取Bean实例");
System.out.println(bean);
//调用配置文件中配置的销毁方法时,需要关闭context资源
context.close();
}
1、什么是自动装配?
根据指定的装配规则(属性名称或属性类型),Spring 自动将匹配到的对象作为属性进行注入。
2、实现方法:
在 bean 标签中,通过 autowire 属性实现,当值为:
(1)byName:根据名称进行查找,当属性名与 bean 标签的 id 值相同时,该对象被注入。
(2)byType:根据类型进行查找,当类型与 bean 标签的 class 类型相同时,该对象被注入,注意,若有多个相同类型的对象,则会注入失败。
Emp.java
package com.mcc.spring5.autowire;
public class Emp {
private String name;
private Dept dept;
public Dept getDept() {
return dept;
}
public void setDept(Dept dept) {
this.dept = dept;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Emp [name=" + name + ", dept=" + dept + "]";
}
}
Dept.java
package com.mcc.spring5.autowire;
public class Dept {
@Override
public String toString() {
return "Dept []";
}
}
Spring 配置文件 autowire.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="emp" class="com.mcc.spring5.autowire.Emp" autowire="byName">
<property name="name" value="emp01">property>
bean>
<bean id="dept" class="com.mcc.spring5.autowire.Dept">bean>
beans>
测试
@Test
public void testAutowire() {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("autowire.xml");
Emp emp = context.getBean("emp", Emp.class);
System.out.println(emp.toString());//Emp [name=emp01, dept=Dept []]
}
以 druid 数据库连接池为例,演示通过引入外部属性文件的方式,创建数据库连接池对象。
实现步骤:
(1)引入 druid 数据库连接池的 jar 包。
(2)创建 druid 配置文件:druid.property
(3)在 spring 配置文件中引入 context 名称空间,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/context http://www.springframework.org/schema/context/spring-context.xsd"
。
(4)在 spring 配置文件中通过
标签引入外部属性文件,该标签的 location 属性可以指定外部文件所在的位置。
<context:property-placeholder location="classpath:druid.property"/>
(5)创建 druid 对象,并通过 ${}
表达式,引入对应的值。
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="${druid.driverClassName}">property>
<property name="url" value="${druid.url}">property>
<property name="username" value="${druid.userName}">property>
<property name="password" value="${druid.password}">property>
bean>
druidOutterFile.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
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/context http://www.springframework.org/schema/context/spring-context.xsd">
<context:property-placeholder location="classpath:druid.property"/>
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="${druid.driverClassName}">property>
<property name="url" value="${druid.url}">property>
<property name="username" value="${druid.userName}">property>
<property name="password" value="${druid.password}">property>
bean>
beans>