spring学习-狂神说-day01

一、什么是spring

Spring框架是由于软件开发的复杂性而创建的。Spring使用的是基本的JavaBean来完成以前只可能由EJB完成的事情。然而,Spring的用途不仅仅限于服务器端的开发。从简单性、可测试性和松耦合性角度而言,绝大部分Java应用都可以从Spring中受益。
◆目的:解决企业应用开发的复杂性
◆功能:使用基本的JavaBean代替EJB,并提供了更多的企业应用功能
◆范围:任何Java应用
Spring是一个轻量级控制反转(IoC)和面向切面(AOP)的容器框架。
SSH:Struct2+spring +Hibernate
SSM:SpringMvc+Spring+mybatis
maven引用:
<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>5.2.8.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-jdbc</artifactId>
    <version>5.2.8.RELEASE</version>
</dependency>

优点:

  • Spring是一个开源的免费的框架(容器)
  • Spring是一个轻量级的,非入侵式的框架
  • 控制反转(IOC)和面向切面编程(AOP)
  • 支持事务的处理
  • 对框架整合的支持

总结一句话:Spring是一个轻量级的控制反转(IOC)和面向切面编程(AOP)的框架

Spring的组成:

Spring学习计划

 

 

 

 Spring Boot

  • 一个快速开发的脚手架
  • 基于Springboot可以快速开发单个微服务
  • 约定大于配置

SpringCloud

  • SpringCloud是基于SpringBoot实现的

因为现在大多数公司的使用SpringBoot进行快速 开发,学习SpringBoot的前提,需要完成掌握Spring及SpringMVC,承上启下作用,SpringBoot又是学习SpringCloud的基础。

  

 缺点:需要有很多配置

 

二、IOC理论指导

原来方式:

1、UserDao接口

2、UserDaoImpl

3、UserService业务接口

4、UserServiceImpl业务实现类

在我们的之前的业务中,用户的需求可能会影响我们原来的代码,我们需要根据用户的需求去修改原代码,如果程序代码量十分大,修改一次的成本就十分昂贵

我们使用了一个Set接口实现,已发生了革命必的变化:

 private IUserDao userDao;
 public void SetUserDao(IUserDao userDao){
       this.userDao = userDao;
 }

之前程序是主动创建对象,控制权在程序员手上,

使用了set注入后,程序不再具有主动性,而是变成了被动接受对象,由使用者在外面指定创建什么类型的对象。

这种思想,从本质上解决了问题,我们程序员不用再去管理对象的创建了。系统的耦合性大大降低,可以更加专注 在业务的实现上。

 

 

 

 

 

 

 

 Ioc—Inversion of Control,即“控制反转”,不是什么技术,而是一种设计思想。在Java开发中,Ioc意味着将你设计好的对象交给容器控制,而不是传统的在你的对象内部直接控制。

 

 

 采用XML方式配置Bean的时候,Bean的定义信息和实现分离的,而采用注解的方式可以把两合为一体;Bean的定义信息直接以注解的形式定义在实现类中,从则达到了零配置的目的。

控制反转是一种通用描述(XML配置或注解),并通过第三方去生产或获取特定对象的方式,在Spring中实现控制返回的是IOC容器,其实现方法是依赖注入(Dependency Injection DI).

以下为HelloDemo的程序:

Hello类定义:

package com.fengfang.dao;

/**
 * @Description TODO
 * @Author liuxh
 * @Date 2020/8/11 15:23
 **/
public class Hello {
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void show(){
        System.out.println("hello " +name);
    }
}

配置文件内容:

<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">
<!--    使用Spring来创建对象,在SPring中,这些都称为bean
    bean等于对象,new hello()
    Hello hello = new Hello();
    类型 变量名 = new 类型();
    id 变量名
    class new 的对象
    property:相当于对象中的属性设置
-->
    <bean id="hello" class="com.fengfang.dao.Hello" >
        <property name="name" value="testaa"></property>
    </bean>
</beans>

测试代码:

package com.fengfang.test;

import com.fengfang.dao.Hello;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * @Description TODO
 * @Author liuxh
 * @Date 2020/8/11 15:25
 **/
