spring简介[IOC]

1、spring简介(IOC)

Spring框架是一个开放源代码的J2EE应用程序框架,是针对bean的生命周期进行管理的轻量级容器。 Spring解决了开发者在J2EE开发中遇到的许多常见的问题,提供了功能强大IOC、AOP及Web MVC等功能。Spring可以单独应用于构筑应用程序,也可以和Struts、Webwork、Tapestry等众多Web框架组合使用,并且可以与 Swing等桌面应用程序AP组合。Spring框架主要由七部分组成,分别是 Spring Core、 Spring AOP、 Spring ORM、 Spring DAO、Spring Context、 Spring Web和 Spring Web MVC

1.1、编写第一个spring的案列

  • 导入pom 文件
    <!-- spring的核心包 -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-core</artifactId>
        <version>5.3.18</version>
    </dependency>
<!--spring应用上下文的包-->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>5.3.18</version>
    </dependency>
<!--spring bean管理的包-->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-beans</artifactId>
        <version>5.3.18</version>
    </dependency>

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-expression</artifactId>
        <version>5.3.18</version>
    </dependency>
<!-- 有关java io输入输出的架包-->
    <dependency>
        <groupId>commons-io</groupId>
        <artifactId>commons-io</artifactId>
        <version>2.11.0</version>
    </dependency>
<!--    单元测试的架包-->
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.13.1</version>
        <scope>test</scope>
    </dependency>
  • 编写测试文件
public class TestDemo {

    @Test
    public void getAnimal() {
        ApplicationContext applicationContext = new GenericXmlApplicationContext("./bean.xml");
        Animal animal = applicationContext.getBean("animal", Animal.class);
        System.out.println(animal);
        animal.eat();

    }
}

1.2、IOC容器

  1. 什么是IOC:
    1. 控制反转,将对象的创建和对象之间调用的过程都交给了spring进行管理
    2. 之前我们创建对象都是new出来的,使用IOC进行创建的话,我们将对象交给了spring容器进行管理,因此IOC降低了耦合度。
  2. IOC的底层原理:
    1. 工厂模式,可以解决耦合度高的问题,类与类之间不直接产生联系,而是通过工厂类的方式创建对象,后面引入话题ioc
    2. XML的解析、反射 IOC容器原理。
  3. IOC的过程:
    1. 创建xml配置文件,配置要创建的对象
    2. 通过xml解析的方式,加载到类的路径 eg: “com.hema.User”
    3. 通过反射Class.forName();获取到字节码文件,然后通过class.newInstance()创建对象返回.
    4. 解耦的原理,将类的路径放到了配置文件中,如果要改变类的话,可以直接进行改变xml配置文件,而不是到处更改类文件

1.3、IOC(接口)

  1. IOC思想基于IOC容器完成,IOC底层就是对象工厂- Spring提供IOC容器实现的两种方式(两个接口)
    1. BeanFactory: IOC容器基本的实现,是spring内部进行使用的接口,不提供给开发人员进行使用,在加载配置文件的时候,不会去创建配置文件中对象,只有在获取或者在使用对象的时候才去创建对象
    2. ApplicationContext:是BeanFactory接口的子接口,提供更加强大的功能,提供给开发人员进行使用,在加载配置文件的时候就去创建对象,spring主要使用在web中,因此的话,当对象在服务启动的时候去创建,将耗时耗资源的步奏交给服务器进行处理,减少应用层面的压力
    3. ApplicationContext中主要的实现类
      1. FileSystemXmlApplicationContext, 使用该实现类的时候,需要将配置文件的绝对路径进行传入.
      2. ClasspathXmlApplicationContext,使用该实现类的时候,传入配置文件的类路径,相对路径

1.4、IOC的操作Bean管理

  1. 什么叫做Bean管理,就是两个操作
    1. Spring创建对象
    2. Spring注入属性
  2. Bean的管理操作有两种方式
    1. 基于Xml配置文件的方式实现
    2. 基于注解方式实现
