spring(二)基础

965 阅读9分钟

基于XML的使用

IoC配置

在spring的XML文件中通过一个bean标签,完成IoC的配置。

bean标签介绍

  • bean标签作用: 用于配置被spring容器管理的bean的信息。默认情况下它调用的是类中的【无参构造函数】,如果没有无参构造函数则不能创建成功。

  • bean标签属性

    • id:给对象在容器中提供一个唯一标识,用于获取对象。

    • class:指定类的全限定名,用于反射创建对象,默认情况下调用无参构造函数。

    • init-method:指定类中的创始化方法名称。

    • destroy-method:指定类中销毁方法名称,比如DataSource的配置中一般需要指定destroy-method="close"

    • scope:指定对象的作用范围。

      • singleton:默认值,单例的(在整个容器中只有一个对象),生命周期如下:

        • 对象出生:当应用加载,创建容器时,对象就被创建了。
        • 对象活着:只要容器在,对象就一直活着。
        • 对象死亡:当应用卸载,销毁容器时,对象就被销毁了。
      • prototype:多例的,每次访问对象时,都会重新创建对象实例,生命周期如下:

        • 对象出生:当使用对象时,创建新的对象实例。
        • 对象活着:只要对象在使用中,就一直活着。
        • 对象死亡:当对象长时间不用时,被Java的垃圾回收器回收了。
      • request:将spring创建的Bean对象存入request域中。

      • session:将spring创建的Bean对象存入session域中。

      • global session:WEB项目中,应用在Protlet环境,如果没有Protlet环境那么globalSession相当于session。

bean实例化的三种方式

  • 第一种:使用默认无参构造函数(重点)

    在默认情况下:它会根据默认无参构造函数来创建对象。 若bean中没有默认无参构造函数,将会创建失败。

    <bean id="id" class="com.XXX.XXX"/>

  • 第二种:静态工厂(了解)

    使用StaticFactory类中的静态方法createbean创建对象,并存入spring容器:

      /**
      *模拟一个静态工厂,创建对象
      */
      public class StaticFactory{
          public static Bean createbean(){
              return new Bean();
          }
      }
    

    <bean id="XXX" class="com.XXX.XXX.StaticFactoty" factory-method="createbean"></bean>

  • 第三种:实例工厂(了解)

    先把工厂创建交给spring来管理,然后再使用工厂的bean来调用里面的方法

      /**
      *模拟一个实例工厂,创建对象
      *此工厂创建对象,必须先有工厂实例对象,再调用方法
      */
      public class IntanceFactory{
          public static Bean createbean(){
              return new Bean();
          }
      }
    

    <bean id ="instancFactory" class="com.XXX.XXX.IntanceFactory"> </bean>

    <bean id ="XXX" factory-bean="instancFactory" factory-method="createbean"> </bean>

DI配置

依赖

  • 依赖指的就是Bean实例中的属性
  • 依赖(属性)分为:简单类型(8种基本类型和String类型)的属性、POJO类型的属性、集合数组类型的属性。

依赖注入

  • 依赖注入:Dependency Injection。它是 spring 框架核心IoC的具体实现。

进行依赖注入

  • 我们的程序在编写时,通过控制反转,把对象的创建交给了spring,但是代码中不可能出现没有依赖的情况。
  • 那如果一个bean包含了一些属性,那么spring帮我们实例化了bean对象之后,也需要将对应的属性信息进行赋值操作,这种属性赋值操作,就是所谓的依赖注入(获取值,注入属性)

依赖注入的方式

  1. 构造函数注入 使用类中的构造函数,给成员变量赋值。注意赋值的操作不是我们自己做的,而是通过配置方式,让spring框架来为我们注入。
  public class User{
      private int id;
      private String name;
      
      public User(int id,String name){
          this.id = id;
          this.name = name;
      }
  }
<bean id="user" class="com.XXX.XXX.User">
        <constructor-arg name="id" value="1"></constructor-arg>
        <constructor-arg name="name" value="张三"></constructor-arg>
</bean>

使用构造的方式,给对象的属性传值要求:类中需要提供一个对应参数列表的构造函数

