欢迎访问悦橙教程(wld5.com),关注java教程。悦橙教程  java问答|  每日更新
页面导航 : > > 文章正文

Spring IOC 复习,

来源: javaer 分享于  点击 22340 次 点评:244

Spring IOC 复习,


Inversion of Control

将创建对象的权利交给框架,包括DI(Dependency Injection,依赖注入)和DL(Dependency Lookup,依赖查找),能削减计算机程序的耦合,即解除代码中的依赖关系

应用

xml

<bean id="bean的唯一标识(名字)" class="全限定类名"></bean>
<bean id="beanId" factory-bean="工厂类的全限定类名" factory-method="方法名"></bean> 
<bean id="beanId" class="全限定类名" factory-method="方法名"></bean>

bean标签还有两个属性init-method和destroy-method指定构造方法和销毁方法

  • 依赖注入

    在bean中需要的数据或其他类的对象都由spring提供,只需配置,但不适合注入常变的数据

    能注入的数据有三类:基本类型和String,其他bean,复杂类型/集合类型

    注入方式有三种,在bean标签内用一个标签代表一个参数:

    构造函数注入

    <constructor-arg type(不常)="类型的全限定名" index(不常)="参数序号,从0开始" name(常用)="参数名" value="基本类型值" ref="引用其他bean"></constructor-arg>

    ​ 优:获取bean对象时注入数据是必须的,否则无法创建成功

    ​ 弊:改变了bean的实例化方式,在创建对象时如果用不到这些数据也必须提供

    set方法注入(常用)

    <property name="set方法对应名" value="基本类型值" ref="其他bean"></property>

    ​ 优:创建对象时没有明确的限制,可以直接使用默认构造函数

    ​ 弊:set方法可能不执行,如果某个成员必须有值,此方法不能保证

    复杂类型的注入需要在参数标签中再加标签array,list,set,map,props

    <property name="listPropName">
        <array>
            <value>...</value>
            ...
        </array>
    </property>
    <property name="mapPropName">
        <map>
            <entry key="keyName" value="值"></entry>
            <entry key="keyName">
                <value>值</value>
            </entry>
        </map>
    </property>

    ​ List结构的用list,array,set都一样,Map结构的用map,props都一样

  • 获取bean,在java代码中

    //获取核心容器对象,也可以用BeanFactory代替ApplicationContext
    ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
    //根据id获取Bean对象
    ClassOfBean bean = (ClassOfBean)ac.getBean("beanId");
    • ApplicationContext的三个常用实现类

    ​ ClassPathXmlApplicationContext: 可以加载类路径下的配置文件

    ​ FileSystemXmlApplicationContext: 可以加载磁盘任意路径(有访问权限)下的配置文件

    ​ AnnotationConfigApplicationContext: 用于读取注解创建容器

    • ApplicationContext和BeanFactory的区别

    ​ 前者在构建容器时采用立即加载的方式,一读取完配置文件就马上创建bean

    ​ 后者在构建窗口时采用延迟加载的方式,当获取bean时才真正创建对象

  • 注解

    用xml文件 bean.xml文件中的约束的标签为

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="
            http://www.springframework.org/schema/beans 
    http://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
        <!-- 告知spring在创建容器时要扫描的包 -->
        <context:component-scan base-package="包路径"></context:component-scan>
    </beans>

    不用xml文件

    创建一个配置类,类上加

    @Configuration指定当前类是一个配置类,获取容器时作为参数传入的配置类可以不加

    @ComponentScan(basePackages="包路径")指定要扫描的包,basePackages可以换成value

    ​ 获取容器时用new AnnotationConfigApplicationContext(配置类.class)

    @Import 导入其他配置类,被导入的类不用再加@Configuration

    @PropertySource("classpath:路径/文件名") 用指定properties文件的位置,属性value

    @PropertySources 有多个properties文件的时候用

    ​ 导入配置文件后可以用@Value(${...})读取

    与bean有关的注解
    • @Bean 用于将当前方法的返回值作为bean存入ioc容器中,属性name指定beanId默认值为当前方法的名称,如果方法有参数,spring框架会去容器中查找 有没有可用的bean对象,查找方式同Autowired

    • 用于创建对象的,相当于bean标签

      @Component 作用:把当前对象存入spring容器中;属性:value:指定bean的id,默认是当前类名且首字母小写;@Controller @Service @Repository与@Component完全一样,体现三层架构

    • 用于注入数据的,相当于property标签

      @Autowired 作用:自动按照类型注入,如果容器中有唯一一个类匹配该数据的类型则注入,若没有匹配类型则报错,如果有多个则通过变量名寻找beanId对应的那个bean注入;位置:类上,方法上,变量上

      @Qualifier 作用:在按照类型注入的基础上再按照名称注入,在给类成员注入时不能单独使用必须和@Autowired一起,但在给方法参数注入时可以;属性:value用于指定beanId

      以上三种只能注入bean,不基本类型和String,复杂类型必须用xml配置

      @Value 作用:用于注入基本类型和String;属性:value用于指定数据的值,可以使用SpEL(spring的EL表达式:${表达式})

      @Resource 作用:直接按照bean的id注入,可以独立使用;属性:name指定beanId

    • 用于改变作用范围的,相当于bean标签的scope属性

      @Scope 作用:指定bean的作用范围;属性:value一般取singleton(默认)或prototype

    • 和生命周期相关的,相当于bean标签的init-method和destroy-method属性(不常用)

      @PostConstruct

      @PreDestroy


    与Junit整合

    常见问题

    • bean的作用范围

      ​ bean标签和@Component注解的scope属性:用于指定bean的作用范围

      ​ 取值:singleton 单例的(常用)

      ​ prototype 多例的(常用)

      ​ request 作用于web应用的请求范围

      ​ session 作用于web应用的会话范围

      ​ global-session 集群环境的会话范围(全局会话范围),若不是集群环境,则为session

    • bean的生命周期

      ​ singleton: 容器创建时对象创建(ApplicationContext),容器销毁时对象销毁

      ​ prototype: 使用对象时创建对象,当对象长时间不用且长时间没有别的对象引用时,由java的垃圾回收器回收


    原理

    • ioc只需要导入spring-context依赖

    • 阅读源码:github下载源码,导入idea,运行调试加注释

    • spring项目启动后,会扫描所有类,找到符合bean标准(加注释或xml配置)的类,通过一个描述类(BeanDefinition)存放bean的信息,isSingleton属性默认为true,再将描述类存入一个map(BeanDefinationMap)中

    • 扫描之后bean的获取:通过BeanDefinationMap里的key(bean名)找到value(BeanDefination)的class属性进行反射,找到bean对应的类。与class名没有关系,可以通过自己实现BeanFactory接口,从beanFactory中获取描述类BeanDefinition,setBeanClass(another.class)将bean和class的对应关系更改

    • 扫描前BeanDefinationMap中已有7个bean,包括AppConfig

    • main() --> AnnotationConfigApplicationContext(AppConfig.class) --> refresh() --> invokeBeanFactoryPostProcessors(beanFactory)(扫描并存入bean)

    • 后置处理器BeanPostProcessors的子类会被自动扫描并对bean进行多层代理,默认有九次(进入依赖注入等操作),实现此接口可以对bean的创建过程进行干预

    • Spring上下文或环境:为了实现IOC或AOP所需要的各种Spring组件的集合,如BeanDefination,BeanPostProcessor(后置处理器),DefaultListableBeanFactory,BeanDefinitionMap,单例池等等

    • 扫描只是将bean对应的类的信息存入map中,并不会实例化类,即lazy(懒加载)

    • factoryBean是一个特殊的bean,beanFactory是bean工厂

    • 单例bean第一次被实例化后就会存入名为singleObjects的map(单例池)中,再次getBean()时就不会new,(保证单例)

    • Spring容器:不止单例池,还包括其他IOC组件

    • 循环依赖:

      单例bean的循环依赖

      isSingletonCurrentlyInCreation判断这个bean是否在创建过程中

      单例池只存放完整的bean

      get(A) --> new A --> auto B --> get(B) --> new B --> auto A --> get(A)

      获取A,新建A,发现A需要注入B且单例池中没有B且B不在创建过程中,获取B,发现B需要注入A且单例池中没有A且A正在创建过程中,获取A并注入B,将B注入A,将A放入单例池

    相关文章

      暂无相关文章
    相关栏目:

    用户点评