Spring初识

1.Spring简介

1.1官方文档

官方文档:https://spring.io/

官方下载地址: http://repo.spring.io/release/org/springframework/spring

构建一切--------->协调一切-------->连接一切:

在这里插入图片描述

  • Spring Boot
    • 一个快速开发的脚手架
    • 基于SpringBoot可以快速开发单个微服务
    • 约定大于配置
    • 学习Spring Boot前提是要完全掌握Spring和SpringMVC
  • Spring Cloud
    • 基于Spring Boot实现的

 
依赖:

<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>5.3.13</version>
</dependency>

<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-jdbc</artifactId>
    <version>5.3.13</version>
</dependency>

 

1.2历史,优点,组成

历史:

  • 2002年,首次推出Spring框架的雏形—>interface21框架
  • Spring框架以interface21框架为基础经过重新设计,并不断丰富其内涵,于2004年3.24发布了1.0正式版本
  • Rod Johnson,SpringFramework创始人
  • Spring理念:是现有的技术更加容易使用,本身是一个大杂烩,整合了现有的技术框架
  • 弊端:发展太久,违背了原来的理念,配置变得十分繁琐(“配置地狱”)
  • SSH:Struct2+Spring+Hibernate(全自动持久化框架)
  • SSM:SpringMvc+Spring+Mybatis(半自动持久化框架)

优点:

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

组成:

七大模块在这里插入图片描述

 
 

2.IOC

2.1IOC理论

在这里插入图片描述

1.UserDao里定义一个getUser接口,然后三个实现类,区别只有输出不同:

public class UserDaoImpl implements UserDao {
    @Override
    public void getUser() {
        System.out.println("user");
    }
}

2.业务层接口也是getUser,实现类为:

public class UserServiceImpl implements UserService {
    private UserDao userDao ;
    //用set进行实现动态值的注入
    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }

    @Override
    public void getUser() {
       userDao.getUser();
    }
}

3.测试(用set就可以在测试中修改代码,调用不同的实现类)

public class MyTest {
    public static void main(String[] args) {
        //用户实际接触的是业务层,根本不需要接触dao层
        UserServiceImpl userService = new UserServiceImpl();
        userService.setUserDao(new UserDaoMysqlImpl());
        userService.getUser();
    }
}
  • 之前的业务中,用户的需求会影响我们原来的代码,我们需要按照用户的需求去修改原代码,一旦代码量十分大,修改一次的成本就会十分昂贵。

  • 后来我们使用一个Set接口实现,已经发生了革命性的变化。之前程序是主动创建对象,控制权在程序员手上;使用set注入后,程序不再具有主动性,而是被动接收对象,这就达到了控制反转的效果。

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

 

2.2IOC原理

在这里插入图片描述

控制反转IoC(Inversion of Control),是一种设计思想,DI(依赖注入)是实现IoC的一种方法,也有人认为DI只是IoC的另一种说法。没有IoC的程序中 , 我们使用面向对象编程 , 对象的创建与对象间的依赖关系完全靠编码在程序中,对象的创建由程序自己控制;控制反转后将对象的创建转移给第三方,个人认为所谓控制反转就是:获得依赖对象的方式反转了。

在这里插入图片描述

IOC是Spring框架的核心内容,使用多种方式完美实现了IOC,可以使用XML配置,也可以使用注解,新版本的Spring也可以零配置实现IOC。

Spring容器在初始化时先读取配置文件,根据配置文件或元数据创建与组织对象存入容器中,程序使用时再从Ioc容器中取出需要的对象。

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

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

 
 

3.HelloSpring

3.1项目

  1. 首先建立一个空的maven

  2. 实体类pojo

    package moli.pojo;
    public class Hello {
        private String str;
    
        public String getStr() {
            return str;
        }
        public void setStr(String str) {
            this.str = str;
        }
    
        @Override
        public String toString() {
            return "Hello{" +
                    "str='" + str + '\'' +
                    '}';
        }
    }
    
  3. 配置文件beans.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
            https://www.springframework.org/schema/beans/spring-beans.xsd">
        <!--使用Spring来创建对象,在Spring中这些都被叫做bean,bean=对象
        Hello hello = new Hello()    类型 变量名 = new 类型()
        id=变量名,class=new的对象,property:给对象中的属性设置一个值
        此过程就是一个控制反转的过程!
        -->
        <bean id="hello" class="moli.pojo.Hello">
            <property name="str" value="Spring"/>
        </bean>
    </beans>
    
  4. 测试,实例化容器

    import moli.pojo.Hello;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    public class MyTest {
        public static void main(String[] args) {
            //获取spring的上下文对象
            ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
            //我们的对象都放到了Spring中了,我们需要就到beans里取即可
            Hello hello = (Hello) context.getBean("hello");
            System.out.println(hello.toString());
        }
    }
    
  5. 结果

    在这里插入图片描述

 

