Spring5框架 笔记总结(一)

1. Spring5

1.1 Spring5 概述


Spring 是轻量级的开源的JavaEE框架。

Spring 可以解决企业应用开发的复杂性。

Spring 有两个核心部分: IOC(Inversion of Control, 控制反转) 和 AOP( Aspect Oriented Programming , 面向切面编程)

Spring是分层的Java SE/EE应用 full-stack 轻量级开源框架,以IOC和AOP为内核。


IOC(Inversion of Control, 控制反转) : 把创建对象过程交给spring进行。

AOP(Aspect Oriented Programming , 面向切面编程):不修改源代码进行功能增强。


Spring的特点:

  • 方便解耦,简化开发(将对象间的依赖关系交由Spring进行控制,避免过度耦合)。
  • AOP编程支持。
  • 方便程序的测试。
  • 方便集成整合各种优秀框架(Struts,Hibemate等)。
  • 方便进行事务操作(Spring ,通过声明式方式灵活的进行事务管理)。
  • 降低Java API的开发难度。

1.2 其他框架


SSH框架 : Struct2 + Spring + Hibernate(自动)
SSM框架 : SpringMVC + Spring + Mybatis(半自动)

学习顺序:
在这里插入图片描述

Spring Boot

  • 一个快速开发的脚手架。
  • 基于SpringBoot可以快速的开发单个微服务。

Spring Cloud

  • Spring Cloud 是基于Spring Boot实现的,用来管理它的。

2. Spring5 的相关jar包下载


Spring5下载相关jar包:https://spring.io/projects/spring-framework#learn

在这里插入图片描述

注意GA 和 snapshot的区别:
在这里插入图片描述

General Availability,正式发布的版本。


想要下载其他版本的可以访问该地址:

https://repo.spring.io/ui/native/release/org/springframework/spring


Spring大体上的一个模块框架:
在这里插入图片描述
Core Container:核心容器 ,这个是最基础要掌握的,上面的操作都是基于核心容器来实现的。

3. Spring5 IOC容器

3.1 为什么要用IOC?


做程序讲究高内聚,低耦合。

一般我们的声明对象调用方法,都是new 对象,调用该对象的方法,但是如果我们修改了对象方法的名字,那么一下子啊就要改所有调用该方法的对象,这样耦合度太高了。

对于上面这种情况可以通过工厂模式来达到一个解耦效果:(通过UserFactory,大大降低了UserService和UserDao直接的耦合。)
在这里插入图片描述
但是,工厂模式下的耦合度还不是最低的,还可以通过IOC来实现这降低耦合!!

3.2 什么是 IOC?


IOC控制反转,把对象创建和对象之间的调用过程,交给Spring进行管理。

没有IOC冲虚,一系列的对象创建都是由程序自己完成,控制反转后将对象的创建转移给第三方,也就是获得依赖对象的方式反转了。

使用IOC目的:为了耦合度降低。


IOC的底层原理由三个部分组成:

  • xml解析。
  • 工厂模式。
  • 反射

也就是说学spring之前,java的工厂模式和java反射都要知道!

在这里插入图片描述


IOC总结:

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

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

3.3 IOC 接口


IOC思想基于IOC容器完成,IOC容器底层就是对象工厂。

spring提供了实现IOC容器的两种方式:(也就是两个接口)

  • BeanFactory接口:该接口是IOC容器最基本的实现方式,是spring内部自带的接口,不提供开发人员进行使用。
  • ApplicationContext接口:它是BeanFactory接口的子接口,提供了更多更强大的功能,一般是开发人员使用的。

上面两个都能实现IOC容器。

4. Spring 实例


所谓的IOC就是:对象由Spring来创建,管理,装配。

创建一个maven项目,在pom.xml中导入spring的相关依赖:

<dependencies>
   <dependency>
       <groupId>org.springframework</groupId>
       <artifactId>spring-web</artifactId>
       <version>5.3.9</version>
   </dependency>
</dependencies>

如下案例:

创建一个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 http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!--使用spring来创建对象,在Spring中这些都称作为Bean-->
    <!--反转:程序本身不创建对象,而变成被动的接受对象。-->
    <bean id="hello" class="com.itholmes.pojo.Hello">
        <!--property属性作用就是为str设置一个值。-->
        <!--依赖注入:就是利用set方法进行注入的,也就是这里的str必须在自己的类中有set方法,来修改它才行!!!-->
        <property name="str" value="Spring"/>
        <!--
            property中,ref属性和value属性不同:
                ref:引用spring容器中创建好的对象。
                value:具体的值,基本数据类型。
        -->
    </bean>
</beans>

在maven中的main/java中创建hello.java类

package com.itholmes.pojo;
/*
    概述:
    @Date:Create in 9:36 2021/12/27
*/

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 + '\'' +
                '}';
    }
}

在maven的test/java中测试能否通过xml文件创建管理类:

/*
    概述:
    @Date:Create in 9:48 2021/12/27
*/

import com.itholmes.pojo.Hello;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Mytest {
    public static void main(String[] args) {
        //获取spring的上下文对象context,也就是获取ApplicationContext:拿到Spring的容器。
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");

        //我们的对象现在都在Spring中管理了,我们要使用,直接去里面取出来调用就可以了。
        Hello hello = (Hello) context.getBean("hello");

        System.out.println(hello.toString());
    }
}

bean属性ref的使用:
在这里插入图片描述


注意:idea提示创建上下文参数
在这里插入图片描述
上面的意思可以理解为创建一个新的程序上下文参数,配置该文件到spring项目中去。

我们可以在project structure中看到applicationcontext的内容:
在这里插入图片描述

完成上面操作,我们在类中可以看到相关的标签已经导入进来:

在这里插入图片描述

5. Spring IOC创建对象的方式

5.1 使用无参构造器创建对象(默认)


IOC在配置xml文件控制反转时,创建对象也是分无参数和有参数的,默认的就是无参数构造器。
在这里插入图片描述

5.2 有参数构造器创建对象


方式一,index下标的方式:

<!--第一种:使用index下标赋值。-->
<bean id="user" class="com.itholmes.pojo.User">
    <constructor-arg index="0" value="张三"/> <!--第一个参数-->
    <constructor-arg index="1" value="18"/> <!--第二个参数-->
</bean>

方式二:通过使用类型创建,不建议使用!

<!--第二种:通过使用类型创建,不建议使用!-->
<bean id="user" class="com.itholmes.pojo.User">
    <!--注意基本类型可以直接用int,short等等,但是String引用类型必须写全,平时我们代码中直接写的String的也只是java.lang.String的别名而已。-->
    <constructor-arg type="java.lang.String" value="张三"/>
    <constructor-arg type="int" value="18"/>
</bean>

第三种:通过使用参数名和name属性来传递参数,建议使用。

<!--第三种:通过使用参数名和name属性来传递参数。-->
<bean id="user" class="com.itholmes.pojo.User">
    <constructor-arg name="name" value="张三"/>
    <constructor-arg name="age" value="18"/>
</bean>

我们平时说的spring容器就是下面的context:

 ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");

总结:在配置文件加载的时候,容器中管理的对象就已经初始化了。

这句话意思不难理解,就是我们所有配置在beans中的内容,都将会在new ClassPathXmlApplicationContext(“beans”); 执行完后将beans中所有的配置的类对象,全部加载创建完毕。之后我们想调用谁就调用谁,也就是在一个容器当中想用谁就用谁。
在这里插入图片描述

6. Spring 配置

6.1 别名


alias别名:就是给user起了个别名,同样我们可以使用别名获取到这个对象。

<!--alias别名:就是给user起了个别名,同样我们可以使用别名获取到这个对象。-->
<alias name="user" alias="alias_user"/>

在这里插入图片描述

6.2 Bean标签 的配置属性


对于Bean标签的配置属性,基本的如下:

<!--
    id: bean的唯一标识符,也就是对应对象名。
    class: bean对象所对应的全限定名,全限定名就是包名加类名。
    name: 这里的name是当前bean的别名,并且name可以取多个别名。(中间分隔,可以用空格,逗号,分号都可以进行分隔效果。)
-->
<bean id="AddrT" class="com.itholmes.pojo.AddrT" name="T,T2,abcT3">
    
</bean>

6.3 import标签


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

在这里插入图片描述
import标签功能很强大,如果遇到相同的内容,就会覆盖一起,别名也是一样的。