<?xml version="1.0" encoding="UTF-8"?>
<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 http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="animal" class="com.hema.xiaohua.Animal">

</bean>
</beans>
1.4.1、IOC操作Bean管理基于XML方式
  1. 基于xml方式进行创建对象

    • 在spring配置文件中使用bean标签,在标签中添加对应的属性,就可以实现对象的创建,在创建对象的时候是执行类的无参构造方法
    • 在bean标签中有很多的属性:
      • id属性:就是为要配置的类起别名,也是类的唯一的一个标识
      • class属性:要配置类的class路径(包全路径)。
      • name:跟id属性的作用差不多,id属性不能加上特殊的符号,而name中可以添加上特殊的符号"/"
      • scope属性,可以指定该类创建时单列模式singleton还是多实例模式prototype
  2. 基于XML方式注入属性
    DI:依赖注入,就是注入属性

1.4.1.1、set注入(无参注入)

第一种注入方式:使用set方式注入
1. 创建类,定义属性,以及属性对应的set方法
2. 在spring配置文件中配置对象,创建配置属性注入,使用到无参构造

<bean id="animal" class="com.hema.xiaohua.Animal">
<!--    property标签,表示用来向配置类中注入属性的默认值-->
    <property name="id" value="100"></property>
    <property name="classId" value="110"></property>
</bean>
1.4.1.2、有参注入

第二种注入方式: 使用有参构造进行注入
1. 创建类,创建类的有参构造
2. 在spring配置文件中配置对象,创建配置属性注入

    <bean id="animal" class="com.hema.xiaohua.Animal">
<!--        使用constructor-arg来指定有参构造属性的注入,可以使用name直接指定属性名字,还可以使用index来直接指定为第几个参数赋值   -->
<!--        <constructor-arg index="1" value="2222"></constructor-arg>-->
        <constructor-arg name="id" value="8888"></constructor-arg>
        <constructor-arg name="classId" value="9999"></constructor-arg>
    </bean>

第三种注入方式:P名称空间注入
使用P名称空间注入,可以简化基于xml配置方式,他是基于set方式进行注入的,在xml的头部添加上 xmlns:p=“http://www.springframework.org/schema/p”
然后就可以使用p标签进行注入属性

    <bean id="animal" class="com.hema.xiaohua.Animal" p:id="555" p:classId="666">
    </bean>
1.4.1.3、注入空值和特殊符号

字面量: 向类的属性中注入固定的值就叫做字面量

  1. 向字面量中设置null值
  2. 向字面量中设置特殊值
    <bean id="animal" class="com.hema.xiaohua.Animal" p:id="555" p:classId="666">
        <!--        为字面量,也就是属性值赋空-->
        <property name="address">
            <null/>
        </property>
<!--        为属性赋特殊的值,可以使用CADTA进行转义-->
        <property name="date">
            <value><![CDATA[<<1998.12>>]]></value>
        </property>
    </bean>
1.4.1.4、注入外部的bean

在service和dao中创建两个类,UserDao和UserService
然后再UserService中引用外部的bean userDao

    <bean id="userDao" class="com.hema.xiaohua.dao.UserImpl"></bean>
    <bean id="userService" class="com.hema.xiaohua.service.UserServiceImpl">
<!--        使用ref将外部bean进行引用注入,ref的值是配置文件中我们为其配置的别名 -->
        <property name="userImpl" ref="userDao"></property>
    </bean>
1.4.1.5、注入属性-内部bean

可以与外部bean进行类比,注入外部bean的话,就是将其他类的bean配置单独写在外面,然后使用ref通过别名进行引入,而注入内部bean的话,顾名思义就不用进行引入,直接将该bean的配置写入到当前bean配置的内部。

        <bean id="student" class="com.hema.xiaohua.entity.Student">
            <property name="id" value="112"></property>
            <property name="name" value="xiaohong"></property>
<!--            内部bean-->
            <property name="teacher">
                <bean name="teacher" class="com.hema.xiaohua.entity.Teacher">
                    <property name="id" value="t123"></property>
                    <property name="name" value="xiaohualaoshi"></property>
                </bean>
            </property>
        </bean>
