Spring-day1-快速开始和注入

Spring

概述

javaEE全站的轻量级开源框架,以IOC(Inverse of control:反转控制)和AOP(Aspect Oriented Programming 面向切面编程)为内核。

工厂模式创建对象

问题:在项目运行时,需要手动导入bean对象,但是在运行时可能会找不到文件等情况出现编译错误错误。

解决:使用工厂类来创建对象,降低依赖调用的耦合,避免产生编译错误。

步骤:

  • 配置文件有xml或properties两种。利用静态代码块加载配置文件
  • 导入配置文件时要用className.class.getClassLoader().getResourceAsStream("文件名")来读取文件流
  • 读取到配置文件后用class.forName(配置文件中类的全路径).newInstance()创建一个bean类,要用一个map容器来存储创建的类,使之成为单例模式。

避免了app自己寻找资源,而是通过工厂来找资源,削减了计算机程序的耦合,接触了代码依赖关系。

快速开始

  1. maven导入spring-context

  2. 在main-resources建立bean.xml,导入以下约束

    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
            https://www.springframework.org/schema/beans/spring-beans.xsd">
    </beans>
    
  3. 在xml中导入自己写的功能组件

        <bean id="accountService" class="web.service.impl.accountServiceImpl"></bean>
        <bean id="accountDao" class="web.dao.impl.accountDaoImpl"></bean>
    
  4. 在主方法中(用户操作自己账户)

    public class Client {
        /*
        * 获取spring的ioc核心容器根据id获取对象
        * ApplicationContext的三个实现类
        *   ClassPathXmlApplicationContext  它可以加载类路径下的配置文件,要求必须在类路径下
        *   FileSystemXmlApplicationContext  可以加载任意路径下的配置文件,必须有访问权限
        *   AnnotationConfigApplicationContext 用于读取注解创建容器的
        *
        * */
        public static void main(String[] args) {
            // 1.获取核心容器对象
            ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
            // 2.根据id获取bean对象
            I_AccountService aservice = (I_AccountService) ac.getBean("accountService");
            I_AccountDao adao = ac.getBean("accountDao", I_AccountDao.class);
    
            System.out.println(aservice);
            System.out.println(adao);
        }
    }
    
    • 核心容器的两个接口引发出的问题
      • ApplicationContext:创建核心容器是,创建对象采取的策略是立即加载的方式,也就是一读取配置文件马上就创建配置文件中配置的对象。(单例对象创建适用)
      • BeanFactory: 创建对象采取的策略是采用延迟加载的方式,也就是什么时候根据id获取对象了,什么时候才真正创建对象。(多例对象创建适用)

bean对象

  1. 创建bean的三种方式

    1. 使用默认构造函数创建:使用bean标签,配以id和class属性后,且没有其他属性和标签。如果类中没有构造函数,则对象无法创建。默认为空参构造

      <bean id="accountService" class="web.service.impl.accountServiceImpl"></bean>
      
    2. 使用某个类中的方法创建对象

      <bean id="工厂类id" class="全路径"></bean>
      <bean id="类id" factory-bean="上方工厂类id" factory-method="创建类的方法"></bean>
      
    3. 使用工厂中的静态方法创建对象

      <bean id="工厂类id" class="全路径"></bean>
      <bean id="类id" factory-bean="上方工厂类id" factory-method="静态方法"></bean>
      
  2. bean的作用范围

    bean标签的scope属性

    • singleton 默认属性 单例
    • prototype 多例
    • request 作用于web应用的请求范围
    • session 作用于web应用的会话
    • Global-session 作用于集群,当不是集群时,就是session
  3. bean对象的生命周期

    • 单例

      和容器生命周期相同

    • 多例

      使用对象时spring框架来创建,对象在使用就一直存在,当对象长时间不用,且没有别的对象引用时,有java的垃圾回收器回收。