public class HelloTest {
    public static void main(String[] args) {
//        获取Spring的上下文对象
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
//      我们的对象现在都在spring管理
        Hello hello = (Hello) context.getBean("hello");
        hello.show();
    }
}

测试结果如下:

 

 

 IOC创建对象的方式:

  • 使用无参构造函数创建对象
  • 假设我们要使用有参构造函数创建对象 
  1. 下标赋值  
<!--    使用有参构造函数:下标赋值-->
    <bean id="userNew" class="com.fengfang.domain.User">
        <constructor-arg index="0" value="这是一个测试名称"></constructor-arg>
    </bean>
  1. 使用参数的类型匹配
    <!--    使用有参构造函数:类型赋值,有多个参数会有问题不建议使用-->
    <bean id="userType" class="com.fengfang.domain.User">
        <constructor-arg type="java.lang.String" value="这是一个测试名称"></constructor-arg>
    </bean>
  1. 使用参数名称来创建:
<!--    使用有参构造函数:参数名称赋值-->
    <bean id="user" class="com.fengfang.domain.User">
        <constructor-arg name="name" value="这是一个测试名称"></constructor-arg>
    </bean>

 Spring的bean中,若有定义了,就算没有被调用实例化,也会发现这个实例已经在容器中创建了。

如测试代码:

package com.fengfang.domain;

/**
 * @Description TODO
 * @Author liuxh
 * @Date 2020/8/11 17:28
 **/
public class Student {
    private String name;
    public Student(){
        System.out.println("这是Student无参构造函数!");
    }
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                '}';
    }
}
package com.fengfang.domain;

/**
 * @Description TODO
 * @Author liuxh
 * @Date 2020/8/11 17:05
 **/
public class User {
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                '}';
    }

//    public User() {
//        System.out.println("user的无参构造函数!");
//
//    }
//
    public User(String name){
        this.name = name;
    }
}

<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">
<!--    这是敷衍无参构照函数来实现-->
 <!--   <bean id="user" class="com.fengfang.domain.User">
        <property name="name" value="liuxh"></property>
    </bean>-->
<!--    使用有参构造函数:下标赋值-->
 <!--   <bean id="user" class="com.fengfang.domain.User">
        <constructor-arg index="0" value="这是一个测试名称"></constructor-arg>
    </bean>-->
    <!--    使用有参构造函数:类型赋值,有多个参数会有问题不建议使用-->
 <!--   <bean id="user" class="com.fengfang.domain.User">
        <constructor-arg type="java.lang.String" value="这是一个测试名称"></constructor-arg>
    </bean>-->
<!--    使用有参构造函数:参数名称赋值-->
    <bean id="user" class="com.fengfang.domain.User">
        <constructor-arg name="name" value="这是一个测试名称"></constructor-arg>
    </bean>
    <bean id="student" class="com.fengfang.domain.Student"></bean>
</beans>

上面是类代码及beans的配置文件

测试代码:

package com.fengfang.test;

import com.fengfang.domain.User;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * @Description TODO
 * @Author liuxh
 * @Date 2020/8/11 17:07
 **/
public class UserTest {
    public static void main(String[] args) {
//        User user = new User();
//        Spring容器,就类似于婚介网站
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
//        这里并没有获取Student类,但是发会现Student的无参构造函数也被初始化了
        User myUser = (User) context.getBean("user");
        System.out.println(myUser.toString());
    }
}

执行测试结果发现,两个实例的构造函数都有执行,如下图:

三:Spring配置 

  1. 别名
<!--    设置user的别名为userAlias-->
    <alias name="user" alias="userAlias"/>

在测试代码里面使用别名也可以调用:

package com.fengfang.test;

import com.fengfang.domain.User;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * @Description TODO
 * @Author liuxh
 * @Date 2020/8/11 17:07
 **/
public class UserTest {
    public static void main(String[] args) {
//        User user = new User();
//        Spring容器,就类似于婚介网站
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
//        这里并没有获取Student类,但是发会现Student的无参构造函数也被初始化了
        User myUser = (User) context.getBean("userAlias");
        System.out.println(myUser.toString());
    }
}

 

  1. Bean配置

 

