Spring的核心原理

一、IOC容器的运行原理

  • 容器:Spring容器是整个核心的载体(如BeanFactory和ApplicationContext)像一个超级工厂负责(既Bean)的创建、管理形成一套生命周期

  • IOC反转控制:IOC本质是一种思想,是根据依赖倒置原则(DIP)来实现的一种规则,其核心是通过对象的创建和依赖关系,将控制权从应用程序代码转移到容器,实现模块间的解耦。

  • 依赖注入(DI):依赖注入是IOC的核心实现手段

补充:

DIP原则:高层模块不直接依赖低层模块,二者均依赖抽象(接口/抽象类)。抽象不依赖细节,细节依赖抽象。

解决痛点:

将所有的创建都交给工厂统一管理,而非开发者手动创建,让开发者将重心更倾向于业务代码上

二、Spring IoC 容器定义 XML 配置文件
以下是创建容器配置文件的几种方式
实现类

<bean id="userService" class="org.nf.service.impl.UserServiceImpl"></bean>
  • id:表示bean在容器中的唯一标识,在获取bean时是根据id来获取
  • class:Bean的完整类名,通过反射创建实例后纳入容器中管理

引言

以上得知bean标签的是通过class属性读取实现类,从而进行让Spring容器接管,那我们是不是也可以将自定义的工厂容器也一并交给Spring容器进行管理

业务接口如下:

public interface UserService {
    /**
     * 添加用户
     */
    void add();
}

前提条件是要给实现类引入接口,例子如下:

public class UserServiceImpl implements UserService {
    @Override
    public void add() {
        System.out.println("添加用户");
    }
}

容器的配置文件如下:

1.装配自定义工厂
自定义工厂如下:

public class PeopleServiceFactory {
    public UserService create(){
        //创建出来的对象也一并会纳入容器中管理
        return new PeopleServiceImpl();
    }
}
  <bean id="peopleServiceFactory" class="org.nf.factory.PeopleServiceFactory"></bean>
    <!--装配peoleService对象,注意:这个对象是通过自定义工厂创建出来的
        factory-bean:自定义工厂的id
        factory-method:自定义工厂的创建方法-->
  <bean id="peopleService" factory-bean="peopleServiceFactory" factory-method="create"></bean>

Spring同样将这个工厂视为Bean来管理,也就是所谓的(FactoryBean)

2.装配静态工厂
自定义静态工厂如下:

public class StudentServiceFactory {
    public static UserService create(){
        return new StudentServiceImpl();
    }
}
 <bean id="studentService" class="org.nf.factory.StudentServiceFactory" factory-method="create"></bean>

目的是将创建出来的对象纳入容器中,而工厂本身不托管。
为什么说工厂本身不托管,因为通过静态方法是可以通过类名直接调用属于类别,从而不需要容器托管

3.基于FactoryBean来创建受管的Bean对象

public class TeacherServiceFactoryBean implements FactoryBean<UserService> {

    /**
     * 工厂方法,将创建的对象纳入容器管理
     * @return
     * @throws Exception
     */
    @Override
    public UserService getObject() throws Exception {
        return new TeacherServiceImpl();
    }

    /**
     * Bean的class类型
     * @return
     */
    @Override
    public Class<?> getObjectType() {
        return TeacherServiceImpl.class;
    }

    /**
     * 是否是以单例来管理(默认就是单例模式)
     * @return
     */
    @Override
    public boolean isSingleton(){
        return true;
    }
}

自定义FactoryBean对象,必须实现Spring提供的FactoryBean接口

 <!--3.基于FactoryBean来创建受管的Bean对象-->
  <bean id="teacherService" class="org.nf.factory.TeacherServiceFactoryBean"></bean>

Bean的作用域
Bean的作用域可以通过scope属性指定值如下:
singleton(默认项):单例,容器唯一保存的实例
prototype:原型,每次从容器中获取都会重新实例一次

容器配置文件xml如下:

 <bean id="userService" class="org.nf.service.impl.UserServiceImpl" scope="prototype"></bean>

测试类如下:

  ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
   UserService s1 = context.getBean(UserService.class);
   UserService s2 = context.getBean(UserService.class);
   System.out.println(s1);
   System.out.println(s2);

通过输出的地址值即可知道两者区别,毋容置疑两者地址值相同则是从容器中拿出的唯一实例,后者相反。

引言

  • 在容器底层中Bean标签的相应属性值是由Map集合保存如key保存唯一标识id,value则是存储组件实例。
  • 而不同作用域存储的Map也截然不同

单例原理解析如下:

Map<String, Object> singleTon = new HashMap<>();
Object object = clazz.getConstructor() .newInstance();
singleTon.put("userService", object);

从value的类型可知存储的是创建好的实例

原型原理解析如下:

Map<String, Class<?>> prototypeMap = new HashMap<>();
prototypeMap.put("userService", clazz);
Class<?> beanClass = prototypeMap.get("userService");
beanClass.getConstructor().newInstance();

Class<?>是一个泛型类型,可接收任意类的 Class ,而Map的值中存储的是按需创建类的Class,从而通过类来重新实例

来源链接:https://www.cnblogs.com/Mr-Keep/p/18849214

© 版权声明
THE END
支持一下吧
点赞6 分享
评论 抢沙发
头像
请文明发言!
提交
头像

昵称

取消
昵称表情代码快捷回复

    暂无评论内容