1.4.1.6、注入属性-级联操作

假如现在有两个类,一个teacher类,一个student类,然后的话,我们将这两个类的bean在配置文件中进行配置,由于student和teacher是多对一的关系,因此的话,在student配置中可以直接配置teacher相关的属性,可以类比外部bean的引用

    <!--       级联赋值第一种写法-->
    <bean id="student" class="com.hema.xiaohua.entity.Student">
       <property name="id" value="st123"></property>
       <property name="name" value="xiaohua"></property>
       <property name="teacher" ref="teacher">
       </property>
   </bean>
    <bean id="teacher" class="com.hema.xiaohua.entity.Teacher">
        <property name="id" value="teacher123"></property>
        <property name="name" value="dss"></property>
    </bean>

    <!--    级联赋值第二种写法-->
    <bean id="student" class="com.hema.xiaohua.entity.Student">
        <property name="id" value="st789"></property>
        <property name="name" value="xiaohong"></property>
        <property name="teacher" ref="teacher">
        </property>
<!--        使用第二种方法的话需要添加上teacher的get方法-->
        <property name="teacher.id" value="hhhhh"></property>
        <property name="teacher.name" value="vvvvvvvv"></property>
    </bean>
    <bean id="teacher" class="com.hema.xiaohua.entity.Teacher">
    </bean>
1.4.1.7、注入集合属性

第一种注入普通属性的集合

    <bean id="student" class="com.hema.entity.Student">
<!--        数组属性类型的注入-->
        <property name="courses">
            <array>
                <value>数学</value>
                <value>英语</value>
            </array>
        </property>
<!--        list集合属性的注入-->
        <property name="list">
            <list>
                <value>xiaoqiang</value>
                <value>xiaohuahua</value>
            </list>
        </property>
<!--        map集合的注入-->
        <property name="map">
            <map>
                <entry key="id" value="100"></entry>
                <entry key="class" value="一年一班"></entry>
            </map>
        </property>
<!--        set集合的注入-->
        <property name="set">
            <set>
                <value>xiaohong</value>
                <value>xiaohong</value>
                <value>xiaohai</value>
            </set>
        </property>

    </bean>

第二种注入包含对象属性的集合:

    <bean id="student" class="com.hema.entity.Student">
<!--        对象集合的注入-->
        <property name="courseList">
            <list>
                <ref bean="course1"></ref>
                <ref bean="course2"></ref>
            </list>
        </property>

    </bean>

<bean id="course1" class="com.hema.entity.Course">
    <property name="name1" value="数学1"></property>
</bean>

<bean id="course2" class="com.hema.entity.Course">
    <property name="name1" value="语文1"></property>
</bean>

1.4.1.8、集合抽取成公共部分进行使用

添加上 xmlns:util=“http://www.springframework.org/schema/util”

<?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:p="http://www.springframework.org/schema/p"
       xmlns:util="http://www.springframework.org/schema/util"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
                           http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">


  <util:list id="bookList">
        <ref bean="book1"></ref>
        <ref bean="book2"></ref>
    </util:list>
    <bean id="book1" class="com.hema.entity.Book">
        <property name="name" value="活着"></property>
    </bean>
    <bean id="book2" class="com.hema.entity.Book">
        <property name="name" value="java核心技术卷"></property>
    </bean>
    <bean id="course" class="com.hema.entity.Course">
        <property name="bookList" ref="bookList"></property>
    </bean>

1.4.2、IOC操作Bean管理

1.Spring有两种bean,一种叫做普通的bean,一种叫做工厂bean(FactoryBean)

普通Bean:在配置文件定义的类型就是返回的类型

工厂bean: 在配置文件中定义bean的类型可以和返回类型不一样
1.首先的话写一个类继承工厂类FactoryBean,然后重写里面的方法,新建对象然后返回,工厂类中的泛型写需要返回类