<!--    id 为bean的唯一标识符,也就是相当于我们学的对象名
        class :bean对象对应的全限定类名:包名+类名
        name :也是别名,可以取多个别名如:name='n1,n2'
        property:
            name:
            value:
-->
  <bean id="user" class="com.fengfang.domain.User">
       <property name="name" value="liuxh"></property>
   </bean>

 

  1. Import

这个import,一般用于团队开发使用,他可以将多个配置文件,导入合并为一个

假设,项目项目中有三个人开发,分别是张三,李四和王五,这三个人复制不同的类开发,不同的类需要注册在不同的bean中,我们可以使用import将所有人的bean.xml合并为一个总的,如总的配置文件为applicationContext.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">
    <import resource="beans2.xml"/>
    <import resource="beans.xml"/>
    <import resource="beans3.xml" />
</beans>

 

使用时,就直接使用applicationContext.xml载入就行,会将所有bean在容器中初始化。

四:依赖注入(DI)

1、构造器注入,前面已经说过

2、Set方式注入【重点】

 依赖注入:set注入

  • 依赖:bean对象的创建依赖容器
  • 注入:bean对象的所有属性,由容器来注入

环境搭建:

1、复杂类型

package com.fengfang.domain;

/**
 * TODO
 *
 * @author liuxh
 * @date 2020/8/11 21:38
 **/
public class Address {
    private String address;

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }
}

2、真实测试对象

package com.fengfang.domain;

import java.util.*;

/**
 * TODO
 *
 * @author liuxh
 * @date 2020/8/11 21:38
 **/
public class Student {
    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", address=" + address +
                ", books=" + Arrays.toString(books) +
                ", hobys=" + hobys +
                ", age=" + age +
                ", card=" + card +
                ", games=" + games +
                ", info=" + info +
                ", wife='" + wife + '\'' +
                '}';
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Address getAddress() {
        return address;
    }

    public void setAddress(Address address) {
        this.address = address;
    }

    public String[] getBooks() {
        return books;
    }

    public void setBooks(String[] books) {
        this.books = books;
    }

    public List<String> getHobys() {
        return hobys;
    }

    public void setHobys(List<String> hobys) {
        this.hobys = hobys;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public Map<String, String> getCard() {
        return card;
    }

    public void setCard(Map<String, String> card) {
        this.card = card;
    }

    public Set<String> getGames() {
        return games;
    }

    public void setGames(Set<String> games) {
        this.games = games;
    }

    public Properties getInfo() {
        return info;
    }

    public void setInfo(Properties info) {
        this.info = info;
    }

    public String getWife() {
        return wife;
    }

    public void setWife(String wife) {
        this.wife = wife;
    }

    private String name;
    private Address address;
    private String[] books;
    private List<String> hobys;
    private Integer age;
    private Map<String,String> card;
    private Set<String> games;
    private Properties info;
    private String wife;
}

3、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
        https://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean id="student" class="com.fengfang.domain.Student">
        <property name="name" value="aaron"></property>
    </bean>
</beans>

4、测试类

package com.fengfang.test;

import com.fengfang.domain.Student;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * TODO
 *
 * @author liuxh
 * @date 2020/8/12 10:03
 **/
public class DITest {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        Student student = (Student) context.getBean("student");
        System.out.println(student.getName());
    }
}

对于属性注入有很多类型可以注入,如下面配置文件示例:

<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">
    <bean id="student" class="com.fengfang.domain.Student">
<!--        普通类型注入-->
        <property name="name" value="aaron"></property>
<!--        bean 注入,直接用ref-->
        <property name="address" ref="address"/>
<!--        数组注入-->
        <property name="books">
           <array>
               <value>红楼梦</value>
               <value>我的自白</value>
               <value>活着</value>
               <value>西游记</value>
           </array>
        </property>
<!--        list注入-->
        <property name="hobys">
            <list>
                <value>电影</value>
                <value>唱歌</value>
                <value>跳舞</value>
            </list>
        </property>
<!--        map注入-->
        <property name="card">
            <map>
                <entry key="身份证" value="123456789"></entry>
                <entry key="银行卡" value="987654321"></entry>
            </map>
        </property>
