01-Spring容器基本使用及原理

01-Spring容器基本使用及原理

IOC容器

负责对象的实例化,对象的初始化,对象和对象之间依赖关系配置,对象的销毁,对外提供对象的查找,对象的整个生命周期都是由容器来控制的。当我们需要使用的时候直接从ioc容器中直接获取就可以了。

spring ioc容器时如何知道需要管理哪些对象的?

需要我们给ioc容器提供一个配置清单,这个配置支持xml格式java注解的方式,当spring容器启动时,就会加载这个配置文件,然后将这些对象给组装好以供外部访问者使用。这里所说的ioc容器也叫spring容器

Bean概念

有spring容器管理的对象统称为Bean对象

spring容器使用步骤

  1. 引入spring相关的maven配置
  2. 创建bean配置文件,比如bean xml配置文件
  3. 在bean xml文件中定义好需要spring容器管理的bean对象
  4. 创建spring容器,并给容器指定需要装载的bean配置文件,当spring容器启动之后,会加载这些配置文件,然后创建好配置文件中定义好的bean对象,将这些对象放在容器中以供使用
  5. 通过容器提供的方法获取容器中的对象,然后使用

spring容器对象

spring内部提供了很多表示spring容器的接口和对象,我们来看看比较常见的几个容器接口和具体实现类

Bean Factory接口

spring容器的顶层接口,提供了最基本的功能

常见的几个方法

//按bean的id或者别名查找容器中的bean
Object getBean(String name) throws BeansException

//这个是一个泛型方法,按照bean的id或者别名查找指定类型的bean,返回指定类型的bean对象
<T> T getBean(String name, Class<T> requiredType) throws BeansException;

//返回容器中指定类型的bean对象
<T> T getBean(Class<T> requiredType) throws BeansException;

//获取指定类型bean对象的获取器,这个方法比较特别,以后会专门来讲
<T> ObjectProvider<T> getBeanProvider(Class<T> requiredType);

ApplicationContext接口

继承了Bean Factory接口,内部包含了Bean Factory所有的功能,并且在其上进行了扩展,增加了很多企业级功能:aop,国际化,事件支持等等。

ClassPathXmlApplicationContext类

实现了ApplicationContext接口,可以看出这个类容器可以从class path中加载bean.xml配置文件,然后创建xml中配置的bean对象

AnnotationConfigApplicationContext类

同样实现了ApplicationContext接口,当我们使用的方式定义bean的时候,就需要用到这个容器来装载,这个容器内部会解析注解来构建和管理需要的bean

创建bean实例这些方法

通过反射调用构造方法创建对象

调用类的构造方法获取对应的bean实例,是使用最多的方式,这种方式只需要在xml bean元素中指定class属性,spring容器内部会自动调用该类型的构造方法来创建bean对象,将其放在容器中以供使用。

通过静态代码工厂创建bean

我们可以创建静态工厂,内部提供一些静态方法来生成所需要的对象,将这些静态方法创建的对象交由spring以供使用

<bean id="bean名称" name="" class="静态工厂完整类名" factory-method="静态工厂的方法">
    <constructor-arg index="0" value="bean的值" ref="引用的bean名称" />
    <constructor-arg index="1" value="bean的值" ref="引用的bean名称" />
    <constructor-arg index="2" value="bean的值" ref="引用的bean名称" />
    ....
    <constructor-arg index="n" value="bean的值" ref="引用的bean名称" />
</bean>

自定义一个静态工厂

public class UserStaticFactory {

    /**
     * 静态无参方法创建UserModel
     *
     * @return
     */
    public static UserModel buildUser1() {

        System.out.println(UserStaticFactory.class + ".buildUser1()");

        UserModel userModel = new UserModel();
        userModel.setName("我是无参静态构造方法创建的!");
        return userModel;
    }