public class MyBean implements FactoryBean<Student> {
    @Override
    public Student getObject() throws Exception {
        Student student = new Student();
        String[] arr = {"11","@22"};
        student.setCourses(arr);
        return student;
    }

    @Override
    public Class<?> getObjectType() {
        return null;
    }
}

1.4.3、Bean的作用域
  1. 在scope属性中,默认值是单实例属性singleton,还有第二个值是prototype,表示的是多实例对象
  2. singleton和prototype的区别:
    1. singleton单实例,prototype是多实例
    2. 设置scope值是singleton的时候,加载spring配置文件的时候就会创建单实例对象
    3. 设置scope属性是prototype的时候,不是加载spring配置文件的时候创建对象,而是在调用getbean方法的时候创建多实例对象
  3. scope属性还有request和session属性可以进行选择
    <bean id="book1" class="com.hema.entity.Book" scope="singleton">
        <property name="name" value="活着"></property>
    </bean>
1.4.4、Bean的生命周期
  1. 生命周期
    1. 从对象的创建到对象销毁的过程
  2. bean的生命周期
    1. 通过构造器创建bean实例(无参构造)
    2. 为bean的属性设置值和其他的bean引用(调用set方法)
    3. 调用bean的初始化方法(需要进行配置)
    4. bean的使用
    5. 当容器关闭的时候,调用bean的销毁的方法,(需要进行配置销毁的方法)
<!--    可以在bean标签中进行配置init-method,和dstory-method 初始化和销毁要执行的方法 -->
    <bean id="book1" class="com.hema.entity.Book" scope="singleton" init-method="" destroy-method="">
        <property name="name" value="活着"></property>
    </bean>

在没有加上后置处理器的时候,bean的生命周期是5步,加上后置处理器之后,bean的生命周期是7步,后置处理器就是写一个类实现BeanPostProcessor接口,重写里面的postProcessBeforeInitialization和postProcessAfterInitialization接口,通过在配置文件中配置,就会在配置文件所有的bean初始化方法前,和初始化方法后进行执行

  1. 执行无参方法创建bean实例
  2. 调用set方法设置属性值
  3. 在初始化方法之前执行的方法
  4. 执行初始化方法
  5. 在初始化方法之后执行的方法
  6. 使用bean对象
  7. 执行销毁的方法
1.4.5、IOC容器(自动装配)

1.什么叫做自动装配
根据指定自动装配的规则(属性名称或者是属性类型),spring自动的将匹配的属性值进行注入
bean标签autowire配置自动装配
autowire常用的两个值
byName根据属性名称进行注入,注入bean的id值和类属性名称一样
byType根据属性类型进行注入

<!--    自动装配-byName,通过bean配置的id别名与定义的属性名字一致进行装配-->
    <bean id="student" class="com.hema.entity.Student" autowire="byName"></bean>
    <bean id="course" class="com.hema.entity.Course">
        <property name="name1" value="123"></property>
    </bean>
    <bean id="course2" class="com.hema.entity.Course">
        <property name="name1" value="123"></property>
    </bean>
        <!--    自动装配-bytype,通过bean配置的类型与定义的属性属性的类型一致进行装配,
    当配置两个类型一致的bean时候,就需要使用到byName进行自动装配了
    -->
    <bean id="student" class="com.hema.entity.Student" autowire="byType"></bean>
    <bean id="course" class="com.hema.entity.Course">
        <property name="name1" value="123"></property>
    </bean>
<!--    <bean id="course2" class="com.hema.entity.Course">-->
<!--        <property name="name1" value="123"></property>-->
<!--    </bean>-->
    
1.4.6、IOC操作(外部属性文件)

案列配置数据库连接池

未使用properties外部文件进行配置


<bean id="datasource" class="com.alibaba.druid.pool.DruidDataSource">
    <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
    <property name="url" value="jdbc:mysql://localhost:33066/demo"></property>
    <property name="username" value="root"></property>
    <property name="password" value="123456"></property>
</bean>