7. 依赖注入

7.1 什么是依赖注入?


在Spring中实现控制反转的是IOC容器,其实现方法是依赖注入(Dependency Injection , ID)
在这里插入图片描述

7.2 构造器注入


构造器,在第三节的Spring IOC创建对象的方式中已经说明。

7.3 Set方式注入(重点)


依赖注入:Set注入

在这解释一下为什么set注入,因为它必须要用到setXxx()方法因此这样命名。

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

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

    <bean id="addr_id" class="com.itholmes.pojo.Address">
        <property name="address" value="上海"/>
    </bean>

    <bean id="student" class="com.itholmes.pojo.Student">

        <!--name属性指向的是类中的变量属性名。-->

        <!--第一种,普通值注入:value属性-->
        <property name="name" value="张三"/>

        <!--第二种,Bean值注入:ref属性-->
        <property name="address" ref="addr_id"/>

        <!--第三种,数组注入:array标签-->
        <property name="books">
            <array>
                <value>三国演义</value>
                <value>水浒传</value>
                <value>红楼梦</value>
                <value>西游记</value>
            </array>
        </property>

        <!--第四种,list集合注入:list标签-->
        <property name="hobbys">
            <list>
                <value>听歌</value>
                <value>玩游戏</value>
                <value>打篮球</value>
            </list>
        </property>

        <!--第五种,map集合注入:map标签和entry标签使用-->
        <property name="card">
            <map>
                <entry key="学号" value="123"/>
                <entry key="姓名" value="itholmes"/>
            </map>
        </property>

        <!--第六种,Set集合注入:set标签-->
        <property name="game">
            <set>
                <value>123</value>
                <value>456</value>
                <value>789</value>
            </set>
        </property>

        <!--第七种,null值注入:null-->
        <property name="wife">
            <null/>
        </property>
        <!--空字符串的注入如下:-->
        <!--<property name="wife" value=""/>-->

        <!--第八种,Properties注入:props标签和prop标签-->
        <property name="info">
            <props>
                <prop key="username">root</prop>
                <prop key="password">root</prop>
                <prop key="url">jdbc:mysql://localhost:3306/</prop>
                <prop key="driver">com.mysql.jdbc.Driver</prop>
            </props>
        </property>

    </bean>

</beans>

student类:

package com.itholmes.pojo;
/*
    概述:
    @Date:Create in 9:12 2021/12/28
*/

import java.util.*;

public class Student {

    private String name;
    private Address address;
    private String[] books;
    private List<String> hobbys;
    private Map<String,String> card;
    private Set<String> game;
    private String wife;
    private Properties info;

    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> getHobbys() {
        return hobbys;
    }

    public void setHobbys(List<String> hobbys) {
        this.hobbys = hobbys;
    }

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

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

    public Set<String> getGame() {
        return game;
    }

    public void setGame(Set<String> game) {
        this.game = game;
    }

    public String getWife() {
        return wife;
    }

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

    public Properties getInfo() {
        return info;
    }

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

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", address=" + address.toString() +
                ", books=" + Arrays.toString(books) +
                ", hobbys=" + hobbys +
                ", card=" + card +
                ", game=" + game +
                ", wife='" + wife + '\'' +
                ", info=" + info +
                '}';
    }
}

Address类:

package com.itholmes.pojo;
/*
    概述:
    @Date:Create in 9:16 2021/12/28
*/

public class Address {
    private String address;

    public String getAddress() {
        return address;
    }

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

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

测试类MyTest:

/*
    概述:
    @Date:Create in 9:28 2021/12/28
*/

import com.itholmes.pojo.Student;
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");
        Student s = (Student) context.getBean("student");
        System.out.println(s.toString());
        //Student{name='张三', address=Address{address='上海'}, books=[三国演义, 水浒传, 红楼梦, 西游记], hobbys=[听歌, 玩游戏, 打篮球], card={学号=123, 姓名=itholmes}, game=[123, 456, 789], wife='null', info={password=root, url=jdbc:mysql://localhost:3306/, driver=com.mysql.jdbc.Driver, username=root}}

    }
}

不同的类型,通过不同的方式进行注入!

7.4 p命名 和 c命名空间注入

7.4.1 概述


官方文档:https://docs.spring.io/spring-framework/docs/current/reference/html/core.html

