Spring | IOC技术之Bean的配置与实例化

博主简介

  1. 获取这个Bean并调用它的方法
/** * @author BoBooY */public class App {    public static void main(String[] args) {        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");        BookDao dao = (BookDao)applicationContext.getBean("dao");        BookDao bookDaoImpl = (BookDao)applicationContext.getBean("bookDaoImpl");        dao.save();        bookDaoImpl.save();    }}
  1. 查看控制台结果

可以看到通过这个两个别名都可以获取到这个Bean

注意:

  • bean依赖注入的 ref 属性指定bean,必须在容器中存在,ref的属性值,也可也是另一个bean的name属性值,不过还是建议使用其id来进行注入

  • 如果id不存在,在获取时会获取不到,然后就会报错:NoSuchBeanDefinitionException

3、scope属性

  • singleton:单例(默认)
  • prototype:非单例
<bean id="bookDao" class="com.bby.dao.bookDaoImpl" scope="prototype"/>

分别获取单例模式和多例模式下的bean

  • 单例模式如下(singleton):

  • 非单例模式如下(prototype):


思考:

  • 为什么bean默认为单例" />

    从这里可以看出:Spring容器在创建对象的时候也走的是构造函数

    1. 将构造函数改成private测试
    /** * @author BoBooY */public class BookDaoImpl implements BookDao {    private BookDaoImpl() {        System.out.println("book dao constructor is running ....");    }    public void save() {        System.out.println("book dao save ...");    }}

    查看控制台结果:

    从这里可以看出:Spring内部走的依然是构造函数,能访问到类中的私有构造方法,显而易见Spring底层用的是反射

    1. 使用带参构造方法测试
    /** * @author BoBooY */public class BookDaoImpl implements BookDao {    private BookDaoImpl(int a) {        System.out.println("book dao constructor is running ....");    }    public void save() {        System.out.println("book dao save ...");    }}

    查看控制台结果:

    程序会报错,说明Spring底层使用的是类的无参构造方法。

    Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.bby.dao.BookDaoImpl]: No default constructor found; nested exception is java.lang.NoSuchMethodException: com.bby.dao.BookDaoImpl.()

    译:()指定是类的构造方法,即该类的无参构造方法

    • Caused by: 引发
    • BeanInstantiationException:翻译为bean实例化异常
    • No default constructor found:没有一个默认的构造函数被发现

    2、静态工厂实例化

    1. 准备一个OrderDao和OrderDaoImpl类

      public interface OrderDao {    public void save();}
      public class OrderDaoImpl implements OrderDao {    public void save() {        System.out.println("order dao save ...");    }}
    2. 创建一个工厂类OrderDaoFactory并提供一个静态方法

      //工厂类public class OrderDaoFactory {    public static OrderDao getOrderDao(){        return new OrderDaoImpl();    }}
    3. 在spring的配置文件applicationContext.xml中添加以下内容

      <bean id="orderDao" class="com.bby.factory.OrderDaoFactory" factory-method="getOrderDao"/>
      • class:工厂类的类全名
      • factory-mehod:具体工厂类中创建对象的方法名
    4. 获取Bean测试

      public class App {    public static void main(String[] args) {        ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");        OrderDao orderDao = (OrderDao) ctx.getBean("orderDao");        orderDao.save();    }}

    3、实例工厂实例化

    1. 创建一个工厂类OrderDaoFactory2并提供一个普通方法,注意此处和静态工厂的工厂类不一样的地方是方法不是静态方法

      //实例工厂public class OrderDaoFactory2 {    public OrderDao getOrderDao(){        return new OrderDaoImplava    }}
    2. 在spring的配置文件中添加以下内容

      <bean id="orderDaoFactory2" class="com.bby.factory.OrderDaoFactory2"/><bean id="orderDao" factory-method="getOrderDao" factory-bean="orderDaoFactory2"/>
      • factory-bean:工厂的实例对象

      • factory-method:工厂对象中的具体创建对象的方法名

    3. 获取Bean进行测试

      /** * @author BoBooY */public class App {    public static void main(String[] args) {        ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");        OrderDao orderDao = (OrderDao) ctx.getBean("orderDao2");        orderDao.save();    }}

    实例化工厂运行的顺序是:

    • 创建实例化工厂对象,对应的是第一行配置

    • 调用对象中的方法来创建bean

    FactoryBean的使用

    实例工厂实例化的方式配置的过程还是比较复杂,所以Spring为了简化这种配置方式就提供了一种叫FactoryBean的方式来简化开发。

    1. 创建一个OrderDaoFactoryBean的类,实现FactoryBean接口,重写接口的方法

      /** * @author BoBooY */public class OrderDaoFactoryBean implements FactoryBean<OrderDao> {    //代替原始实例工厂中创建对象的方法    public OrderDao getObject() throws Exception {        return new OrderDaoImpl();    }    //返回所创建类的Class对象    public Class<" />


      查看源码会发现,FactoryBean接口其实会有三个方法,分别是:

      T getObject() throws Exception;Class<?> getObjectType();default boolean isSingleton() {return true;}
      • getObject():被重写后,在方法中进行对象的创建并返回
      • getObjectType():被重写后,主要返回的是被创建类的Class对象
      • isSingleton:没有被重写,因为它已经给了默认值,从方法名中可以看出其作用是设置对象是否为单例,默认true

      尾言:创作不易,如果本文的内容对您有帮助,还望客官可以支持一下博主,(点赞)+✏️(评论)+⭐️(收藏)是我创作的巨大动力!

THE END
分享
二维码
< <上一篇
下一篇>>