简述创建Bean的普通方式
创建Spring config的xml配置文件,在此配置文件中对bean进行定义,如:
<!--配置Bean,目的是让spring帮我们创建java对象。一个bean标签创建一个对象
id属性:配置一个唯一的标识
class属性:设置类的全类名,spring利用反射创建对象-->
<bean id="helloWorld" class="spring.HelloWorld">
<!--设置属性值 name的值为setXXX中的XXX-->
<property name="name" value="Spring"></property>
</bean>
其中,class = "spring.HelloWorld"固定了此bean的类型为HelloWorld类型的。验证如下:
public class HelloWorldDemo {
@Test
public void testHelloWorld() {
//1、创建IOC容器对象
ClassPathXmlApplicationContext ioc = new ClassPathXmlApplicationContext("applicationContext.xml");
//2、从IOC容器中获取HelloWorldI对象
/*方式一*/
Object object = ioc.getBean("helloWorld");
System.out.println("object.getClass() = " + object.getClass());
//输出结果:object.getClass() = class spring.HelloWorld
/*方式二*/
HelloWorld helloWorld1 = ioc.getBean("helloWorld", HelloWorld.class);
System.out.println("helloWorld1.getClass() = " + helloWorld1.getClass());
//输出结果:helloWorld1.getClass() = class spring.HelloWorld
}
}
使用FactoryBean创建万能Bean
FactoryBean的源码非常简单,其中包含两个抽象方法和一个默认方法。其中getObject()方法用于获取实例,即创建bean,当xml配置文件中bean标签的class属性为FactoryBean的实现类是,使用getBean()方法获取bean时会调用该方法来创建,相当于getObject()代理了getBean();getObjectType()方法用于获取bean的类型。
package org.springframework.beans.factory;
import org.springframework.lang.Nullable;
public interface FactoryBean<T> {
String OBJECT_TYPE_ATTRIBUTE = "factoryBeanObjectType";
@Nullable
T getObject() throws Exception;
@Nullable
Class<?> getObjectType();
default boolean isSingleton() {
return true;
}
}
要想使用工厂Bean,首先就要创建一个FactoryBean接口的实现类,然后在实现类中重写的getObject()和getObjectType()方法中做文章。
创建过程
由于我们希望得到一个万能的工厂Bean,所以在实现FactoryBean接口时仍然使用泛型,并且创建此泛型的实例用于接收从xml配置文件中传递来的值,这样的话,xml配置文件中传递什么类型的值,这个泛型就会是什么类型。
本例创建了一个Book类型的Bean,并以级联的形式赋值给FactoryBeanImpl的Bean中的 t 属性。这样,FactoryBeanImpl中的泛型属性 t 就会接收到传递过来的Book类型的bean——book,然后泛型就会成为Book类型。
最后在测试类FactoryBeanImplTest中进行测试,通过ClassPathXmlApplicationContext创建ioc容器对象,然后通过ioc容器对象创建bean,其getBean()方法的第二个参数并不必须得按照xml配置文件中的类型写,比如我这里可以不用非得写FactoryBeanImpl.class(并且这样写会报BeanNotOfRequiredTypeException错,因为这样的话就会创建一个FactoryBeanImpl类型的bean,但是由于传递过来的为Book类型,两个类型不同),而是写Book.class才可以
public class FactoryBeanImpl<T> implements FactoryBean {
private T t;
public T getT() {
return t;
}
public void setT(T t) {
this.t = t;
}
public T getObject() throws Exception {
return t;
}
public Class<?> getObjectType() {
return t.getClass();
}
}
<?xml version="1.0" encoding="UTF-8"?>
<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="book" class="spring2.Book">
<property name="name" value="西游记"></property>
<property name="ID" value="1"></property>
<property name="sales" value="99"></property>
<property name="author" value="施耐庵"></property>
<property name="price" value="55.34"></property>
</bean>
<bean id="FactoryBeanImpl" class="spring4.FactoryBeanImpl">
<property name="t" ref="book"></property>
</bean>
</beans>
public class FactoryBeanImplTest {
@Test
public void Demo() throws Exception {
ClassPathXmlApplicationContext ioc = new ClassPathXmlApplicationContext("applicationContext4.xml");
/*方式一*/
Book book = ioc.getBean("beanFactoryImpl", Book.class);
/*方式二*/
Book book2 = (Book) ioc.getBean("FactoryBeanImpl");
System.out.println("beanFactory = " + book2);
//输出结果:beanFactory = Book{ID=1, name='西游记', author='施耐庵', price=55.34, sales=99}
}
}
图解