3.2解决问题

3.2.1jar包不存在

报错:

在这里插入图片描述

解决方法:

  • 修改maven本地仓库里的setting.xml

    在这里插入图片描述

  • 刷新并重启

    在这里插入图片描述

  • 重启后再次刷新工程

    在这里插入图片描述

 

3.2.2执行main函数报错

报错:

Failed to execute goal org.codehaus.mojo:exec-maven-plugin:3.0.0:exec (default-cli) on project helloSpring: Command execution failed.

解决办法:

  1. idea降版本(2017)

  2. 用单元测试,不去使用main方法。因为maven项目执行main函数的时候需要两个插件:

    • maven-compiler-plugin:用来编译Java文件,指定JDK版本等(可以不导入)

    • exec-maven-plugin:用来执行class文件

      <build>
          <plugins>
              <plugin>
                  <groupId>org.codehaus.mojo</groupId>
                  <artifactId>exec-maven-plugin</artifactId>
                  <version>1.6.0</version>
                  <executions>
                      <execution>
                          <goals>
                              <goal>java</goal>
                          </goals>
                      </execution>
                  </executions>
                  <configuration>
                      <classpathScope>test</classpathScope>
                  </configuration>
              </plugin>
          </plugins>
      </build>
      

 

3.2.3乱码

<properties>
    <!-- 文件拷贝时的编码 -->
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    <!-- 编译时的编码 -->
    <maven.compiler.encoding>UTF-8</maven.compiler.encoding>
</properties>

 

3.3修改IOC理论中的例子

<?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
        https://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean id="Impl" class="moli.dao.UserDaoImpl"/>
    <bean id="MysqlImpl" class="moli.dao.UserDaoMysqlImpl"/>
    <bean id="OracleImpl" class="moli.dao.UserDaoOracleImpl"/>
    <bean id="ServiceImpl" class="moli.service.UserServiceImpl">
        <!--ref:引用spring容器中创建好的对象
        value:一个具体的值,基本数据类型-->
        <property name="userDao" ref="MysqlImpl"/>
    </bean>
</beans>
import moli.service.UserServiceImpl;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MyTest {
    public static void main(String[] args) {
        //获取ApplicationContext:拿到spring的容器
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        //容器在手,需要什么就get什么
        UserServiceImpl serviceImpl = (UserServiceImpl) context.getBean("ServiceImpl");
        serviceImpl.getUser();
    }
}

 

3.4小总结

  • spring的这个过程就叫控制反转 :

    • 控制 : 谁来控制对象的创建 , 传统应用程序的对象是由程序本身控制创建的new ;使用Spring后 , 对象是由Spring来创建的
    • 反转 : 程序本身不创建对象 , 而变成被动的接收对象
  • 依赖注入 : 就是利用set方法来进行注入的,所以实体类中的set方法必须存在,否则spring失效

  • IOC是一种编程思想,由主动的编程变成被动的接收

  • 可以通过ClassPathXmlApplicationContext去浏览一下底层源码

  • 到了现在 , 我们彻底不用再程序中去改动了 , 要实现不同的操作 , 只需要在xml配置文件中进行修改

  • 所谓的IOC,一句话搞定 : 对象由Spring 来创建 , 管理 , 装配 !

 
 

4.IOC创建对象的方式

在配置文件加载的时候,容器中的对象就已将初始化了。

package moli.pojo;
public class User {
    private String name;
    public User(){
        System.out.println("wucan");
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public void show(){
        System.out.println("name="+name);
    }
}
<?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
        https://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean id="user" class="moli.pojo.User">
        <property name="name" value="ming"/>
    </bean>
</beans>
import moli.pojo.User;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MyTest {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        User user = (User) context.getBean("user");
        user.show();
    }
}
  • 使用无参构造创建对象,默认

  • 如果使用有参构造创建对象

    方式一:下标赋值

    <bean id="user" class="moli.pojo.User">
        <constructor-arg index="0" value="ming"/>
    </bean>
    

    方式二:通过类型创建,不建议使用,因为类型可重复

    <bean id="user" class="moli.pojo.User">
        <constructor-arg type="java.lang.String" value="ming"/>
    </bean>
    

    方式三:直接通过参数名来设置,推荐使用

    <bean id="user" class="moli.pojo.User">
        <constructor-arg name="name" value="ming"/>
    </bean>
    

 
 

5.Spring的配置

5.1别名

如果添加了别名,我们也可以用别名来获取对象