p命名和c命名如下:

xmlns:p="http://www.springframework.org/schema/p"
xmlns:c="http://www.springframework.org/schema/c"

7.4.2 p-namespace p命名空间


p命名空间注入,可以直接注入属性的值。(这里的p就是property属性的意思

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

    <!--p命名空间注入,可以直接注入属性的值。(这里的p就是property属性的意思。)-->
    <bean id="user" class="com.itholmes.pojo.User" p:name="张三" p:age="18"/>

</beans>

User.java类:

package com.itholmes.pojo;
/*
    概述:
    @Date:Create in 10:11 2021/12/28
*/

public class User {
    private String name;
    private int age;

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

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

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

}

MyTest02.java测试类:

/*
    概述:
    @Date:Create in 10:51 2021/12/28
*/

import com.itholmes.pojo.User;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MyTest02 {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("userbeans.xml");
        User user = context.getBean("user",User.class); //在后面添加上了User.class类型后,就不用每次都强转了。
        System.out.println(user.toString());
        //User{name='张三', age=18}
    }
}

这里我们可以通过使用测试类验证,p命名是否注入成功。

7.4.3 c-namespace c命名空间


这里就是传递构造器的内容了,注意如果我们添加了有参构造器,那么无参构造器也要添加,不然前面的默认无参构造器的bean会报错!

c命名空间的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"
       xmlns:c="http://www.springframework.org/schema/c"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!--c命名空间注入,可以通过构造器注入。(这里的c就是constructor构造器的意思。)-->
    <bean id="user2" class="com.itholmes.pojo.User" c:age="18" c:name="itholmes"/>
	<!--注意这里仅仅只是调用了age和name也可以用index下标来表示,了解就好。-->
</beans>

User.java类(比起上添加了有参和无参构造器):

package com.itholmes.pojo;
/*
    概述:
    @Date:Create in 10:11 2021/12/28
*/

public class User {
    private String name;
    private int age;

    public User() {
    }

    public User(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

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

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

}

同样进行MyTest02.java测试:

/*
    概述:
    @Date:Create in 10:51 2021/12/28
*/

import com.itholmes.pojo.User;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MyTest02 {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("userbeans.xml");
        User user = context.getBean("user2",User.class); //在后面添加上了User.class类型后,就不用每次都强转了。
        System.out.println(user.toString());
        //User{name='itholmes', age=18}
    }
}

c命名空间就是设置有参构造器的,很容易理解。


注意:p命名和c命名空间不能直接使用,需要导入xml约束,所谓的约束就是下面的这段代码:

xmlns:p="http://www.springframework.org/schema/p"
xmlns:c="http://www.springframework.org/schema/c"

8. Bean 作用域(scopes)

8.1 官方的bean 6个作用域


在官方上面bean的作用域有六种:

在这里插入图片描述


我们写代码的原则就是能用单例就不会用多例,因为单例节省资源。一般用多例的情况都是不能使用单例的情况下才使用多例,如多线程的共享成员变量的问题。

8.2 singleton 单例模式(Spring 默认的模式)


singleton意思是单例。

Spring默认就是单例模式。

通过scope属性设置为singleton:

<bean id="user2" class="com.itholmes.pojo.User" c:age="18" c:name="itholmes" scope="singleton"/>

spring的bean设置为单例,开始默认就是单例的饿汉模式,就是在加载容器时就直接加载。

spring的bean设置为多例,就是多例的懒汉模式,什么时候需要,什么使用用的原则。

在spring中,单例是可以改成懒汉模式的!!需要设置懒加载。
在这里插入图片描述

8.3 prototype 原型模式


原型模式和我们认识的多例模式差不多。

scope属性值设置为prototype就可以了。

<bean id="user2" class="com.itholmes.pojo.User" c:age="18" c:name="itholmes" scope="prototype"/>

多线程一般使用原型模式,单线程一般使用单例模式,看情况使用。

MyTest02.java 测试类:

/*
    概述:
    @Date:Create in 10:51 2021/12/28
*/

