Spring详解(一)概述和 IoC控制反转

文章目录

  • Spring
    • 第一章 Spring 概述
      • 1.1. 什么是spring
      • 1.2 spring的地址
      • 1.3 Spring优点
    • 第二章 IoC 控制反转
      • 2.1 IoC 概念
      • 2.2 Spring的配置文件
      • 3.Spring 容器创建对象的特点
      • 4.DI:给属性赋值
        • 4.1基于xml的DI
          • 1)set注入,也叫作设值注入
          • 2)构造注入(理解)
          • 3)引用类型的自动注入
          • 4)作业 IoC
          • 5)项目中使用多个Spring配置文件
        • 4.2基于注解的DI(注解为主,配置文件为辅)
          • 4.21注解使用的核心步骤
          • 4.22注解介绍
          • @Component
          • 多个包扫描直接的配置文件
          • 4.23简单属性的赋值@Value
          • 4.24配置文件赋值
          • 4.25@Autowired 注解byType方法
          • 4.26@Autowired 注解byName方法
          • 4.27 @Resource
      • 5.总结

Spring

第一章 Spring 概述

1.1. 什么是spring

​ spring就是一个java框架,使用java语言开发的, 轻量级的, 开源的框架。 可以在j2se、j2ee项目中都可以使用。

​ spring核心技术: ioc, aop

​ spring又叫做:容器, spring作为容器, 装的是java对象。 可以让spring创建java对象, 给属性赋值。

​ spring作用: 实现解耦合, 解决java对象之间的耦合, 解决模块之间的耦合。

​ tomcat也是容器:管理的是servlet, listener, filter等对象。

​ 创建HelloServlet 类, 写web.xml

​ spring:创建SomeServiceImpl, 写spring的配置文件。

1.2 spring的地址

​ https://spring.io

1.3 Spring优点

​ Spring 是一个框架,是一个半成品的软件。有 20 个模块组成。它是一个容器管理对象,容器是装东西的,Spring 容器不装文本,数字。装的是对象。Spring 是存储对象的容器。
(1) 轻量
​ Spring 框架使用的 jar 都比较小,一般在 1M 以下或者几百 kb。Spring核心功能的所需的 jar 总共在 3M 左右。
Spring 框架运行占用的资源少,运行效率高。不依赖其他 jar

(2) 针对接口编程,解耦合
Spring 提供了 Ioc 控制反转,由容器管理对象,对象的依赖关系。原来在程序代码中的对象创建方式,现在由容器完成。对象之间的依赖解耦合。

(3) AOP 编程的支持
通过 Spring 提供的 AOP 功能,方便进行面向切面的编程,许多不容易用传统 OOP 实现的功能可以通过 AOP 轻松应付在 Spring 中,开发人员可以从繁杂的事务管理代码中解脱出来,通过声明式方式灵活地进行事务的管理,提高开发效率和质量。

(4) 方便集成各种优秀框架
Spring 不排斥各种优秀的开源框架,相反 Spring 可以降低各种框架的使用难度,Spring 提供了对各种优秀框架(如 Struts,Hibernate、MyBatis)等的直接支持。简化框架的使用。Spring 像插线板一样,其他框架是插头,可以容易的组合到一起。需要使用哪个框架,就把这个插头放入插线板。不需要可以轻易的移除。

第二章 IoC 控制反转

2.1 IoC 概念

​ IoC,Inversion of Control : 控制反转, 是一个理论,一个指导思想。 指导开发人员如何使用对象,管理对象的。 把对象的创建,属性赋值,对象的声明周期都交给代码之外的容器管理。

  1. IoC分为 控制和反转

​ 控制: 对象创建,属性赋值, 对象声明周期管理

​ 反转:把开发人员管理对象的权限转移给了代码之外的容器实现。 由容器完成对象的管理。

​ 正转:开发人员在代码中, 使用 new 构造方法创建对象。 开发人员掌握了对象的创建,属性赋值,对象从开始到销毁的全部过程。 开发人员有对 对象 全部控制。

​ 通过容器,可以使用容器中的对象(容器已经创建了对象, 对象属性赋值了, 对象也组装好了)。