<!--        set 注入-->
        <property name="games">
            <set>
                <value>LOL</value>
                <value>王者</value>
                <value>红警</value>
            </set>
        </property>
<!--        properties注入-->
        <property name="info">
            <props>
                <prop key="driver">val1</prop>
                <prop key="url">val2</prop>
                <prop key="username">val3</prop>
                <prop key="password">val3</prop>
            </props>
        </property>
        <property name="age" value="25"></property>
<!--        对于null的注入-->
        <property name="wife">
            <null/>
        </property>
    </bean>
<!--    定义一个新的bean-->
    <bean id="address" class="com.fengfang.domain.Address">
        <property name="address" value="广东省东莞市"></property>
    </bean>
</beans>

3、拓展方式注入

使用C命名空间或P命名空间

1、若使用P命名空间,其实是基于Set注入方式

在配置文件引入约束,下面品红色部分内容

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

定义方式:p:属性名称

  <bean id="user" class="com.fengfang.domain.User" p:name="aaron" p:age="20" p:address="广东东莞">
    </bean>

测试代码:

 @Test
    public void testPnamespace(){
        ApplicationContext context = new ClassPathXmlApplicationContext("user.xml");
        User user = context.getBean("user", User.class);
        System.out.println(user);
    }

测试发现是可以对属性进行注入成功的:

 

 2、若使用C命名空间方式,则是基于构造注入方式

增加约束内容,下面品红色内容

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:c="http://www.springframework.org/schema/c"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd">

在类中需增加有参和无参构造函数

package com.fengfang.domain;

/**
 * @Description TODO
 * @Author liuxh
 * @Date 2020/8/12 10:49
 **/
public class Teacher {
    private String name;
    private Integer age;
    private String courseName;

    public Teacher() {
    }

    public Teacher(String name, Integer age, String courseName) {
        this.name = name;
        this.age = age;
        this.courseName = courseName;
    }

    @Override
    public String toString() {
        return "Teacher{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", courseName='" + courseName + '\'' +
                '}';
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public String getCourseName() {
        return courseName;
    }

    public void setCourseName(String courseName) {
        this.courseName = courseName;
    }
}

定义也和P类型

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:c="http://www.springframework.org/schema/c"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd">
<!--  原来方式-->
 <!--   <bean id="teacher" class="com.fengfang.domain.Teacher">
        <constructor-arg name="name" value="刘东东"></constructor-arg>
        <constructor-arg name="age" value="26"></constructor-arg>
        <constructor-arg name="courseName" value="英语"></constructor-arg>
    </bean>-->
    <bean id="teacher" class="com.fengfang.domain.Teacher" c:name="刘东东" c:age="25" c:courseName="英语"></bean>
</beans>

测试代码和结果展示:

 五、作用域

ScopeDescription

singleton

(Default) Scopes a single bean definition to a single object instance for each Spring IoC container.

prototype

Scopes a single bean definition to any number of object instances.

request

Scopes a single bean definition to the lifecycle of a single HTTP request. That is, each HTTP request has its own instance of a bean created off the back of a single bean definition. Only valid in the context of a web-aware Spring ApplicationContext.

session

Scopes a single bean definition to the lifecycle of an HTTP Session. Only valid in the context of a web-aware Spring ApplicationContext.

application

Scopes a single bean definition to the lifecycle of a ServletContext. Only valid in the context of a web-aware Spring ApplicationContext.

websocket

Scopes a single bean definition to the lifecycle of a WebSocket. Only valid in the context of a web-aware Spring ApplicationContext.

1、单例模式

默认使用单例模式,我们发现两个创建的实例是一致的,即如下结果比对:

   <bean id="user" class="com.fengfang.domain.User" p:name="aaron" p:age="20" p:address="广东东莞" scope="singleton">
    </bean>

 

 2、原型模式

<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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean id="user" class="com.fengfang.domain.User" p:name="aaron" p:age="20" p:address="广东东莞" scope="prototype">
    </bean>
</beans>

测试比对结果发现是不一致的

 

 3、其它模式,request、session、application这些只能在Web开发中使用到

 

 

 

posted @ 2020-08-12 11:05  aaron616  阅读(132)  评论(0)    收藏  举报