import com.itholmes.pojo.User;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MyTest02 {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("userbeans.xml");
        User user = context.getBean("user2",User.class); //在后面添加上了User.class类型后,就不用每次都强转了。
        User user2 = context.getBean("user2",User.class); //在后面添加上了User.class类型后,就不用每次都强转了。
        //原型模式就是不同的对象了。
        System.out.println(user.hashCode()+","+user2.hashCode());
        System.out.println(user == user2);
        //1709366259,1335298403
        //false
    }
}

可以看到上面的结构无论是hashcode还是判断都是不同的对象。
也就是每次从容器中获得时,都会获得一个新对象。

8.4 request,session ,application


request,session ,application这些个只能在web开发中使用。

就是Servlet的三大域对象一样的。

  • 设置为request:对象只能在一次请求内存活。
  • 设置为session:对象只能在一次会话内存活。
  • 设置为application:对象在项目开始到项目关闭存活。

9. Bean的生命周期 和 后置器

9.1 Bean的生命周期


初始化回调接口:

  • org.springframework.beans.factory.InitializingBean 接口指定一个单一的方法(afterPropertiesSet方法)。

意思很简单,就是我们在spring配置bean对象,如果继承了上面的接口,在创建bean对象后,就会调用响应的实现方法来初始化。

在这里插入图片描述


销毁回调

  • org.springframework.beans.factory.DisposableBean 接口指定一个单一的方法(destroy方法)

意思也很简单,实现了这个接口的bean对象,在被销毁的时候,就会调用destroy方法。

我们可以通过context.regitsterShutdownHook()方法(关闭容器),来查看bean的销毁,并且发现一个特点,就是bean不是伴随着容器的关闭而关闭,而是容器关闭后,直到项目关闭就走销毁,并且关闭。

在这里插入图片描述

bean的生命周期,销毁过程是regitsterShutdownHook()方法后,等程序结束后再销毁bean。


对于上面,我们更喜欢直接在xml文件中,配置初始化方法指定那个方法,销毁指定那个方法。

  • 使用 init-method 属性来指定带有 void 无参数方法的名称。
  • destroy-method 属性来指定带有 void 无参数方法的名称。

在这里插入图片描述

9.2 Bean的后置处理器


Bean 后置处理器允许在调用初始化方法前后对 Bean 进行额外的处理。

实现BeanPostProcessor接口的类,要实现以下的两个抽象方法 ​BeanPostProcessor.postProcessBeforeInitialization(Object, String)​ 和 ​BeanPostProcessor.postProcessAfterInitialization(Object, String)方法
在这里插入图片描述

注意:这里的bean,是操作当前xml文件的所有bean的初始化。
在这里插入图片描述

10. Bean 自动装配

10.1 Bean的装配方式


自动装配是Spring满足bean依赖的一种方式。

Spring会在上下文中自动寻找,并自动给bean装配属性。

Spring中有三种装配的方式:

  • 在xml中显示的配置。(前面)
  • 在java中显示配置。
  • 隐式的自动装配bean。(重点!)

10.2 bean 隐式的自动装配(Autowired)

10.2.1 Autowired 属性


官方给的是:自动装配Autowired。

通过Autowired属性设定。

10.2.2 Autowired的 byName值


byName值:会自动在容器上下文中查找,和自己对象setXxx方法后面的Xxx值对应的beanid

<?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="cat" class="com.itholmes.pojo.Cat"/>
    <bean id="dog" class="com.itholmes.pojo.Dog"/>

	<!--
	    autowire属性:
	        byName值:会自动在容器上下文中查找,和自己对象setXxx方法后面的Xxx值对应的beanid。
	-->
	<bean id="people" class="com.itholmes.pojo.People" autowire="byName">
	<!--People类中调用了上面的内容,这样我们就可以自动装配了,而不用设置property来手动设置。-->
	</bean>
	
</beans>

弊端:必须和set后面的名字相同,也就是唯一才能自动装配到。

10.2.3 Autowired的 byType值


byType值:会自动在容器上下文中查找,和自己对象属性类型相同的bean。

<?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="cat" class="com.itholmes.pojo.Cat"/>
    <bean id="dog" class="com.itholmes.pojo.Dog"/>

	<!--
	    autowire属性:
	        byType值:会自动在容器上下文中查找,和自己对象属性类型相同的bean。
	-->
	<bean id="people" class="com.itholmes.pojo.People" autowire="byType">
	</bean>