涉及的标签:

  • constructor-arg

    • index:指定参数在构造函数列表的索引位置
    • name:指定参数在构造函数中的名称
    • value:它能赋的值时基本数据类型和String类型
    • ref:它能赋的值时其他bean类型,也就是说,必须的是在配置文件中配置过的bean
  1. set方法注入(重点)

    • 手动装配方式(XML方式)

      • 需要配置bean标签的子标签property
      • 需要配置的bean中指定setter方法
    • 自动装配方式(注解方式)

      • @Autowired

        • 作用一:查找实例,从spring容器中根据Bean的类型(byType)获取实例
        • 作用二:赋值,将找到的实例,装配给另一个实例的属性值
        • 注意事项:一个Java类型在同一个spring容器中,只能有一个实例
      • @Resource

        • 作用一:查找实例,从spring容器中根据Bean的名称(byName)获取实例
        • 作用二:赋值,将找到的实例,装配给另一个实例的属性值
      • @Inject

  2. 使用p名称注入数据

    • 本质上还是调用set方法

      • 步骤一:需要先引入p名称空间 在schema的名称空间加入该行:xmlns:p="http://www.springframework.org/schema/p"

      • 步骤二:使用p名称空间的语法

      P:属性名 = ""
      p:属性名-ref = ""
      

依赖注入不同类型的属性

  • 简单类型(value)
<bean id="user" class="com.XXX.XXX.User">
       <constructor-arg name="id" value="1"></constructor-arg>
       <constructor-arg name="name" value="张三"></constructor-arg>
</bean>
  • 引用类型(ref)
<bean id="user" class="com.XXX.XXX.User">
       <property name ="car" ref="car"></property>
</bean>
<bean id="car" class="com.XXX.XXX.Car"></bean>
  • 集合类型(数组)

    • 如果是数组或者list集合,注入配置文件的方式是一样的
     <bean id="user" class="com.XXX.XXX.User">
             <property name="arrs">
                 <list>
                     <!-- 如果集合内是简单类型,使用value子标签,如果是POJO类型,则使用bean标签 -->
                     <value>123</value>
                     <value>aaa</value>
                     <bean></bean>
                 </list>
             </property>
     </bean>
    
    • 如果是Set集合,注入的配置文件方式如下:
    <bean id="user" class="com.XXX.XXX.User">
            <property name="sets">
                <set>
                    <!-- 如果集合内是简单类型,使用value子标签,如果是POJO类型,则使用bean标签 -->
                    <value>123</value>
                    <value>aaa</value>
                    <bean></bean>
                </set>
            </property>
    </bean>
    
    • 如果是Map集合,注入的配置方式如下
     <bean id="user" class="com.XXX.XXX.User">
             <property name="map">
                 <map>
                     <!-- 如果集合内是简单类型,使用value,如果是POJO类型,则使用ref -->
                    <entry key="key1" value="23"/>
                    <entry key="key2" ref="">
                 </map>
             </property>
     </bean>
    
    • 如果是Properties集合的方式,注入的配置如下:
     <bean id="user" class="com.XXX.XXX.User">
             <property name="pro">
                 <props>
                    <prop key="name">张三</prop>
                 </props>
             </property>
     </bean>
    

基于注解和XML混合方式的使用

IoC注解使用方法

  • 第一步:spring配置文件中,配置context:component-scan标签

Snipaste_2021-07-14_22-13-41.png

  • 第二步:类上面加上注解@Component,或者它的衍生注解@Controller、@Service、@Repository

Snipaste_2021-07-14_22-16-33.png

常用注解

IoC注解

  • 相当于 <bean id="" class=""></bean>

  • Component注解

    • 作用:把资源让spring来管理,相当于在xml中配置一个bean。
    • 属性:value:指定bean的id,如果不指定value属性,默认bean的id是当前类的类名,首字母小写。
  • @Controller、@Service、@Repository注解

    它们三个注解都是针对@Component的衍生注解,它们的作用及属性是一模一样的。它们只不过是提供了更加明确的语义化。

    注意:如果注解中有且只有一个属性要赋值时,且名称是value,value在赋值时可以不写

    • @Controller:一般用于表现层的注解
    • @Service:一般用于业务层的注解
    • @Repository:一般用于持久层的注解