​ Spring就是一个容器,可以管理对象,创建对象,给属性赋值。

  1. IoC的技术实现

    DI ( 依赖注入) :Dependency Injection, 缩写是DI . 是IoC的一种技术实现。 程序只需要提供要使用的对象的名称就可以了, 对象如何创建, 如何从容器中查找,获取都由容器内部自己实现。

​ 依赖名词: 比如说ClassA类使用了ClassB的属性或者方法,叫做ClassA依赖ClassB.

public class ClassB{
    
    public void createOrder(){}
}

public class ClassA{
    //属性
    private ClassB  b = new ClassB();
    
    public void buy(){
        b.createOrder();
    }
}

执行ClassAbuy()
ClassA a  = new ClassA();
a.buy();
  1. Spring框架使用的DI实现IoC.

    通过spring框架, 只需要提供要使用的对象名词就可以了。 从容器中获取名称对应的对象。

spring底层使用的 反射机制, 通过反射创建对象,给属性。

2.2 Spring的配置文件


<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">
    

beans>

spring标准的配置文件:
1)根标签是 beans
2)beans 后面的是约束文件说明
3)beans里面是bean声明。
4)什么是bean:bean就是对象,spring容器管理的java对象,叫做bean。


3.Spring 容器创建对象的特点

1.容器对象ApplicationContext:接口

​ 通过ApplicationContext对象,获取要使用的其他java对象,执行getBean(“的id”)

  1. spring默认是调用类的无参数构造方法,创建对象。
  2. spring读取配置文件,一次创建好所有对象,都放到容器的map中。

src/main/resources/beans.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 http://www.springframework.org/schema/beans/spring-beans.xsd">



    <bean id="someService" class="com.sunny.service.impl.SomeServiceImpl"/>
    <bean id="someService1" class="com.sunny.service.impl.SomeServiceImpl"/>
    <bean id="otherService" class="com.sunny.service.impl.OtherService"/>




    <bean id="mydate" class="java.util.Date"/>
beans>

​ 改变传统思想,要从容器中拿对象去用。

  /*
    * 获取容器中对象的信息
    *
    * */
    @Test
    public void test04(){
        String config = "beans.xml";
        ApplicationContext ctx = new ClassPathXmlApplicationContext(config);

//        获取容器中定义的对象的数量
        int nums = ctx.getBeanDefinitionCount();
        System.out.println("容器中定义对象的数量=="+nums);

//        获取容器中定义的对象名称
        String names[] = ctx.getBeanDefinitionNames();
        for (String name:names){
            System.out.println("容器中对象的名称 ==="+name);
        }
    }
    /*
    * 让spring创建非自定义的对象
    * 有class就能让spring创建对象
    * */
    @Test
    public void test05(){
        String config = "beans.xml";
        ApplicationContext ctx = new ClassPathXmlApplicationContext(config);
        Date date = (Date) ctx.getBean("mydate");
        System.out.println("date==="+date);

        OtherService service = (OtherService) ctx.getBean("otherService");
        service.doOther();
    }

4.DI:给属性赋值

​ Spring调用类的无参数构造方法,创建对象。对象创建后给属性赋值。

​ 给属性赋值可以使用1)xml配置文件的标签和属性;2)使用注解。

DI的分类:1.set注入,也叫做设值注入;2.构造注入。

4.1基于xml的DI

​ 在xml配置文件中使用标签和属性,完成对象的创建,属性赋值。

1)set注入,也叫作设值注入

​ 概念:spring调用类中的set方法,在set方法中可以完成属性的赋值。推荐使用 applicationContext.xml

简单类型的设值注入,使用value
    <bean id="mySchool" class="com.sunny.ba02.School">
        <property name="name" value="北京大学"/>
        <property name="address" value="北京的海淀区"/>
    bean>

        DI:给属性赋值
        简单类型:java中的基本数据类型和String
        1.set注入:spring调用类的set方法,通过set方法完成属性赋值
          简单类型的set注入:
          语法: <bean id="xxx" class="yyy">
                    <property name = "属性名" value="简单类型属性值"/>
                    ....
               bean>
        2.set注入:
           引用类型的set注入:
           语法:<bean id="xxx" class="yyy">
                    <property name="属性名" ref="bean的id"/>
                    ...
                bean>