<alias name="user" alias="o"/>

5.2bean的配置

bean中的name也是别名,而且分隔符很灵活

<bean id="user" class="moli.pojo.User" name="user1,user2 user3;user4"></bean>

5.3import

一般用于团队开发使用,可以将多个配置文件导入合并为一个总的,直接使用总的配置就可以。

在这里插入图片描述

 
 

6.DI

三类:构造器注入,set方式注入,拓展方式注入

6.1set

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

 

【环境搭建】

  1. 复杂类型

    package moli.pojo;
    public class Address {
        private String address;
        public String getAddress() {return address;}
        public void setAddress(String address) {this.address = address;}
    }
    
  2. 真实测试对象

    package moli.pojo;
    import java.util.*;
    public class Student {
        private String name;
        private Address address;
        private String[] books;
        private List<String> hobbies;
        private Map<String,String> card;
        private Set<String> games;
        private String wife;
        private Properties info;
        //然后敲出这些实体类的get和set
    
  3. beans.xml

    <bean id="address" class="moli.pojo.Address">
        <property name="address" value="黑龙江"/>
    </bean>
    <bean id="student" class="moli.pojo.Student">
            <!--第一种:普通值注入,value-->
            <property name="name" value="小明"/>
            <!--第二种:bean注入,ref-->
            <property name="address" ref="address"/>
            <!--第三种:数组-->
            <property name="books">
                <array>
                    <value>西游记</value>
                    <value>水浒传</value>
                    <value>红楼梦</value>
                </array>
            </property>
            <!--第四种:列表-->
            <property name="hobbies">
                <list>
                    <value>睡觉</value>
                    <value>敲代码</value>
                    <value>打球</value>
                </list>
            </property>
            <!--第五种:map-->
            <property name="card">
                <map>
                    <entry key="身份证" value="1234567"/>
                    <entry key="银行卡" value="1239870"/>
                </map>
            </property>
            <!--第六种:set-->
            <property name="games">
                <set>
                    <value>LOL</value>
                    <value>COC</value>
                    <value>BOB</value>
                </set>
            </property>
            <!--第七种:null-->
            <property name="wife">
                <null/>
            </property>
            <!--第八种:自定义信息-->
            <property name="info">
                <props>
                    <prop key="性别"></prop>
                    <prop key="年龄">19</prop>
                    <prop key="成绩">99</prop>
                </props>
            </property>
    </bean>
    
  4. 测试

    public class MyTest {
        public static void main(String[] args) {
            ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
            Student student = (Student) context.getBean("student");
            System.out.println(student.toString());
        }
    }
    //Student{name='小明', address=Address{address='黑龙江'}, books=[西游记, 水浒传, 红楼梦], hobbies=[睡觉, 敲代码, 打球], card={身份证=1234567, 银行卡=1239870}, games=[LOL, COC, BOB], wife='null', info={性别=男, 成绩=99, 年龄=19}}
    

 

6.2p、c

官方文档:

在这里插入图片描述

 

public class User {
    private String name;
    private int age;
}
//依旧get、set、toString
<?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:c="http://www.springframework.org/schema/c"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd">
     <!--p命名空间注入,可以直接注入属性的值,无参构造,property-->
     <bean id="user" class="moli.pojo.User" p:name="小明" p:age="19"/>
     <!--c命名空间注入,有参构造,construct-args-->
     <bean id="user2" class="moli.pojo.User" c:name="小红" c:age="1"/>
</beans>

 

6.3bean的作用域

在这里插入图片描述

  1. 单例模式(spring的默认模式),永久都是一个

    <bean id="user" class="moli.pojo.User" p:name="小明" p:age="19" scope="singleton"/>
    
  2. 原型模式,每次从容器中get的时候都会产生一个新的对象

    <bean id="user" class="moli.pojo.User" p:name="小明" p:age="19" scope="prototype"/>
    

    在这里插入图片描述

  3. request、session、application在web开发中应用

 
 

7.Bean的自动装配

  • 自动装配是spring满足bean依赖的一种方式
  • spring会在上下文中自动寻找,并自动给bean装配属性

 

在spring中有三种装配方式

  • 在xml中显示的配置
  • 在java中显示的配置
  • 隐式的自动装配bean(重要)

 

7.1测试

一个人有两个宠物

 

7.2byName、byType

<bean id="cat" class="moli.pojo.Cat"/>
<bean id="dog1" class="moli.pojo.Dog"/>
<!--byName:会自动在容器上下文中查找,和自己set对象后面名字相同的beanid,如果id不同则报错-->
<!--byType:会自动在容器上下文中查找,和自己对象属性类型相同的beanclass,id可以不同s可以,但是属性类型要唯一,否则报错-->
<bean id="people" class="moli.pojo.People" autowire="byType">
    <property name="name" value="小明"/>
</bean>

 

7.3使用注解自动装配

jdk1.5支持注解,spring2.5支持注解

使用注解:

  1. 导入约束:context约束

  2. 配置注解支持:context:annotation-config/

    <?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">
    
        <context:annotation-config/>
    
    </beans>
    

 

7.3.1@Autowired

在这里插入图片描述
在这里插入图片描述

  • 直接在属性上使用即可,也可以在set方式上使用

  • 而且使用Autowired我们就可以不再编写set方法了,前提是你这个自动装配的属性在ioc(spring)容器中存在,且符合byType

  • 先通过byType,再通过byName寻找

  • 如果@Autowired自动装配环境比较复杂,自动装配无法通过一个注解( @Autowired)完成的时候,我们可以使用**@Qualifier(value = “xxx”)**去配置@Autowired的使用,指定一个唯一的bean对象注入!

    在这里插入图片描述

 
拓展:@Nullable

@Nullable字段标记了这个注解,说明这个字段可以为null。

//@Autowired的一段源码
public @interface Autowired {
   boolean required() default true;
}
public class People {
    //如果显示的定义required属性为false,说明这个对象可以为null,否则不允许为空
    @Autowired(required = false)
    private Cat cat;
    @Autowired
    private Dog dog;
    private String name;
}

 

7.3.2@Resource

java原生自动装配注解,比较强大,先通过byName再通过byType寻找

import javax.annotation.Resource;
public class People {
    @Resource
    private Cat cat;
    @Resource(name = "dog1")
    private Dog dog;
    private String name;
}

 
 

8.使用注解开发

  • 在spring4之后使用注解开发必须导入aop的jar包在这里插入图片描述

  • 导入context约束,增加注解支持

  1. bean:@Component

  2. 属性注入:@Value(“xxx”)

    //组件,等价于<bean id="user" class="moli.pojo.User"/>
    @Component
    @Scope("singleton")
    public class User {
        //相当于<property name="name" value="小明"/>
        @Value("小明")
        public String name;
    }
    
    <?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">
        <!--指定要扫描的包,这个包下的注解就会生效-->
        <context:component-scan base-package="moli.pojo"/>
        <context:annotation-config/>
    </beans>
    
  3. 衍生的注解:

    @Component的衍生注解

    • dao:@Repository
    • service:@Service
    • controller:@Controller
  4. 自动装配:@Autowired

  5. 作用域:@Scope(“singleton”)

  6. 小结

       xml与注解:

  • xml适用于任何场合,比较万能,维护简单

  • 注解不是自己的类使用不了,维护比较复杂
     
    xml与注解的最佳实现:

  • xml负责管理bean

  • 注解负责实现属性的注入

 
 

9.使用java的方式配置spring

我们现在要完全不使用Spring的xml配置了,全权交给Java来做。JavaConfig是Spring的一个子项目,在Spring4之后,它成为了一个核心功能。

在这里插入图片描述

  1. 实体类

    package moli.pojo;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.stereotype.Component;
    @Component
    public class User {
        @Value("小明")
        private String name;
    
        public String getName() {return name;}
        public void setName(String name) {this.name = name;}
        @Override
        public String toString() {return "User{" +"name='" + name + '\'' +'}';}
    }
    
  2. 配置类

    package moli.config;
    import moli.pojo.User;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.ComponentScan;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.context.annotation.Import;
    
    @Configuration
    //@Configuration代表这是一个配置类,就相当于beans.xml
    //这个也会被spring管理注册到容器中,因为相当于@Component
    @ComponentScan("moli.pojo")
    //扫描包
    @Import(UserConfig1.class)
    public class UserConfig {
        // 注册一个bean,就相当于我们之前写的一个bean标签
        // 这个方法的名字,就相当于bean标签中id属性
        // 这个方法的返回值,就相当于bean标签中的class属性
        @Bean
        public User getUser(){
            return new User(); // 就是返回要注入到bean的对象!
        }
    }
    
  3. 测试

    import moli.config.UserConfig;
    import moli.pojo.User;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.annotation.AnnotationConfigApplicationContext;
    public class MyTest {
        public static void main(String[] args) {
            //如果完全使用了配置类方式去做,我们就只能通过 AnnotationConfig 上下文来获取容器,通过配置类的class对象加载!
            ApplicationContext context = new AnnotationConfigApplicationContext(UserConfig.class);
            //方法名就是bean的名字
            User getUser = (User) context.getBean("getUser");
            System.out.println(getUser.getName());
        }
    }
    
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值