使用外部properties文件引入数据库连接池
1.要加入context命名空间,通过context标签将properties文件进行引入,进而引用properties中的配置

<?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:p="http://www.springframework.org/schema/p"
       xmlns:util="http://www.springframework.org/schema/util"
       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/util http://www.springframework.org/schema/util/spring-util.xsd
                           http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<beans>                           

    <context:property-placeholder location="classpath:./jdbc.properties"/>
<bean id="datasource" class="com.alibaba.druid.pool.DruidDataSource">
    <property name="driverClassName" value="${jdbc.driverClassName}"></property>
    <property name="url" value="${jdbc.url}"></property>
    <property name="username" value="${jdbc.username}"></property>
    <property name="password" value="${jdbc.password}"></property>
</bean>
1.4.7、IOC操作Bean管理(基于注解方式)
  1. 什么是注解

    1. 注解是代码中特殊的标记,格式:@注解名称(属性名称=属性值,属性名称=属性值…)
    2. 使用注解,注解是作用在类上面,方法上面,属性上面
    3. 使用注解的目的,为了简化xml配置
  2. Spring针对Bean管理中创建对象提供注解

    1. @Component: 中性使用
    2. @Service: 放到service层上
    3. @Controller: 放到controller层上
    4. @Repository: 放到实体类中,dao层上
    5. 上面四个注解的功能都是一样的,都可以用来创建bean实例
  3. 基于注解的方式创建对象

    • 引用pom坐标:
<!--    有关spring注解的jar包-->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-aop</artifactId>
        <version>5.3.13</version>
    </dependency>
<?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:p="http://www.springframework.org/schema/p"
       xmlns:util="http://www.springframework.org/schema/util"
       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/util http://www.springframework.org/schema/util/spring-util.xsd
                           http://www.springframework.org/schema/context  http://www.springframework.org/schema/context/spring-context.xsd">
<!--使用注解对bean进行管理
    1.导入命名空间context   xmlns:context="http://www.springframework.org/schema/context"
    2.使用context:component-scan 标签开启注解扫描,base-package中可以写要扫描包的路径,可以使用逗号隔开书写多个包路径
    3.在书写的配置类上加上@Service/@Component/@Controller/@Repository
    4.@Service(value=""),如果value中不写值的话,默认的话使用类名首字母小写
-->
    <context:component-scan base-package="com.hema"></context:component-scan>
</beans>
<!--    在component-sacan中,我们可以配置过滤掉要进行扫描的注解
        1.首先将 user-default-filters属性配置为false,不使用spring默认的注解
        2.expression配置要过滤的注解内容 下面的是要过滤@Controller的注解
        3.还可以使用exclude-filter设置哪些内容不进行扫描,include-filter可以设置哪些内容可以进行扫描
        -->
    <context:component-scan base-package="com.hema" use-default-filters="false">
        <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>
1.4.7.1、基于注解方式实现属性注入
  1. AutoWired: 根据属性类型进行自动注入(对象)
  2. @Qualifier: 根据属性的名称进行注入(对象),这个注解的使用要和@Autowired的一起进行使用,用来解决的问题,一个类型可以有多个实现类,因此的话,@Autowired通过类型进行注入的话就会有问题,这个时候就可以使用@Qualifier通过属性名进行注入
  3. @Resource: 可以根据类型注入,也可以根据名称注入(对象),是java包下面提供的注解,不是spring提供的原生注解
  4. @Value:根据属性类型进行注入(基本属性)
1.4.7.2、完全使用注解替换掉xml

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration //该注解用来声明是一个配置类,替换掉bean.xml
@ComponentScan("com.hema") //该注解用来属性要扫描bean的包
public class AutoConfig {

}

test:


    @Test
    public void getUser() {
//        ApplicationContext applicationContext = new GenericXmlApplicationContext("./bean.xml");
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(AutoConfig.class);
        UserService userService = applicationContext.getBean("userService", UserService.class);
        System.out.println(userService);
        userService.eat();
        UserDao userDao = userService.getUserDao();
        userDao.eat();
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值