    /**
     * 静态有参方法创建UserModel
     *
     * @param name 名称
     * @param age  年龄
     * @return
     */
    public static UserModel buildUser2(String name, int age) {

        System.out.println(UserStaticFactory.class + ".buildUser2()");

        UserModel userModel = new UserModel();
        userModel.setName(name);
        userModel.setAge(age);
        return userModel;
    }

bean.xml配置

<!-- 通过工厂静态无参方法创建bean对象 -->
<bean id="createBeanByStaticFactoryMethod1" class="com.javacode2018.lesson001.demo3.UserStaticFactory"
      factory-method="buildUser1"/>

<!-- 通过工厂静态有参方法创建bean对象 -->
<bean id="createBeanByStaticFactoryMethod2" class="com.javacode2018.lesson001.demo3.UserStaticFactory"
      factory-method="buildUser2">
    <constructor-arg index="0" value="通过工厂静态有参方法创建UerModel实例对象"/>
    <constructor-arg index="1" value="30"/>
</bean>

通过实例工厂方法创建bean对象

让spring容器去调用某些对象的某些实例方法来生成bean对象放在容器中以供使用。

<bean id="bean名称" factory-bean="需要调用的实例对象bean名称" factory-method="bean对象中的方法">
    <constructor-arg index="0" value="bean的值" ref="引用的bean名称" />
    <constructor-arg index="1" value="bean的值" ref="引用的bean名称" />
    <constructor-arg index="2" value="bean的值" ref="引用的bean名称" />
    ....
    <constructor-arg index="n" value="bean的值" ref="引用的bean名称" />
</bean>

spring容器以factory-bean的值为bean名称查找对应的bean对象,然后调用该对象中factory-method属性值指定的方法,将这个方法返回的对象作为当前bean对象放在容器中供使用。

自定义一个实例工厂

public class UserFactory {
    public UserModel buildUser1() {
        System.out.println("----------------------1");
        UserModel userModel = new UserModel();
        userModel.setName("bean实例方法创建的对象!");
        return userModel;
    }

    public UserModel buildUser2(String name, int age) {
        System.out.println("----------------------2");
        UserModel userModel = new UserModel();
        userModel.setName(name);
        userModel.setAge(age);
        return userModel;
    }
}

bean.xml

<!-- 定义一个工厂实例 要先将实例工厂对象添加到spring容器中-->
<bean id="userFactory" class="com.javacode2018.lesson001.demo3.UserFactory"/>
<!-- 通过userFactory实例的无参user方法创建UserModel对象 -->
<bean id="createBeanByBeanMethod1" factory-bean="userFactory" factory-method="buildUser1"/>

<!-- 通过userFactory实例的有参user方法创建UserModel对象 -->
<bean id="createBeanByBeanMethod2" factory-bean="userFactory" factory-method="buildUser2">
    <constructor-arg index="0" value="通过bean实例有参方法创建UserModel实例对象"/>
    <constructor-arg index="1" value="30"/>
</bean>

通过FactoryBean来创建bean对象

BeanFactory是spring容器的顶层接口,而这里要说的是FactoryBean,也是一个接口,FactoryBean可以让spring容器通过这个接口的实现来创建我们需要的bean对象

FactoryBean接口源码:

public interface FactoryBean<T> {

    /**
     * 返回创建好的对象
     */
    @Nullable
    T getObject() throws Exception;

    /**
     * 返回需要创建的对象的类型
     */
    @Nullable
    Class<?> getObjectType();

    /**
    * bean是否是单例的
    **/
    default boolean isSingleton() {
        return true;
    }

}

接口中有3个方法,前面2个方法需要我们去实现,getObject方法内部由开发者自己去实现对象的创建,然后将创建好的对象返回给Spring容器,getObjectType需要指定我们创建的bean的类型;最后一个方法isSingleton表示通过这个接口创建的对象是否是单例的,如果返回false,那么每次从容器中获取对象的时候都会调用这个接口的getObject() 去生成bean对象。

案例

创建一个FactoryBean实现类

public class UserFactoryBean implements FactoryBean<UserModel> {
    int count = 1;
    @Nullable
    @Override
    public UserModel getObject() throws Exception { //@1
        UserModel userModel = new UserModel();
        userModel.setName("我是通过FactoryBean创建的第"+count+++ "对象");//@4
        return userModel;
    }

    @Nullable
    @Override
    public Class<?> getObjectType() {
        return UserModel.class; //@2
    }

    @Override
    public boolean isSingleton() { 
        return true; //@3
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值