​ 建议使用name的方式,可读性更高。


    <bean id="myStudent" class="com.sunny.ba02.Student">
        <property name="name" value="李四"/> 
        <property name="age" value="20"/>
        <property name="email" value="[email protected]"/>

        <property name="school" ref="mySchool"/>
    bean>
2)构造注入(理解)

​ 构造注入:spring调用类中的有参数构造方法,在创建对象的同时,给属性赋值

构造注入,使用index


    <bean id="myStudent2" class="com.sunny.ba03.Student">
        <constructor-arg index="0" value="张三"/>
        <constructor-arg index="1" value="26"/>
        <constructor-arg index="2" ref="mySchool"/>
    bean>

    <bean id="myStudent3" class="com.sunny.ba03.Student">
        <constructor-arg value="张峰"/>
        <constructor-arg value="28"/>
        <constructor-arg ref="mySchool"/>
    bean>


    <bean id="mySchool" class="com.sunny.ba03.School">
        <property name="name" value="北京大学"/>
        <property name="address" value="北京的海淀区"/>
    bean>

创建文件对象


    <bean id="myFile" class="java.io.File">
        <constructor-arg name="parent" value="E:\\demo"/>
        <constructor-arg name="child" value="SpringFile.txt"/>
    bean>
public class MyTest03 {
    @Test
    public void test01(){
        String config ="ba03/applicationContext.xml";
        ApplicationContext ctx = new ClassPathXmlApplicationContext(config);

        Student student =(Student) ctx.getBean("myStudent3");
        System.out.println("student=="+student);

        //获取File对象
        File file = (File) ctx.getBean("myFile");
        System.out.println("file==="+file.getName());
    }
}

3)引用类型的自动注入

概念:spring可以根据某些规则给引用类型完成赋值。只对引用类型有效。规则byName,byType。

①:byName(按名称注入):java类中引用类型属性名称和Spring容器中bean的id名称一样的,且数据类型也是一样的,这些bean能够赋值给引用类型。




    <bean id="myStudent" class="com.sunny.ba04.Student" autowire="byName">
        <property name="name" value="李四"/> 
        <property name="age" value="20"/>
        <property name="email" value="[email protected]"/>

    bean>



    <bean id="school" class="com.sunny.ba04.School">
        <property name="name" value="清华大学"/>
        <property name="address" value="北京的海淀区"/>
    bean>

②:byType(按类型注入):java类中引用类型的数据类型和Spring容器中bean的class值是同源关系的,这样的bean赋值给引用类型。

        2.byType(按类型注入):java类中引用类型的数据类型和bean的class是同源的。
                            这些bean能够赋值给引用类型。
        同源关系:
            1.java中引用类型的数据类型和bean的class值是一样的。
            2.java中引用类型的数据类型和bean的class值是父子类关系的。
            3.java中引用类型的数据类型和bean的class值是接口和实现类关系的。
        语法:
            <bean id="xxx" class="yy" autowire="byType">
                简单类型属性赋值
            bean>

            注意:在xml配置文件中,符合条件的对象,只能有一个。
                 多于一个会报错

-->


    <bean id="myStudent" class="com.sunny.ba05.Student" autowire="byType">
        <property name="name" value="张三"/> 
        <property name="age" value="26"/>
        <property name="email" value="[email protected]"/>
    bean>








    <bean id="primarySchool" class="com.sunny.ba05.PrimarySchool">
        <property name="name" value="北京大兴小学"/>
        <property name="address" value="北京大兴区"/>
    bean>


4)作业 IoC

需求:模拟一用户注册操作。

​ 需要定义一个dao接口(UserDao)接口中的方法 insertUser(SysUser user ) , 定义接口的实现类 MySqlUserDao

inserUser()方法里面不需要操作数据, 输出“使用了dao执行insert操作”。

​ 需要定义一个service接口(UserService),定义接口的实现类 UserServiceImpl. 在service的实现类有一个 UserDao类型的属性。 service类中有一个方法 addUser(SysUser user).