<bean id="accountService" class="web.service.impl.accountServiceImpl"
scope="",
init-method="初始化方法",
destroy-method="结束方法"
></bean>
  1. 如果一个类引用了另一个类,那么在xml文件中就要用property去引用他。
  2. 连接数据库的信息也在bean中注入,包括账号密码

依赖注入

能注入的数据有三类

  1. 基本类型和String
  2. 其他bean类型,配置文件或注解配置的bean
  3. 复杂类型/集合类型

注入的方式

某个类构造方法如下:

    public accountServiceImpl(String name, Integer age, Date birthday) {
        this.name = name;
        this.age = age;
        this.birthday = birthday;
    }
  1. 使用构造函数提供(不推荐使用,看弊端)

    使用的标签:constructor-arg,出现在bean内部

    属性:

    • type:要注入的数据的数据类型,是构造函数中某个或谬写参数的类型
    • index:用于指定要注入的数据给构造函数中索引位置赋值
    • name:用于指定给构造函数中指定名称的参数赋值
    • value:基本类型和string类型
    • ref:指定其他类型数据,指的是spring的Ioc核心容器出现过的bean对象
        <bean id="accountService" class="web.service.impl.accountServiceImpl">
        	<constructor-arg name="name" value="jack"/>
        	<constructor-arg name="age" value="13"/>
    			<constructor-arg name="birthday" value="2012-12-12"/> //会报错
    			==============================================
    			<constructor-arg name="birthday" ref="now"/>
        </bean>
        <bean id="now" class="java.util.Date">
    
    • 优势:在获取bean对象时,注入数据是必须的操作,否则对象无法创建成功
    • 弊端:改变了bean对象的实例化方式,在创建对象时,如果用不到也必须提供
  2. 使用set方法提供(常用方式)

    涉及的标签:property 出现的位置bean标签的内部

    标签的属性

    • name 用于指定注入时所调用的set方法名称
    • value
    • ref
    <bean id="accountService" class="web.service.impl.accountServiceImpl">
    	<property name="name",value="test"></property>
    </bean>
    <bean id="now" class="java.util.Date">
    

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

    劣势:如果有某个成员必须有值,则获取对象有可能set方法没有执行

    • 复杂类型注入如list array set 结构相同,标签可以互换。map props同样

      <property name="name",value="test">
      
      	<array name=Array对象名称>
      		<value>aaaa1</value>
      		<value>aaaa3</value>
      		<value>aaaa2</value>
      	</array>
      
      	<map name=Map对象名称>
      		<entry key="a" value=1></entry>
      	</map>
      	
      	<props>
      		<prop key="b">c</prop>
      	</props>
      	
      </property>
      
  3. 使用注解提供

    1. 用于创建对象的(在实现类上添加)

      作用和xml文件中编写bean标签功能相同

      • @component
      类文件
      @Component("accountService")
      public class accountServiceImpl implements I_AccountService {
          // 如果经常变化的数据,并不适用于注入的方式
          private String name;
          private Integer age;
          private Date birthday;
      
      //    public accountServiceImpl(String name, Integer age, Date birthday) {
      //        this.name = name;
      //        this.age = age;
      //        this.birthday = birthday;
      //    }
      
          public void saveAcount() {
              System.out.println("service 方法执行"+name+age+birthday);
          }
      }
      
      配置文件:
      <?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
              https://www.springframework.org/schema/beans/spring-beans.xsd
              http://www.springframework.org/schema/context
              https://www.springframework.org/schema/context/spring-context.xsd">
      		// 告知spring在创建容器要扫描的包
          <context:component-scan base-package="目录"></context:component-scan>
      </beans>
      
      应用层://getBean后面接的是bean的id,component也是bean
      I_AccountService aservice = (I_AccountService) ac.getBean("accountService");
      
      

      ​ 作用:用于把当前类对象存入spring容器中

      ​ 属性:value用于指定bean的id,默认值是当前类名小写

      一下三个注解作用和属性和component一模一样

      • Controller:一般用在表现层
      • Service:一般用在业务层
      • Repository:一般用在持久层
    2. 用于注入数据的

      作用就合bean标签中property作用相同

      • Autowired

            @Autowired
            private I_AccountDao accountDao = null;
            public void saveAccount() {
                accountDao.b();
        

        作用:自动按照类型注入,只要容器中有唯一的一个bean对象类型和要注入的变量类型匹配成功,就可以成功注入。如果匹配到了两个相同的实现类,就根据变量名在去匹配beanid,如果变量名两者不匹配则报错。

        位置:可以是变量或方法

        注意:只能匹配一个,如果有多个会报错

      • Qualifier

        作用:按照类型注入的基础上再按照名称注入。在给类成员注入时不能单独使用,可以给方法参数注入。

        属性:value用于指定注入bean的id

            @Autowired
            @Qualifier("dao1")
            private I_AccountDao accountDao = null;
            public void saveAccount() {
                accountDao.b();
        
      • Resource

        作用:直接按照bean的id注入,可以独立使用

        属性:name 用于指定bean的id

            @Resource(name="dao2")
            private I_AccountDao accountDao = null;
            public void saveAccount() {
                accountDao.b();
        

      以上三个注入都只能注入其他bean类型的数据,而基本类型和String类型都无法通过以上方式实现。另外集合只能通过xml的方式注入。

      • Value

      作用:用于注入基本类型和String类型的数据

      属性:用于指定数据的值 value,常用取值singleton prototype

    3. 用于改变作用范围的

      作用就合bean标签中scope作用相同

    4. 和生命周期相关

      作用就合bean标签中init-method,destroy-method作用相同

注解类替换xml文件

配置类

@Configuration //当配置类需要被扫描时(通过ComponentScan配置的)该注解不可以省略
@ComponentScan(basePackages = "web")
public class SpringConfiguration {

    @Bean(name="runner")
    // 用于把当前方法的返回值作为bean对象存入spring ioc容器中
    // 属性:
    //  name:用于指定bean的id,默认值时当前方法的id
    // 注意: 如果方法有参数,spring框架会去容器中查找有没有可用的bean对象,查找的方式和autowired一样
    public QueryRunner createQueryRunner(DataSource dataSource){
        return new QueryRunner(dataSource);
    }
}

应用层

        AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfiguration.class); //可省略该类的configuration注解
        // 2.根据id获取bean对象
        I_AccountService aservice = (I_AccountService) ac.getBean("accountService");
        I_AccountDao adao = ac.getBean("accountDao", I_AccountDao.class);
        aservice.saveAccount();
  • Import注解

    作用:导入其他的配置类。既不需要在获取配置类事导入字节码AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfiguration.class)

    也不需要通过加Component和ComponentScan扫描

    属性:

    ​ value:用于指定其他配置类的字节码。使用Import注解后,有Import的类就是父配置类,而导入的都是子配置类。

  • PropertySource注解

    作用:导入properties里面的配置

    属性:value指定文件的名称和路径

@ComponentScan(basePackages = "web")
@import(jdbcConfig.class)
@PropertySource("classpath:config/spring/jdbcConfig.properties")
public class SpringConfiguration {

    @Bean(name="runner")
    // 用于把当前方法的返回值作为bean对象存入spring ioc容器中
    // 属性:
    //  name:用于指定bean的id,默认值时当前方法的id
    // 注意: 如果方法有参数,spring框架会去容器中查找有没有可用的bean对象,查找的方式和autowired一样
    public QueryRunner createQueryRunner(DataSource dataSource){
        return new QueryRunner(dataSource);
    }
}

在jdbcConfig中,用value去对应表达式的值,@PropertySource已经找到了配置文件
@Value("${jdbc.driver}")
private String driver;
posted @ 2020-03-25 18:33  Jimmyhe  阅读(149)  评论(0)    收藏  举报