DI注解(依赖注入)

  • 相当于: <property name="" value=""></property> <property name="" ref=""></property>

  • @Autowired

    • @Autowired默认是按类型装配(byType)
    • @Autowired是由AutowiredAnnotationBeanPostProcessor类实现
    • @Autowired是spring自带的注解
    • @Autowired默认情况下要求依赖对象必须存在,如果需要允许null值,可以设置它的required属性为false,如:@Autowired(required=false)
    • 如果我们想按名称装配(byName)可以结合@Qualifier注解进行使用
  • @Qualifier

    • 在自动按照类型注入的基础之上,再按照Bean的id注入
    • 它在给字段注入是不能独立使用,必须和@Autowire一起使用
    • 但是给方法参数注入时,可以独立使用
  • @Resource

    • @Resource默认按名称装配(byName),可以通过@Resource的name属性指定名称,如果没有指定name属性,当注解写在字段上时,默认取字段名进行按照名称查找,当找不到与名称匹配的bean时才按照类型进行装配
    • @Resource属于J2EE JSR250规范的实现
    • 但是需要注意的是,如果name属性一旦指定,就只会按照名称进行装配

推荐使用@Resource注解,因为它属于J2EE的,减少了与spring的耦合。

  • @Inject

    • @Inject是根据类型进行自动装配的,如果需要按照名称进行装配,则需要配合@Name
    • @Inject是在JSR303中的规范,需要导入javax.inject.Inject,实现注入
    • @Inject可以作用在变量、setter方法、构造函数上
  • @Value

    • 给基本类型和String类型注入值
    • 可以使用占位符获取属性文件中的值
  • @Autowired、@Resource、@Inject 区别

    • @Autowired是spring自带的,@Resource是JSR250规范实现的,@Inject是JSR330规范实现的,需要导入不同的包
    • @Autowired、@Inject用法基本一样,不同的是@Autowired有一个request属性
    • @Autowired、@Inject是默认按照类型匹配的,@Resource是按照名称匹配的
    • @Autowired如果需要按照名称匹配需要和@Qualifier一起使用,@Inject和@Name一起使用

改变Bean作用范围的注解

  • @Scope:指定bean的作用范围,相当于以下配置:

    <bean id="" class="" scope=""></bean>

    • 属性: value:指定范围的值,取值:singleton prototype request session globalsession

生命周期相关注解

  • @PortConstruct
  • @PreDestroy

相当于 <bean id="" class="" init-method="" destroy-method=""></bean>

关于XML于注解方式比较

  • 注解

    配置简单,维护方便(我们找到类,就相当于找到了对应的配置)

  • XML

    修改时不需要改动源码,不涉及重新编译和部署

  • spring管理Bean方式比较

XML注解
Bean定义@Component 衍生类 @Controller @Service @Repository
Bean名称通过id或name指定@Component("XXX")
Bean注入或者p命名空间@Autowired 按类型注入 @Qualifier按名称注入
生命过程、 Bean作用范围init-method destroy-method 范围scope属性@PortConstruct 初始化 @PreDestroy 销毁 @Scope作用范围
适合场景Bean来自第三方,使用其他实现类Bean的实现类由用户自己开发

基于纯注解方式使用

  • @Configuration

    • 相当于spring的XML配置文件

    • 从spring3.0开始可以使用@Configuration定义配置类,可以替换XML配置文件

    • 配置类内部包含由一个或者多个被@Bean注解的方法,这些方法将会被AnnotationConfigApplicationContext或者AnnotationConfigWebApplicationContext类进行扫描,并用于构建bean定义对象,初始化spring容器。spring初始化时会调用配置类的无参构造函数。

    • 属性:

      • value:用于指定配置的字节码
  • @Bean

    • 相当于bean标签

    • 作用为:注册bean对象,主要用来配置非自定义的bean,比如DruidDataSource、SqlSessionFactory

    • @Bean标注在方法上(返回某个实例的方法)

    • 属性:

      • name:给当前@Bean注解方法创建的对象指定一个名称(即bean的id),如果不指定,默认于标注的方法名相同
      • @Bean注解默认作用域为单例singleton作用域,可通过@Scope("prototype")设置为对象作用域
  • @ComponentScan

    • 相当于context:component-scan标签

    • 组件扫描器,扫描@Component、@Controller、@Service、@Repository注解的类

    • 该注解是编写再类上面的,一般配合@Configuration注解一起使用

    • 属性

      • basePackages:用于指定要扫描的包
      • value:和basePackages作用一样
  • @PropertySource

    • 相当于context:property-placeholder标签

    • 编写在类上面,作用是加载properties配置文件

    • 属性

      • value[]:用于指定properties文件路径,如果在类路径下,需要写上classpath
  • @Import

    • 相当于spring配置文件中的标签

    • 用来组合多个配置类,在引入其他配置类时,可以不用再写@Configuration注解,若写,也无问题

    • 属性

      • value:用来指定其他配置类的字节码文件