• Spring


    一、概述

    1、什么是spring

    一个java框架、java语言开发,轻量级、开源框架、可以在j2se、j2ee中都可以使用

    核心技术:ioc aop

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

    spring作用,实现解耦合,解决模块之间的耦合

    2、spring地址

    https://spring.io

    3、优点

    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 不排斥各种优秀的开源框架

    二、控制反转

    1、简述

    IOC(控制反转)和DI(依赖注入)是一件事(把对对象的创建、管理、属性赋值等使用交给spring容器),IOC是理论 DI是理论的技术实现

    BeanFactory接口

    (1) spring的原始接口,针对原始接口的实现类功能较为单一

    (2)BeanFactory接口实现类的容器,特点是每次在获得对象时才会创建对象

    ApplicationContext接口

    (1)每次容器启动时就会创建容器中配置的所有对象

    (2)提供了更多功能

    (3)从类路径下加载配置文件: ClassPathXmlApplicationContext

    从硬盘的绝对路径下加载配置文件:FileSystemXmlApplication

    2、程序测试

    idea创建一个基于maven骨架的maven-archetype-quickstart项目,引入以下依赖

    1. <!--spring核心依赖-->
    2. <dependency>
    3. <groupId>org.springframework</groupId>
    4. <artifactId>spring-context</artifactId>
    5. <version>5.3.8</version>
    6. </dependency>
    7. <!--做测试用-->
    8. <dependency>
    9. <groupId>junit</groupId>
    10. <artifactId>junit</artifactId>
    11. <version>4.11</version>
    12. <scope>test</scope>
    13. </dependency>
    14. <plugin>
    15. <artifactId>maven-compiler-plugin</artifactId>
    16. <version>3.1</version>
    17. <configuration>
    18. <source>1.8</source>
    19. <source>1.8</source>
    20. </configuration>
    21. </plugin>

    resources目录下创建配置文件 , 文件名可以随意,但 Spring 建议的名称为 applicationContext.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"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    
        <!--声明对象
            id:自定义对象名称,唯一值,可以没有,spring提供默认名称
            class:spring根据反射创建对象放在容器中,class不能是接口
            spring根据id class创建对象,把对象放入到spring的一个map对象map(id,对象)
        -->
        <bean id="studentService" class="org.example.demo1.service.imp.StudentServiceImpl"/>
        <!--也可以创建非自定义对象-->
        <bean id="myDate" class="java.util.Date"/>
    
    </beans>

    测试

    @Test
        public void test() {
            /**
             * 1、从classpath加载配置文件,这里直接在resource目录下,可以自定义目录
             * 2、容器对象ApplicationContext是一个接口,通过实现类ClassPathXmlApplicationContext加载文件,
             * 获取其他java对象
             * 3、ApplicationContext 容器,会在容器对象初始化时,读取配置文件将其中的所有对象一次性全部装配好放在map中
             * 4、spring默认使用的是无参构造方法创建对象
             */
            String bean = "beans.xml";
            ApplicationContext ctx = new ClassPathXmlApplicationContext(bean);
            StudentService service= (StudentService)ctx.getBean("studentService");
            service.sayHello();
        }

    3、多个配置文件引入

    在实际应用里,随着应用规模的增加,系统中 Bean 数量也大量增加,导 致配置文件变得非常庞大、臃肿。为了避免这种情况的产生,提高配置文件的 可读性与可维护性,可以将 Spring 配置文件分解成多个配置文件 多个配置文件中有一个总文件,总配置文件将各其它子文件通过 引入。在 Java 代码中只需要使用总配置文件对容器进行初始化即 可

    <?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">
    
        <import resource="beanStudent.xml"/>
        <import resource="classpath:com/test/test.xml"/>
        <bean id="studentService" class="org.example.demo1.service.imp.StudentServiceImpl"/>
    </beans>

    也可使用通配符*。但,此时要求父配置文件名不能满足*所能匹配的格 式,否则将出现循环递归包含。就本例而言,父配置文件不能匹配 spring- *.xml 的格式,即不能起名为 spring-total.xml。

    三、基于xml的DI

    在xml配置文件中使用标签完成对象创建、属性赋值

    1、set注入(设值注入)推荐

    <?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">
    
        <!--
        1、自定义对象进行set注入
        set 注入也叫设值注入是指,通过 setter 方法传入被调用者的实例。
        这种注入方式简单、直观,因而在 Spring 的依赖注入中大量使用。-->
        <bean id="student" class="org.example.demo1.Student">
            <!--简单属性赋值-->
            <property name="name" value="abc"/><!--setName("abc)"-->
            <property name="age" value="18"/>
            <!--当指定 bean 的某属性值为另一 bean 的实例时,通过 ref 指定它们间的引
            用关系。ref 的值必须为某 bean 的 id 值-->
            <property name="school" ref="school"/>
        </bean>
    
        <bean id="school" class="org.example.demo1.School">
            <property name="name" value="清华"/>
            <property name="id" value="1"/>
        </bean>
    
    
        <!--2、非自定义对象set注入-->
        <bean id="myDate" class="java.util.Date">
            <property name="time" value="1655698332000"/>
        </bean>
    
    </beans>

    2、构造注入

    public class Student {
        private String name;
        private Integer age;
        private School school;
    
        public Student(String name, Integer age, School school) {
            System.out.println("调用了构造注入方法创建对象和属性赋值");
            this.name = name;
            this.age = age;
            this.school = school;
        }
    }
    <?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">
    
        <!--构造注入,使用name-->
        <bean id="student1" class="org.example.demo1.Student">
            <constructor-arg name="age" value="12"/>
            <constructor-arg name="name" value="abc"/>
            <constructor-arg name="school" value="mySchool"/>
        </bean>
        <!--构造注入,使用index,index表示参数位置-->
        <bean id="student2" class="org.example.demo1.Student">
            <constructor-arg index="1" value="12"/>
            <constructor-arg index="0" value="abc"/>
            <constructor-arg index="2" value="mySchool"/>
        </bean>
        <!--构造注入,省略index属性-->
        <bean id="student3" class="org.example.demo1.Student">
            <constructor-arg index="1" value="12"/>
            <constructor-arg index="0" value="abc"/>
            <constructor-arg index="2" value="mySchool"/>
        </bean>
    
        <bean id="mySchool" class="org.example.demo1.School">
            <property name="id" value="1"/>
            <property name="name" value="清华"/>
        </bean>
    </beans>

    非定义对象构造注入演示

        <bean id="myFile" class="java.io.File">
            <constructor-arg name="parent" value="d:\\test"/>
            <constructor-arg name="child" value="test.txt"/>
        </bean>

    注:引用类型自动注入

    说明set注入和构造注入时,对于引用类型使用的是ref引入,但是 对于引用类型属性的注入,也可不在配置文件中显示的注入。可以通过为 标签设置 autowire 属性值,为引用类型属性进行隐式自动注入(默 认是不自动注入引用类型属性)。根据自动注入判断标准的不同,可以分为两 种:

    2.1、byName

    当配置文件中被调用者 bean 的 id 值与代码中调用者 bean 类的属性名相 同时,可使用 byName 方式,让容器自动将被调用者 bean 注入给调用者 bean。容器是通过调用者的 bean 类的属性名与配置文件的被调用者 bean 的 id 进行比较而实现自动注入的。

    2.2、byType

    使用 byType 方式自动注入,要求:配置文件中被调用者 bean 的 class 属 性指定的类,要与代码中调用者 bean 类的某引用类型属性类型同源。即要么 相同,要么有 is-a 关系(子类,或是实现类)。但这样的同源的被调用 bean 只能有一个。多于一个,容器就不知该匹配哪一个了。

    四、基于注解的DI

    对于 DI 使用注解,将不再需要在 Spring 配置文件中声明 bean 实例。 Spring 中使用注解,需要在原有 Spring 运行环境基础上再做一些改变。 需要在 Spring 配置文件中配置组件扫描器,用于在指定的基本包中扫描 注解。 启动之后加载配置文件,框架扫描包会找到类中所有注解,遇到注解按照注解表示的功能去创建对象,给属性赋值

    <?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 https://www.springframework.org/schema/context/spring-context.xsd">
    
        <!--第一种:使用多个component-scan指定包-->
        <context:component-scan base-package="org.example.demo1"/>
        <context:component-scan base-package="org.example.demo2"/>
        <!--第二种:base-package分隔符可以使用逗号(,)分号(;)还可以使用空格,不建议使用空格-->
        <context:component-scan base-package="org.example.demo1;org.example.demo2"/>
        <!--第三种:base-package 是指定到父包名,base-package 的值表是基本包,容器启动会扫描包及其子包中的注解,当
    然也会扫描到子包下级的子包。所以 base-package 可以指定一个父包就可
    以。但不建议使用顶级的父包,扫描的路径比较多,导致容器启动时间变慢-->
        <context:component-scan base-package="org"/>
    </beans>

    1、4个定义Bean的注解

    /**
     * Component注解表示创建对象放到容器中,等同于
     * <bean id="myStudent" class="com.demo.student"/>
     */
    @Component(value = "myStudent")
    //@Component("myStudent") value可以不写
    //@Component 不写自定义对象名称 框架默认类型首字母小写
    public class Student {
        private String name;
        private Integer age;
    }
    另外,Spring 还提供了 3 个创建对象的注解:
    @Repository 用于对 DAO 实现类进行注解
    @Service 用于对 Service 实现类进行注解
    @Controller 用于对 Controller 实现类进行注解
    
    这三个注解与@Component 都可以创建对象,但这三个注解还有其他的含义,
    @Service 创建业务层对象,业务层对象可以加入事务功能,
    @Controller 注解创建的对象可以作为处理器接收用户的请求。
    @Repository,@Service,@Controller 是对@Component 注解的细
    化,标注不同层的对象。即持久层对象,业务层对象,控制层对象。
    
    当前对象不是持久层、业务层、控制层的时候最好使用component

    2、简单属性的注入

    @Component(value = "myStudent")
    public class Student {
        /**
         * 简单类型属性赋值@value
         *      位置1:属性定义上面 无需set方法 推荐使用
         *      位置2:set方法上面
         */
        @Value("abc")
        private String name;
        
        private Integer age;
        @Value("20")
        public void setAge(Integer age) {
            this.age = age;
        }
    }
    
    
    <?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 https://www.springframework.org/schema/context/spring-context.xsd">
    
        <context:component-scan base-package="org.example.demo1"/>
    </beans>
    
    
    @Test
        public void test() {
            String bean = "applicationContext.xml";
            ApplicationContext ctx = new ClassPathXmlApplicationContext(bean);
            Student s= (Student)ctx.getBean("myStudent");
            System.out.println(s.toString());
        }

    当然上面的value可以使用外部配置文件中的值

    @Component(value = "myStudent")
    public class Student {
        @Value("${myname}")//读取配置文件中的值
        private String name;
        @Value("${age}")
        private Integer age;
     }
    
    <?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 https://www.springframework.org/schema/context/spring-context.xsd">
    
        <context:component-scan base-package="org.example.demo1"/>
        <!--使用property-placeholder加载properties文件-->
        <context:property-placeholder location="stu.properties"/>
    </beans>
    
    
    stu.properties配置文件
    myName=abc
    age=12
    
    
    @Test
        public void test() {
            String bean = "applicationContext.xml";
            ApplicationContext ctx = new ClassPathXmlApplicationContext(bean);
            Student s= (Student)ctx.getBean("myStudent");
            System.out.println(s.toString());
        }

    3、按类型自动注入引用属性

    1. @Component(value = "myStudent")
    2. public class Student {
    3. /**
    4. * Autowired属性,spring框架提供给引用类型赋值 使用自动注入原理实现支持byName byType默认byType
    5. * 位置:
    6. * 1、属性值上面 无需set 推荐使用
    7. * 2set方法上面
    8. */
    9. @Autowired
    10. private School school;
    11. private String name;
    12. private Integer age;
    13. public Integer getAge() {
    14. return age;
    15. }
    16. public void setAge(Integer age) {
    17. this.age = age;
    18. }
    19. public String getName() {
    20. return name;
    21. }
    22. public void setName(String name) {
    23. this.name = name;
    24. }
    25. @Override
    26. public String toString() {
    27. return "Student{" +
    28. "school=" + school +
    29. ", name='" + name + '\'' +
    30. ", age=" + age +
    31. '}';
    32. }
    33. }
    34. <?xml version="1.0" encoding="UTF-8"?>
    35. <beans xmlns="http://www.springframework.org/schema/beans"
    36. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    37. xmlns:context="http://www.springframework.org/schema/context"
    38. xsi:schemaLocation="http://www.springframework.org/schema/beans
    39. http://www.springframework.org/schema/beans/spring-beans.xsd
    40. http://www.springframework.org/schema/context
    41. https://www.springframework.org/schema/context/spring-context.xsd">
    42. <context:component-scan base-package="org.example.demo1"/>
    43. </beans>
    44. @Test
    45. public void test() {
    46. String bean = "applicationContext.xml";
    47. ApplicationContext ctx = new ClassPathXmlApplicationContext(bean);
    48. Student s= (Student)ctx.getBean("myStudent");
    49. System.out.println(s.toString());
    50. }

    4、按 名称自动注入引用属性

    @Component(value = "myStudent")
    public class Student {
        //给引用类型赋值 默认required为true表示容器创建对象时检查引用类型,
        // 失败启动会抛出异常,false程序正常执行,引用类型的值为null 推荐默认即true
        @Autowired(required = true)
        @Qualifier("mySchool")//从容器中找到指定名称对象 把这个对象赋值给引用类型
        private School school;
    
        private String name;
        private Integer age;
    }

    5、jdk注解自动属性注入

    @Component(value = "myStudent")
    public class Student {
        /**
         *jdk中的注入引用类型属性注解,spring支持其使用 支持byName、byType
         *位置:1)、属性上面,无需set,推荐使用
         *     2)、set上面
         *赋值:先按byName赋值,即容器中差school的,没有查到按照byType注入
         *说明:jdk高于1.8是没有resource注解 需要加入javax.annotation-api依赖
         *只按照byName注入:@Resource(name="mySchool")使用name属性表示只能按照名称注入
         */
        @Resource
        private School school;
        private String name;
        private Integer age;
    }

    五、注解和xml的对比

    注解为主 xml为辅

    引入别人jar,如果要注入一般xml

    六、IOC总结

    IOC解决的是业务逻辑对象之间的耦合关系,也就是service和dao之家的解耦合

    1)、spring容器适合管理哪些对象

    servi1ce 、dao对象

    工具类对象

    2)、适合管理对象

    实体对象

    servle、listener、filter等web中的对象,他们是tomcat创建和管理的

    参考地址

    bilibili.com/video/BV1hN411X77N?p=18&spm_id_from=pageDriver&vd_source=f795d6b757455528005051cfa124da7f

    【尚硅谷】Spring框架视频教程(spring5超详细源码级讲解)_哔哩哔哩_bilibili

    Spring框架总结【无比详细】_itcats_cn的博客-CSDN博客_spring

  • 相关阅读:
    一个类在什么时候会被加载
    python profile 性能分析
    Linux学习记录——삼십일 socket编程---TCP套接字
    全科医学科常用评估量表汇总,建议收藏!
    链接文件学习(七):英飞凌MCU Tasking编译器LSL链接文件解析 及代码变量定位方法
    优化数据中心机架和设备的 5 个理由
    LCR 150.彩灯装饰记录 II
    动态规划:背包问题
    java LinkedList集合特有功能
    方舟综合指令代码大全系统综合
  • 原文地址:https://blog.csdn.net/qq_34491508/article/details/125475629