​ 操作是 service类中的addUser() { userDao.insertUser() } 完成注册。

​ 定义一个实体类 SysUser, 表示用户的数据。

要求实现:

程序中的UserServiceImpl,  MySqlUserDao这些类都有spring容器创建和管理, 同时要给 UserServiceImpl类中的 userDao属性赋值。    从spring容器中获取  UserServiceImpl类型的对象, 调用addUser()方法,输出“使用了dao执行insert操作”。
    <bean id="sysuser" class="com.login.entity.SysUser" >
        <property name="username" value="admin"/>
        <property name="password" value="123456"/>
    bean>

    <bean id="userDao" class="com.login.dao.Imp.MySqlUserDao"/>

    <bean id="userService" class="com.login.service.Imp.UserServiceImpl">
        <property name="userDao" ref="userDao"/>
    bean>
    @Test
    public void test01(){
        String config ="dao/applicationContext.xml";
        ApplicationContext cxt = new ClassPathXmlApplicationContext(config);

        SysUser user = (SysUser) cxt.getBean("sysuser");

        UserServiceImpl userService =(UserServiceImpl) cxt.getBean("userService");
        userService.addUser(user);
    }
5)项目中使用多个Spring配置文件

​ 分多个配置文件的方式

①按功能模块分,一个模块一个配置文件。

②按类的功能分,数据库操作相关的类在一个文件,service类在一个配置文件,配置redis,事务等等的一个配置文件。

​ Spring管理多个配置文件,常用的是包含关系的配置文件、项目中有一个总的文件,里面有import标签包含其他多个配置文件。

语法:

总的文件
<import resource="其他的文件的路径1"/>
<import resource="其他的文件的路径2"/>

关键字“classpath”:表示类路径,也就是类文件(class文件)所在的目录。Spring到类路径中加载文件什么时候使用						classpath:在一个文件中要使用其他的文件,需要使用classpath。


<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">

    <import resource="classpath:ba06/spring-school.xml"/>
    <import resource="classpath:ba06/spring-student.xml"/>

    <import resource="classpath:ba06/spring-*.xml"/>

beans>

4.2基于注解的DI(注解为主,配置文件为辅)

基于注解的DI:使用spring提供的注解,完成java对象的创建,属性赋值。

4.21注解使用的核心步骤

1.在源代码加入注解,例如@Component。

2.在Spring的配置文件,加入组件扫描器的标签。

    <context:component-scan base-package="注解所在的包名"/>
4.22注解介绍

1.创建对象的注解

@Component 普通jiava对象

@Respository dao对象,持久层对象,表示对象能访问数据库。

@Service service对象,业务层对象,处理业务逻辑,具有事务能力。

@Controller 控制器对象,接受请求,显示请求处理的结果。

2.简单类型属性赋值

@Value

3.引用类型赋值

@Autowired:spring提供的注解,支持byName,byType

​ @Autowired:默认就是byType

​ @Autowired @Qualifier:使用byName

@Resource:来自jdk中的注解,给引用类型赋值的,默认是byName

​ @Resource:先使用byName,在byType

​ @Resource(name=“bean的名称”):只使用byName注入。

@Component
/**
* @Component: 表示创建对象,对象放到容器中。作用是
 *       属性:value,表示对象名称,也就是bean的id属性值
 *       位置:在类的上面,表示创建子类的对象。
 *@Component(value = "myStudent")等同于
 * 
 *
 * 和@Component功能相同的创建对象的注解。
 * 1)@Repository:放在dao接口的实现类上面,表示创建dao对象,持久层对象。能访问数据库
 * 2)@Service  :放在业务层接口的实现类上面,表示创建业务层对象,业务层对象有事务的功能。
 * 3)@Controller:放在控制器类上面,表示创建控制器对象。属于表示层对象。
 *                  控制器对象能接受请求,把请求的处理结果显示给用户。
 *   以上四个注解都能创建对象,但是@Repository  @Service  @Controller有角色说明,表示对象是分层的。
 *   对象是属于不同层的,具有额外的功能。
* */
//使用value 指定对象的名称。
//@Component(value = "myStudent")
//省略value
@Component("myStudent")
//    没有提供自定义对象名称,使用框架的默认独享名称:类名首字母小写。
//@Component
public class Student {
多个包扫描直接的配置文件