</beans>

弊端:type类型必须唯一,不然会直接报错的,同样就算设置的bean没有id,依然能够自动装配,因为是根据类型来的。。

11. Spring的注解 实现自动装配


注解仅仅是JDK1.5以上支持的版本,在Spring中2.5 版本就支持注解了。

使用注解前提:

  • 导入约束。
  • 配置注解的支持。

官方的注解配置如下:

<?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/>

	<!--
		上面的xmlns:context="http://www.springframework.org/schema/context"要添加的命名空间也就是约束。
		
	-->

</beans>

第一步,添加约束:

添加一个约束:

xmlns:context="http://www.springframework.org/schema/context"

两个约束的支持就是xsi:schemaLocation中的:

http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd

第二步,添加注解支持:

context:annotation-config,开启注解的支持。

<context:annotation-config\>


设置好上面的约束后,就可以在对象类中设置@Autowired注解:
(被注解注释的属性必须与xml文件中的bean的id属性相同)

在这里插入图片描述


@Autowired注解注意事项:

  • 使用了@Autowired注解后,连set方法都是不需要的!
  • @Autowired注解直接在属性上使用即可!也可以在setXxx方法上使用。
  • 使用@Autowired我们可以不用编写setXxx方法了,前提是你这个自动装配的属性在IOC(Spring)容器中存在,且bean的id值名字必须相同!

@Nullable注解使用:

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

@Autowired注解源码如下:

public @interface Autowired {
    boolean required() default true;
}

因此,它是有一个required属性的设置,设个属性和@Nullable注解差不多来定义能否为null的。

如果显示定义了Autowired的required属性为false,说明这个对象可以为null;定义为true,就不能为空!


@Autowired注解:

可以自动进行装配匹配xml文件中的bean效果,不用设置property属性了。但是如果有多个bean名字差不多,这是Autowired就会报错了!原因就是不确定找不到是哪一个。如下:

在这里插入图片描述


@Qualifier注解:

这个时候就需要@Qualifier(value=“xxx”)来指定xml配置文件中的bean属性了。

@Qualifier注解和@Autowired注解是一般成对出现的。
在这里插入图片描述

代码效果如下:

package com.itholmes.pojo;
/*
    概述:
    @Date:Create in 14:10 2021/12/28
*/

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.lang.Nullable;


public class People {

    //如果显示定义了Autowired的required属性为false,说明这个对象可以为null;定义为true,就不能为空!。
    @Autowired
    @Qualifier(value = "cat222")
    private Cat cat;

    @Autowired
    @Qualifier(value = "dog222")
    private Dog dog;

    private String name;


    public People() {
    }

    //@Nullable注解:name为空也不会报错!
    public People(String name) {
        this.name = name;
    }

    public Cat getCat() {
        return cat;
    }

    public Dog getDog() {
        return dog;
    }

    public String getName() {
        return name;
    }

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

