编写一个Bean类 SpringBean.java
package com.powernode.spring6.bean;
/**
* @author Bonbons
* @version 1.0
*/
public class SpringBean {
}
编写我们的配置文件 spring.xml
<!--
Bean对象实例化方法一: 通过声明bean,给出全限定类名,spring会自动调用该bean的无参构造方法来实例化Bean
-->
<bean id="sb" class="com.powernode.spring6.bean.SpringBean"/>
编写测试方法 SpringBeanTest.java
@Test
public void testInstantiation1(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
SpringBean sb = applicationContext.getBean("sb", SpringBean.class);
System.out.println(sb);
}
编写我们的测试类 Gun.java
package com.powernode.spring6.bean;
/**
* @author Bonbons
* @version 1.0
*/
public class Star {
public Star() {
System.out.println("调用了Star的无参构造方法。");
}
}
编写我们的简单工厂类 StarFactory.java
package com.powernode.spring6.bean;
/**
* @author Bonbons
* @version 1.0
*/
public class StarFactory {
// 在简单工厂中,通过静态方法获取我们的产品对象
public static Star get(){
return new Star();
}
}
编写我们的配置文件
<!--方法二:通过简单工厂模式实例化Bean
我们需要指定使用哪个工厂,指定调用工厂的哪个静态方法获取Bean
这个Bean实际还是自己 new 的,只不过是通过Spring的bean来获取
底层还是调用的构造方法,只是外在的展示形式不同
-->
<bean id="starBean" class="com.powernode.spring6.bean.StarFactory" factory-method="get" />
编写我们的测试方法
@Test
public void testInstantiation2(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
Star star = applicationContext.getBean("starBean", Star.class);
System.out.println(star);
}

编写我们的 Gun.java
package com.powernode.spring6.bean;
/**
* 具体产品角色
* @author Bonbons
* @version 1.0
*/
public class Gun {
public Gun() {
System.out.println("调用了Gun的无参构造方法。");
}
}
编写我们的工厂方法类 GunFactory.java
package com.powernode.spring6.bean;
/**
* 具体工厂角色
* @author Bonbons
* @version 1.0
*/
public class GunFactory {
// 方法是实例的 >> 需要创建对象才能调用
public Gun get(){
return new Gun();
}
}
配置我们的 bean
<!--
方法三:通过工厂方法模式实例化Bean
因为需要创建工厂的Bean,
通过 factory-bean 属性告诉Spring使用哪个工厂的对象,
然后通过 factory-method告诉Spring调用哪个方法获取Bean
-->
<bean id="factory" class="com.powernode.spring6.bean.GunFactory" />
<bean id="gunBean" factory-bean="factory" factory-method="get"/>
编写测试方法:
@Test
public void testInstantiation3(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
Gun gun = applicationContext.getBean("gunBean", Gun.class);
System.out.println(gun);
}

定义我们的具体角色类 Person.java
package com.powernode.spring6.bean;
/**
* @author Bonbons
* @version 1.0
*/
public class Person {
public Person() {
System.out.println("调用了Person的无参构造方法。");
}
}
定义我们的具体工厂类 PersonFactory.java
package com.powernode.spring6.bean;
import org.springframework.beans.factory.FactoryBean;
/**
* 工厂Bean >> 可以获得普通Bean
* @author Bonbons
* @version 1.0
*/
public class PersonFactoryBean implements FactoryBean<Person> {
@Override
public Person getObject() throws Exception {
// 获取我们的Bean对象
return new Person();
}
@Override
public Class<?> getObjectType() {
return null;
}
@Override
public boolean isSingleton() {
// 在接口中就实现了这个方法,默认为 true >> 单例
return FactoryBean.super.isSingleton();
}
}
编写配置文件
<!--
方法四:通过FactoryBean接口来实例化我们的Bean
属于方法三的简化形式,我们的工厂方法模式实现了这个接口,在配置的时候就不需要
指定factory-bean、factory-bean两个属性
直接通过创建工厂Bean就能直接返回一个具体的普通Bean的对象
-->
<bean id="person" class="com.powernode.spring6.bean.PersonFactoryBean" />
编写我们的测试文件
@Test
public void testInstantiation4(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
Person person = applicationContext.getBean("person", Person.class);
System.out.println(person);
}

BeanFactory
FactoryBean
在Spring中,Bean可以分为两类:
编写我们的普通角色类 Person.java
package com.powernode.spring6.bean;
package com.powernode.spring6.bean;
import java.util.Date;
/**
* @author Bonbons
* @version 1.0
*/
public class Student {
// 为了演示如何注入Date类型 >> 定义一个私有日期类型的birth
private Date birth;
public void setBirth(Date birth) {
this.birth = birth;
}
@Override
public String toString() {
return "Student{" +
"birth=" + birth +
'}';
}
}
编写我们的工厂类 DateFactory.java
package com.powernode.spring6.bean;
import org.springframework.beans.factory.FactoryBean;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* 使用工厂类获取我们的日期对象
* @author Bonbons
* @version 1.0
*/
public class DataFactoryBean implements FactoryBean<Date> {
// 通过构造方法传递我们要生成的日期
private final String strDate;
public DataFactoryBean(String srtDate) {
this.strDate = srtDate;
}
@Override
public Date getObject() throws Exception {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
// 格式化我们的日期字符串
return sdf.parse(strDate);
}
@Override
public Class<?> getObjectType() {
return null;
}
}
编写我们配置文件
<bean id="date" class="com.powernode.spring6.bean.DataFactoryBean">
<!--通过它的构造方法传递我们的日期字符串-->
<constructor-arg index="0" value="2022-11-15" />
</bean>
<bean id="student2" class="com.powernode.spring6.bean.Student">
<property name="birth" ref="date" />
</bean>
编写我们测试方法
@Test
public void testStudent2(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
Student student2 = applicationContext.getBean("student2", Student.class);
System.out.println(student2);
}