    <context:component-scan base-package="com.sunny.ba01"/>



    <context:component-scan base-package="com.sunny.ba01"/>
    <context:component-scan base-package="com.sunny.ba02"/>


    <context:component-scan base-package="com.sunny.ba01;com.sunny.ba02"/>


    <context:component-scan base-package="com.sunny"/>
    
4.23简单属性的赋值@Value

​ 这个只是基本的使用格式,还可以外部提供值。

    /*
    * 简单类型的属性赋值:@value
    * @Value :简单类型属性赋值
    *    属性:value 简单类型属性值
    *    位置:1)在属性定义的上面,无需set方法,推荐使用。
    *          2)在set方法的上面
    * */
    @Value(value = "李四")
    private String name;

    private int age;

    public Student(){
        System.out.println("Student 无参数构造方法");
    }

    public void setName(String name) {
        this.name = name;
    }
    @Value(value = "20")
    public void setAge(int age) {
        System.out.println("setAge===="+age);
        this.age = age;
    }
4.24配置文件赋值

​ resources文件下新建 myconf.properties。在applicationContext.xml文件中配置。

    <context:property-placeholder location="classpath:/myconf.properties"/>
    @Value("${myname}")
    @Value(value = "${myage}")
4.25@Autowired 注解byType方法
    /**
    * 引用类型
     * @Autowired: spring框架提供的,给引用类型赋值的,使用自动注入原理。
     *              支持byName,byType。默认是byType。
     *          位置:1)在属性定义的上面,无需set方法,推荐使用
     *               2)在set方法上面
    * */
    //默认使用byType
    @Autowired
    private School school;
4.26@Autowired 注解byName方法
    /*     
	 * byName自动注入:
     * 1)@Autowired:给引用类型赋值
     * 2)@Qualifer(value="bean的id"):从容器中找到指定名称的对象,
     *                                  把这个对象赋值给引用类型。
    * */
    //byName
    @Autowired
    @Qualifier(value = "myschool")
    private School school;

推荐用true @Autowired

     *          属性:required:boolean类型的属性,默认为true
     *               true:spring在启动的时候,创建容器对象的时候,会检查引用类型是否赋值成功。
     *                    如果赋值失败,终止程序执行,并报错。
     *               false:引用类型赋值失败,程序正常执行,不报错。引用类型的值是null
	//byName
    @Autowired(required = false)
    @Qualifier(value = "myschoolaaa")
    private School school;
4.27 @Resource
    /**
    * 引用类型
     * @Resource: 来自jdk中,给引用类型赋值的,支持byName,byType,默认是byName
     *            Spring框架支持这个注解的使用。
     *       位置:1)在属性定义的上面,无需set方法,推荐使用
     *            2)在set方法的上面。
     *   说明,使用jdk1.8带有@Resource注解,高于jdk1.8没有这个@Resource,需要加一个依赖。
     *       
     *       javax.annotation
     *       javax.annotation-api
     *       1.3.2
     *     
    * */
    //默认byName自动注入
    //先使用byName赋值,如果赋值失败,再使用byType.
    //本例是byType赋值成功
    @Resource
    private School school;
    //只用byName自动注入

    @Resource(name = "mySchool")
    private School school;

5.总结

​ loC:管理对象的,把对象放在容器中,创建,赋值,管理依赖关系。

​ loC:通过管理对象,实现解耦合。loC解决处理业务逻辑对象之间的耦合关系,也就是service和dao之间的解耦合。

spring作为容器适合管理什么对象:

1)service对象,dao对象。

2)工具类对象

不适合交给spring的对象?

1)实体类。比如动态的对象,用户输入的信息创建的对象,mybatis查出来的对象。

2)servlet,listener,filter等web中的对象。他们是tomcat创建和管理的。

你可能感兴趣的:(Spring核心技术,spring,java)