    @Override
    public String toString() {
        return "People{" +
                "cat=" + cat +
                ", dog=" + dog +
                ", 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"
       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:annotation-config/>

    <bean id="cat111" class="com.itholmes.pojo.Cat"/>
    <bean id="cat222" class="com.itholmes.pojo.Cat"/>
    <bean id="dog111" class="com.itholmes.pojo.Dog"/>
    <bean id="dog222" class="com.itholmes.pojo.Dog"/>

    <bean id="people" class="com.itholmes.pojo.People"/>

</beans>

确定好前后对应即可。

12. java自带的注解 实现自动装配


@Resource注解:

同样,在没有多个bean的相同类型时,@Resource也是可以实现自动装配,name属性也可以指定bean的属性值id。
在这里插入图片描述

注意这个Resource注解是javax.annotation.Resource下的,不是spring的东西。

开发中,我们常用的就是@Autowired注解和@Resource注解实现,前者最多。


@Resource和@Autowired的区别:

  • 都是用来自动装配的,都可以放在属性字段上。
  • @Autowired通过byType的方式实现,如果设置了@Qualifier(value=“xxx”)则用byname实现,而且必须要求该对象bean存在!
  • @Resource默认通过byname的方式实现,如果找不到名字,则通过byType实现,如果两个都找不到就会报错!。
  • 执行顺序不同:@Autowired先是通过byType实现,@Resource先是通过byname实现

13. Spring 注解开发

13.1 四个注解的使用


上面说过的注解如下:

@Autowired:spring自动装配,配合@Qualifier(value=“xxx”)来使用。

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

@Resource:java自带的自动装配通过名字,类型。


在介绍一个@Component注解:

@Component:Component英文意思就是组件的意思。

这个注解相当于我们自定义的bean标签,例如:

<bean id="user" class="com.itholmes.dao.User"/>

注意使用@Component注解时,必须指定要扫描的包:
<context:component-scan base-package=“com.itholmes.dao”/>

换句话说,我们不用自己去xml文件定义对象bean标签了。

他还有一个@Value(“xxx”)注解可以给属性变量添加值,我们之前的@Autowired是给自己创建的引用实例类来自动装配的。

User.java类:

package com.itholmes.dao;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

//@Component英文意思就是组件的意思。
//等价于<bean id="user" class="com.itholmes.dao.User"/>
@Component
public class User {

    //@Value等价于它:<property name="name" value="ithomes"/>
    @Value("itholmes")
    public String name;

    //也可以注入到set方法上面
    //@Value("itholmes")
    public void setName(String name) {
        this.name = name;
    }

}

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"
       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
            http://www.springframework.org/schema/context/spring-context.xsd
            ">

    <!--指定要扫描的包,这个包下的注解就会生效-->
    <context:component-scan base-package="com.itholmes.dao"/>

    <context:annotation-config/>

</beans>

测试类:

/*
    概述:
    @Date:Create in 10:13 2021/12/30
*/

import com.itholmes.dao.User;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MyTest {

    public static void main(String[] args) {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        User user = context.getBean("user", User.class);
        System.out.println(user.name);
    }

}

13.2 @Component的衍生注解


@Component有几个衍生注解,在web开发中,会按照mvc三层架构分层。

  • dao层 : @Repository
  • service层:@Service
  • controller层:@Controller ,注意:@Controller是servlet和springmvc的结合体,是基于http协议的。

换句话说这四个注解的功能是相同的!都是代表某个类注入到Spring容器中,装配Bean。

注意,不要忘记扫描包的的声明!

在这里插入图片描述

13.5 @Value注解的使用


上面我们通过@Autowired注解来自动装配指定实例类的操作。

我们还可以通过@Value来给类中的属性变量设置值。

在这里插入图片描述

13.4 @Scope注解 作用域的使用


@Scope就是对应上面我们设定scope属性的注解,同样值常用的就是singleton单例模式,prototype原型模式。

Scope也就是作用域。

13.5 总结 xml和注解 的优劣


xml 与 注解:

  • xml是万能的,适用于任何场合!维护起来简单方便。
  • 注解是定义到类中,因此不是被自己注解的类是不能够使用的。而且维护起来相对复杂一些。

最佳方案如下:

  • xml用来管理bean。
  • 注解只负责完成属性的注入。
  • 我们在使用的过程中只需要注意一个问题,必须让注解生效,也就是开启注解支持,也就是下面内容:
<?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
            http://www.springframework.org/schema/context/spring-context.xsd
            ">

    <!--指定要扫描的包,这个包下的注解就会生效-->
    <context:component-scan base-package="com.itholmes.dao"/>
    <context:annotation-config/>

</beans>

14. 补充

14.1 获取bean的三种方式


获取bean的三种方式:

  • bean的id。
  • bean的类。
  • bean的类的接口。

14.2 @Autowired注解自动装配常见的几个错误


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

一般碰到这个就是我们@autowired的对象,不确定是哪一个实现类了。

我们一般都是通过下面的方式来操作解决。
在这里插入图片描述


总结:

  • @Autowired注解是根据类型找实现类,找到的实现类,再看他们的名称。如果有多个。就会报错。因此需要@Qualifier注解。
  • 如果不指定@Service(“xxx”)的别名,默认就是首字母小写的类名,其他3个注解也一样。

@Autowired有一个required值设置为true就是必须要注入。
在这里插入图片描述
false就是注入不注入无所谓也不会报错,但是如果没有注入成功,调用其方法因为没有注入进来就会空指针异常。
在这里插入图片描述

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

xupengboo

你的鼓励将是我创作最大的动力。

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值