可以看到我们输入的日期还是那个格式,只是通过工厂类把输入日期的格式变成了我们习惯的格式。
🌔 1、什么是Bean的生命周期?
🌔 2、那么一个Bean的一个完整生命周期都包括哪些部分?
编写我们的 User 类,我们通过User类演示Bean的这五步生命周期
package com.powernode.spring6.bean;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.*;
/**
* Bean的生命周期被分为五步的情况
* @author Bonbons
* @version 1.0
*/
public class User implements BeanNameAware, BeanClassLoaderAware, BeanFactoryAware, InitializingBean, DisposableBean {
public User(){
System.out.println("第一步,无参构造方法被调用");
}
private String name;
public void setName(String name) {
System.out.println("第二步,set方法被调用 >> 属性赋值");
this.name = name;
}
// 让我们的User类去实现这三个接口 >> 用于在执行Bean后处理器的before方法之前调用
public void initBean(){
System.out.println("第三步,初始化Bean");
}
public void destroyBean(){
System.out.println("第五步,销毁Bean");
}
}
在配置文件中声明一下我们的Bean
<!--将bean的生命周期分为五步:需要配置我们的初始化方法和销毁方法-->
<bean id="user" class="com.powernode.spring6.bean.User" init-method="initBean" destroy-method="destroyBean">
<property name="name" value="白居易" />
</bean>
编写我们的测试方法
@Test
public void testBeanLifecycleFive(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
User user = applicationContext.getBean("user", User.class);
System.out.println("第四步,使用Bean" + user);
// 需要我们手动销毁Bean,但是这个方法属于ClassPathXMLApplicationContext的,所以我们需要强转
ClassPathXmlApplicationContext context = (ClassPathXmlApplicationContext) applicationContext;
context.close();
}

编写我们的Bean后处理器:LogBeanPostProcessor
package com.powernode.spring6.bean;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.lang.Nullable;
/**
* 日志Bean后处理器 >> 用来演示初始化前后插入代码的
* @author Bonbons
* @version 1.0
*/
public class LogBeanPostProcessor implements BeanPostProcessor {
// bean 我们的bean对象、beanName 我们bean的名字
@Nullable
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("执行Bean后处理器的before方法");
return bean;
}
@Nullable
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("执行Bean后处理器的after方法");
return bean;
}
}
在配置文件中配置我们的Bean后处理器
<!--配置Bean后处理器,作用范围是整个配置文件-->
<bean class="com.powernode.spring6.bean.LogBeanPostProcessor" />
测试方法我们依旧使用我们上面五步生命周期的测试方法 >> 我们可以很清楚的看到生命周期变成了七步

让我们User类实现这五个接口 【第一种三个、第二种一个、第三种一个】
package com.powernode.spring6.bean;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.*;
/**
* Bean的生命周期被分为五步的情况
* @author Bonbons
* @version 1.0
*/
public class User implements BeanNameAware, BeanClassLoaderAware, BeanFactoryAware, InitializingBean, DisposableBean{
public User(){
System.out.println("第一步,无参构造方法被调用");
}
private String name;
public void setName(String name) {
System.out.println("第二步,set方法被调用 >> 属性赋值");
this.name = name;
}
// 让我们的User类去实现这三个接口 >> 用于在执行Bean后处理器的before方法之前调用
public void initBean(){
System.out.println("第三步,初始化Bean");
}
public void destroyBean(){
System.out.println("第五步,销毁Bean");
}
@Override
public void setBeanClassLoader(ClassLoader classLoader) {
System.out.println("传递了类加载器" + classLoader);
}
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
System.out.println("传递了创建这个Bean的工厂" + beanFactory);
}
@Override
public void setBeanName(String s) {
System.out.println("传递了Bean的名字" + s);
}
@Override
public void destroy() throws Exception {
System.out.println("DisposableBean's destroy method");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("InitializingBean's afterPropertiesSet method");
}
}
配置文件、测试文件都不需要改变

scope = prototype,那么spring的工作内容只负责到使用Bean,之后的工作内容交给我们的客户端<!--将bean的生命周期分为五步:需要配置我们的初始化方法和销毁方法-->
<bean id="user" class="com.powernode.spring6.bean.User" init-method="initBean" destroy-method="destroyBean" scope="prototype">
<property name="name" value="白居易" />
</bean>
执行测试方法 >> Spring在完成Bean对象初始化之后,就不再追踪其生命周期了

编写我们的Student类
package com.powernode.spring6.bean;
/**
* @author Bonbons
* @version 1.0
*/
public class Student {
}
编写我们的测试方法:
@Test
public void testRegisterBean(){
// 我们自己创建一个对象
Student student = new Student();
System.out.println(student);
// 创建一个可以将对象加入到Bean中的工厂
DefaultListableBeanFactory defaultListableBeanFactory = new DefaultListableBeanFactory();
defaultListableBeanFactory.registerSingleton("studentBean", student);
// 通过getBean方法获取我们的Bean
Student studentBean = defaultListableBeanFactory.getBean("studentBean", Student.class);
System.out.println(studentBean);
}
通过测试结果我们可以得出结论 >> 注入我们自己new的对象成功
