spring5学习个人笔记

244 阅读12分钟

一、构建一个基础的spring项目

image.png 这是spring5的模块,现在需要下面这四个组件。

  1. 创建了一个javase的maven的工程,添加jar包依赖
<dependencies>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.11</version>
        <scope>test</scope>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.springframework/spring-beans -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-beans</artifactId>
        <version>5.3.16</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.springframework/spring-expression -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-expression</artifactId>
        <version>5.3.14</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.springframework/spring-core -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-core</artifactId>
        <version>5.3.14</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>5.3.15</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/commons-logging/commons-logging -->
    <dependency>
        <groupId>commons-logging</groupId>
        <artifactId>commons-logging</artifactId>
        <version>1.2</version>
    </dependency>

一共五个,最后一个是关于日志文件的也需要,要加上,不加报错

二、IOC(控制反转)

1、什么是 IOC

  • (1)控制反转,把对象创建和对象之间的调用过程,交给 Spring进行管理
  • (2)使用 IOC目的:为了耦合度降低
  • (3)做入门案例就是 IOC 实现 2、IOC底层原理
  • (1)xml 解析、工厂模式、反射

image.png

image.png

三、IOC bean管理 使用xml配置文件

1、什么是 Bean 管理

  • (0)Bean管理指的是两个操作
  • (1)Spring创建对象
  • (2)Spirng注入属性 2、Bean管理操作有两种方式
  • (1)基于 xml 配置文件方式实现
  • (2)基于注解方式实现

1.使用xml文件创建一个bean对象

  1. 实体类
package huiqing.spring5;

public class User {
    public void add(){
        System.out.println("add.....");
    }
}
  1. 配置文件(注意配置文件放的地方,maven工程下应该放在resource资源目录下,不然以类路径获取配置文件时不放到这里会抛出异常说找不到文件)
<?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">

<!--    配置User对象创建类-->
<!--    底层默认使用的是无参构造-->
    <bean id="user" class="huiqing.spring5.User"></bean>
</beans>
  1. 测试类
package huiqing.spring5;

import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestUser {

    @Test
    public void testAdd(){
        //1.加载spring配置文件
        ClassPathXmlApplicationContext file = new ClassPathXmlApplicationContext("beanUser.xml");
        //2.获取配置创建的对象
        User user = file.getBean("user", User.class);
        System.out.println(user);
        user.add();
    }
}

结果:
huiqing.spring5.User@2173f6d9
add.....

2.注入属性

基于xml方式注入属性一共有两种方式,一种是set方法进行注入,一种是有参构造函数进行注入

set方法进行注入

  • 实体类,(用实体类中的set方法)
package huiqing.spring5;

public class Book {
    private String bname;
    private String bauthor;

    public void setBname(String bname) {
        this.bname = bname;
    }

    public void setBauthor(String bauthor) {
        this.bauthor = bauthor;
    }

    public String getBname() {
        return bname;
    }

    public String getBauthor() {
        return bauthor;
    }
}
  • 配置文件
<?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="book" class="huiqing.spring5.Book">
    
    
        <!--使用property完成属性注入 name:类里面属性名称 value:向属性注入的值-->
        <property name="bname" value="java算法"></property>
        <property name="bauthor" value="庆哥"></property>
        
        
    </bean>
</beans>
  • 测试类
package huiqing.spring5;

import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestBook {

    @Test
    public void testBook(){

        //1.加载spring配置文件
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("beanBook.xml");
        //2.获取配置创建的对象
        Book book = context.getBean("book", Book.class);
        System.out.println(book.getBname());
        System.out.println(book.getBauthor());
    }
}
  • 结果 (对应测试文件中的内容) java算法
    庆哥

有参构造方法进行注入

  • 实体类
package huiqing.spring5;

public class Orders {
    private String oname;
    private String oaddress;

    public Orders(String oname, String oaddress) {
        this.oname = oname;
        this.oaddress = oaddress;
    }

    public String getOname() {
        return oname;
    }

    public String getOaddress() {
        return oaddress;
    }
}
  • 配置文件
package huiqing.spring5;

import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;


public class TestOrders {

    @Test
    public void testOrders(){
        //1.加载配置文件
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("beanOrders.xml");
        //2.获取配置文件创建对象
        Orders orders = context.getBean("orders", Orders.class);
        System.out.println(orders.getOname());
        System.out.println(orders.getOaddress());

    }


}
  • 测试类
package huiqing.spring5;

import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;


public class TestOrders {

    @Test
    public void testOrders(){
        //1.加载配置文件
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("beanOrders.xml");
        //2.获取配置文件创建对象
        Orders orders = context.getBean("orders", Orders.class);
        System.out.println(orders.getOname());
        System.out.println(orders.getOaddress());

    }


}

结果 :
电脑
china

p 名称空间注入(了解)

详细内容,上网查。

注入其他类型属性

  • 注入空值,注入特殊字符 首先明白一个名词--字面量,就是对一个属性赋的值。
  1. 注入空值 以Orders类为例,将其beanOrders.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">

    <bean id="orders" class="huiqing.spring5.Orders">
<!--        有参构造注入属性,属性不写全下面会报错(就下面两行)-->
        <constructor-arg name="oname" value="电脑"></constructor-arg>
<!--        <constructor-arg name="oaddress" value="china"></constructor-arg>-->
        <constructor-arg name="oaddress" >
            <null></null> <!--属性标签内部加上这个null标签-->
        </constructor-arg>
    </bean>
</beans>

结果:
电脑
null (刚刚的中国,这里变成了null)

  1. 转义特殊符号(用cdata)
<?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="book" class="huiqing.spring5.Book">
        <!--使用property完成属性注入 name:类里面属性名称 value:向属性注入的值-->
        <property name="bname" value="java算法"></property>
        <property name="bauthor" >
<!--            转义这个尖括号-->
            <value><![CDATA[<庆哥>]]></value>
        </property>
    </bean>
</beans>

输入结果:
java算法
<庆哥>

注入属性外部bean

注入外部bean其实就是,这个类里面有一个属性是其他类的 引用类型变量

这里我们用service层和Dao层做演示,在之前的开发中我们会在service层中创建一个dao层的对象,然后在service当某个功能用到数据库时,dao层的对象执行增删查改操作。这里我们不在servic类中创建dao层的对象我们用配置文件的方式进行service和dao的对象创建。

  • 配置文件
<?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其实就是,这个类里面有一个属性是其他类的 引用类型变量-->

    <!--        1.创建service 和 dao的对象-->
    <bean name="userService" class="huiqing.spring5.service.UserService">
        <property name="userDao" ref="userDaoImpl"></property><!--注意这里用的不是value,而是ref。这里的ref值要与下面哪个bean中的id对应-->
    </bean>
    <bean id="userDaoImpl" class="huiqing.spring5.dao.UserDaoImpl"></bean>
</beans>
  • UserService类
package huiqing.spring5.service;

import huiqing.spring5.dao.UserDao;

public class UserService {
    //创建UserService类型属性,生成set方法
    private UserDao userDao;

    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }

    public void function(){
        System.out.println("service's function ........");
        userDao.update();
    }
}
  • UserDao 和 UserDaoImpl
package huiqing.spring5.dao;

public interface UserDao {
    public void update();
}
package huiqing.spring5.dao;

public class UserDaoImpl implements UserDao{
    @Override
    public void update() {
        System.out.println("update..........");
    }
}
  • 测试类
package huiqing.spring5;

import huiqing.spring5.service.UserService;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestUserService_UserDao {

    @Test
    public void testUserServiceUserDao() {
        //1.加载配置文件
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("service_dao.xml");
        //2.用配置文件创建一个对象
        UserService userService = context.getBean("userService", UserService.class);
        userService.function();
    }
}

注入属性内部bean

与注入外部bean不同这个引用类型的bean标签写在所在类bean标签的内部。

  • Emp 和 Dept类
package huiqing.spring5;

//员工类
public class Emp {
    private String ename;
    private String gender;
    //员工属于某一个部门,使用对象形式表示
    private Dept dept;

    public void setEname(String ename) {
        this.ename = ename;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }

    public void setDept(Dept dept) {
        this.dept = dept;
    }

    public Dept getDept() {
        return dept;
    }

    public String getEname() {
        return ename;
    }

    public String getGender() {
        return gender;
    }
}
package huiqing.spring5;


/**
 * 部门类
 */
public class Dept {
    private String dname;

    public void setDname(String dname) {
        this.dname = dname;
    }

    public String getDname() {
        return dname;
    }
}
  • 配置文件
<?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">

    <!--    注入方式使用的是set注入-->

    <bean id="emp" class="huiqing.spring5.Emp">

        <!-- 普通变量           -->
        <property name="ename" value="张迪"></property>
        <property name="gender" value="男"></property>

        <!--                引用类型的变量-->
        <!--        property里面写bean,bean里面在写property-->
        <property name="dept">
            <bean id="dept" class="huiqing.spring5.Dept">
                <property name="dname" value="安保部"></property>
            </bean>
        </property>

    </bean>
</beans>
  • 测试类
package huiqing.spring5;

import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestEmpDept {

    @Test
    public void testEmpDept(){
        //1.加载配置文件
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("dept_emp.xml");
        //2.创建对象
        Emp emp = context.getBean("emp", Emp.class);
        //获取到Demp类的相关信息
        System.out.println(emp.getDept().getDname());
        //获取自身类相关属性
        System.out.println(emp.getEname());
        System.out.println(emp.getGender());
    }
}

级联赋值

就是对引入类型变量对象内部的属性赋值,配置文件书写有两种方式。 还用刚刚的员工类和部门类测试。
测试时不要忘了更改配置文件。

  • 第一种写法
<?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的方式-->
    <bean id="emp" class="huiqing.spring5.Emp">
        <property name="ename" value="qingge"></property>
        <property name="gender" value="男"></property>
        <property name="dept" ref="dept"></property>
    </bean>
    <bean id="dept" class="huiqing.spring5.Dept">
        <property name="dname" value="财务部"></property>
    </bean>


</beans>
  • 第二种写法
<?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="emp" class="huiqing.spring5.Emp">
        <property name="ename" value="张慧庆"></property>
        <property name="gender" value="男"></property>
        <!--                注意:这种用.的方式赋值时,Emp类中一定要有dept属性的get方法不然无法获得dept属性,这里会报错-->
        <property name="dept" ref="dept"></property><!--刚开始这一句忘写了,找了好久。。。。。-->
        <property name="dept.dname" value="技术部"></property>
    </bean>
    <bean id="dept" class="huiqing.spring5.Dept"></bean>

</beans>

xml注入集合属性

包括集合中注入对象属性

  • 实体类
package huiqing.spring5.collection;

import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * Student类用于学习注入  数组、list、map、set类型的属性
 */
public class Student {
    private String[] course;
    private List<String> list;
    private Map<String,String> map;
    private Set<String> set;

    //在集合里面设置对象类型值---Course类的对象
    private List<Course> courseList;

    public void setCourseList(List<Course> courseList) {
        this.courseList = courseList;
    }

    public void setCourse(String[] course) {
        this.course = course;
    }

    public void setList(List<String> list) {
        this.list = list;
    }

    public void setMap(Map<String, String> map) {
        this.map = map;
    }

    public void setSet(Set<String> set) {
        this.set = set;
    }

    //test方法用户测试打印
    public void test(){
        System.out.println(Arrays.toString(course));
        System.out.println(list);
        System.out.println(map);
        System.out.println(set);
        System.out.println(courseList);
    }
    
    ```
package huiqing.spring5.collection;

/**
 * 往list集合中注入对象所用到的一个类,配置文件末尾的一部分代码,就是用的这个类
 */
public class Course {
    private String cname;

    public void setCname(String cname) {
        this.cname = cname;
    }

    @Override
    public String toString() {
        return "Course{" +
                "cname='" + cname + ''' +
                '}';
    }
}
  • 配置文件
<?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="student" class="huiqing.spring5.collection.Student">
        <!--        数组类型属性注入-->
        <property name="course">
            <array>
                <value>java课程</value>
                <value>数据库课程</value>
            </array>
        </property>
        <!--        list类型属性注入-->
        <property name="list">
            <list>
                <value>张三</value>
                <value>小张</value>
            </list>
        </property>
        <!--        map类型属性注入-->
        <property name="map">
            <map>
                <entry key="JAVA" value="java"></entry>
                <entry key="C" value="c"></entry>
            </map>
        </property>
        <!--        set类型属性注入-->
        <property name="set">
            <set>
                <value>Mysql</value>
                <value>Redis</value>
            </set>
        </property>
      
        <!--    在集合里面设置对象类型值,这是个对象类型的属性,所以还是先写在Student类的property标签里面,之后用外部bean ref标签引入-->
        <property name="courseList">
            <list>
                <ref bean="course1"></ref>
                <ref bean="course2"></ref>
            </list>
        </property>
    </bean>
    <!--    创建多个course对象-->
    <bean id="course1" class="huiqing.spring5.collection.Course">
        <property name="cname" value="大学英语"></property>
    </bean>
    <bean id="course2" class="huiqing.spring5.collection.Course">
        <property name="cname" value="大学物理"></property>
    </bean>


</beans>
  • 测试类
package huiqing.spring5.collention;

import huiqing.spring5.collection.Student;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestStudent {

    @Test
    public void testArrayListMapSet(){
        //1.加载配置文件
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("studentCollection.xml");

        //2.创建对象
        Student student = context.getBean("student", Student.class);
        student.test();
    }
}

把集合注入部分提取出来(暂且不知道有啥用)

-实体类

package huiqing.spring5.collection;

import java.util.List;

public class Book {
    private List<String> list;

    public void setList(List<String> list) {
        this.list = list;
    }

    /**
     * 测试时要用到的方法
     */
    public void test(){
        System.out.println(list);
    }
}
  • 配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:util="http://www.springframework.org/schema/util"
       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
       http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">

    <!--    1.提取list集合类型属性注入-->
    <util:list id="bookList"><!--这个id bookList对应下面 bean 中 property 的 ref 的 bookList-->
        <value>易筋经</value>
        <value>九阴真经</value>
        <value>九阳神功</value>

    </util:list>
    <!--    2.提取list集合类型属性注入使用-->
    <bean id="book" class="huiqing.spring5.collection.Book">
        <property name="list" ref="bookList"></property>
    </bean>
</beans>
  • 测试类
package huiqing.spring5.collention;

import huiqing.spring5.collection.Book;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * 把集合注入部分提取出来
 *在xml文件中使用 util 标签完成 list 集合注入提取
 */
public class TestListBook {
    public static void main(String[] args) {
    //1.加载配置文件
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("tiqujiheleixingshuxingzhuru.xml");
        Book book = context.getBean("book", Book.class);
        book.test();

    }
}

bean的两种类型(之后记得不详细的就看ipad上pdf笔记)

普通bean 和 工厂bean

bean作用域

设置bean实例是单例的还是多例的

bean生命周期

五步的 和 七步的区别,相比之下七步的多了啥,配置文件要做什么配置

xml文件 bean 自动装配

一个类的属性是对象类型

  • 实体类
package huiqing.spring5.autoWire;

public class Dept {

    @Override
    public String toString() {
        return "Dept{}";
    }
}
package huiqing.spring5.autoWire;

public class Emp {
    private Dept dept;

    public void setDept(Dept dept) {
        this.dept = dept;
    }

    @Override
    public String toString() {
        return "Emp{" +
                "dept=" + dept +
                '}';
    }
}
  • 配置文件
<?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="emp" class="huiqing.spring5.autoWire.Emp" autowire="byName"></bean>-->
    <bean id="emp" class="huiqing.spring5.autoWire.Emp" autowire="byType"></bean>
    <bean id="dept" class="huiqing.spring5.autoWire.Dept"></bean>
<!--    <bean id="dept1" class="huiqing.spring5.autoWire.Dept"></bean>--> 若使用byType自动装配,同一个类型的,只能有一个id。
</beans>
  • 测试类
package huiqing.spring5.autoWire;

import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestAutoWire {

    @Test
    public void testAutowire(){
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("autoWire.xml");
        Emp emp = context.getBean("emp", Emp.class);
        System.out.println(emp.toString());
    }


}

四、Ioc容器bean管理 使用注解

环境配置

  1. 首先在maven依赖中相比于上面的xml方式多了一个spring-aop依赖
<!-- https://mvnrepository.com/artifact/org.springframework/spring-aop -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-aop</artifactId>
    <version>5.3.14</version>
</dependency>
  1. 在配置文件中开启组件扫描

image.png

在注解扫描中有一些小细节,请看pdf学习笔记

1.第一个小案例-测试使用注解创建对象

  • 实体类
package huiqing.service;


import org.springframework.stereotype.Component;


//在注解里面的value值可以不写默认是类名称,只不过类名称是首字母小写--userService


@Component(value = "userService")  //这个注解就相当于<bean id = "userService" class"..."/>
public class UserService {
    public void add(){
        System.out.println("service add.....");
    }
}
  • 配置文件
<?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:xontext="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">


    <!--    开启组件扫描-->
    <!--    组件扫描的多个包的两种方式,一种是多个包使用逗号隔开  一种是扫描这多个包的上层包-->
    <xontext:component-scan base-package="huiqing"></xontext:component-scan>

</beans>
  • 测试类
package huiqing.service;

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class AnnotationTest01 {
    public static void main(String[] args) {
        //1.加载配置文件
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("annotationTest01.xml");
        UserService userService = context.getBean("userService", UserService.class);
        userService.add();
    }
}

2.基于注解实现属性注入

进行属性注入,首先类上面要用注解,属性上面也要用到注解,类上面用到注解是为了创建实例,不要忘了

  • 实例类 dao层接口
package huiqing.dao;

public interface UserDao {
    public void add();
}

dao层实现类

package huiqing.dao;

import org.springframework.stereotype.Repository;

@Repository(value = "userDaoImpl")
public class UserDaoImpl implements UserDao{

    @Override
    public void add() {
        System.out.println("UserDao  add ......");
    }
}

service 层

package huiqing.service;


import huiqing.dao.UserDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;


//在注解里面的value值可以不写默认是类名称,只不过类名称是首字母小写--userService


@Service(value = "userService")  //这个注解就相当于<bean id = "userService" class"..."/>
public class UserService {

    @Value(value = "abc")//@Value注解是注入普通属性
    private String name;


    //定义dao类型属性
    //不需要添加set方法
    //添加注入属性注解
//    @Autowired //根据类型进行注入
//    @Qualifier(value = "userDaoImpl")//@Qualifier和@Autowired一起使用,不要忘了
    //@Resource 这个注解可以根据名字也可以根据类型进行注入
//    @Resource//根据类型
    @Resource(name = "userDaoImpl")//根据名字
    private UserDao userDao;



    public void add(){
        System.out.println("service add....."+ name);
        userDao.add();

    }
}
  • 配置文件
<?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:xontext="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">


    <!--    开启组件扫描-->
    <!--    组件扫描的多个包的两种方式,一种是多个包使用逗号隔开  一种是扫描这多个包的上层包-->
    <xontext:component-scan base-package="huiqing"></xontext:component-scan>

</beans>
  • 测试类
package huiqing.service;

import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * 测试注解诸如属性
 */

public class AnnotationTest02 {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("AnnotationTest02.xml");
        UserService userService = context.getBean("userService", UserService.class);
        userService.add();
    }
}

3.完全注解开发

(1)创建配置类,替代 xml 配置文件 @Configuration
//作为配置类,替代xml配置文件

package huiqing.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

/**
 * 用配置类替代配置文件,实现完全注解开发
 */
@Configuration
@ComponentScan(basePackages = {"huiqing"})
public class SpringConfig {

}

实例类还是上面那一个dao 和 service

  • 测试
package huiqing.service;

import huiqing.config.SpringConfig;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * 测试注解诸如属性
 */

public class AnnotationTest02 {
    public static void main(String[] args) {
//        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("AnnotationTest02.xml");
        //使用配置类创建一个对象
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
        UserService userService = context.getBean("userService", UserService.class);
        userService.add();
    }
}

五、AOP

什么是 AOP (1)面向切面编程(方面),利用 AOP 可以对业务逻辑的各个部分进行隔离,从而使得 业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。一句话,aop可以降低类的耦合度。
底层原理使用了动态代理:

  • 有接口情况可以用jdk动态代理
  • 无接口使用CGLIB动态代理
  1. 了解一下几个术语
  • 连接点 类里面哪些方法可以被增强,这些成为连接点
  • 切入点 类里面哪些方法被增强了,称为切入点。
  • 通知(增强) 实际增强的逻辑部分成为通知(增强)
  • 通知的种类
  1. 前置通知
  2. 后置通知
  3. 环绕通知
  4. 最终通知
  5. 异常通知
  • 切面 是动作,把通知运用到切入点的过程。

1.准备工作

加入依赖

<!--下面这几个注解是aop学习相比刚刚的ioc学习新加的-->
<!--        ==================================================================-->
        <dependency>
            <groupId>net.sourceforge.cglib</groupId>
            <artifactId>com.springsource.net.sf.cglib</artifactId>
            <version>2.2.0</version>
        </dependency>
        <dependency>
            <groupId>org.aopalliance</groupId>
            <artifactId>com.springsource.org.aopalliance</artifactId>
            <version>1.0.0</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.9.7</version>
            <scope>runtime</scope><!--这个runtime要删除不然增强类在引入@Aspect注解时会报错-->
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aspects</artifactId>
            <version>5.2.6.RELEASE</version>
        </dependency>
<!--        ================================================================-->

        <!-- https://mvnrepository.com/artifact/org.springframework/spring-beans -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
            <version>5.3.16</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.springframework/spring-expression -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-expression</artifactId>
            <version>5.3.14</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.springframework/spring-core -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>5.3.14</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.3.15</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/commons-logging/commons-logging -->
        <dependency>
            <groupId>commons-logging</groupId>
            <artifactId>commons-logging</artifactId>
            <version>1.2</version>
        </dependency>


        <!--        使用注解是要加上这个spring-aop依赖-->
        <!-- https://mvnrepository.com/artifact/org.springframework/spring-aop -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aop</artifactId>
            <version>5.3.14</version>
        </dependency>
  1. 切入点表达式 (1)切入点表达式作用:知道对哪个类里面的哪个方法进行增强
    (2)语法结构: execution(权限修饰符 返回类型 类全路径 方法名称 参数列表) 举例 1:对 com.atguigu.dao.BookDao 类里面的 add进行增强
    execution(* com.atguigu.dao.BookDao.add(..))星号代表所有

    举例 2:对 com.atguigu.dao.BookDao 类里面的所有的方法进行增强
    execution(* com.atguigu.dao.BookDao.* (..))

    举例 3:对 com.atguigu.dao包里面所有类,类里面所有方法进行增强
    execution(* com.atguigu.dao.. (..))

2.第一个小案例

-- 配置文件

<?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"
       xmlns:aop="http://www.springframework.org/schema/aop"
       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
                            http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
<!--        开启注解扫面-->
    <context:component-scan base-package="aopanno"></context:component-scan>
<!--    开启Aspect生成代理对象,类上有@Aspect注解的就会生成-->
    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>
  • 实体类
package aopanno;

import org.springframework.stereotype.Component;
//被增强的类
@Component
public class User {
    public void add(){
//        int a = 10 / 0;
        System.out.println("add ......");
    }
}
package aopanno;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

//增强的类
@Component
@Aspect //生成代理对象
public class UserProxy {
    //前置 通知
    //@Before 注解表示前置通知,就是在你的要增强的方法之前执行
    @Before(value = "execution(* aopanno.User.add(..))")
    public void Before(){
        System.out.println("before........");
    }
    //后置通知(返回通知)
    @After(value = "execution(* aopanno.User.add(..))")
    public void after(){
        System.out.println("after......");
    }

    /**
     * 当有异常发生时afterThorwing通知执行,after通知不执行
     */
    //异常通知
    @AfterThrowing(value = "execution(* aopanno..User.add(..))")
    public void afterThorwing(){
        System.out.println("afterThorwing.......");
    }
    //环绕通知,在增强的方法之前和之后都执行
    @Around(value = "execution(* aopanno.User.add(..))")
    public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        System.out.println("环绕之前");//环绕之前比before执行的还早

        proceedingJoinPoint.proceed();//这就话是调用执行那个被增强的方法,这里是add()。

        System.out.println("环绕之后");//环绕之后比after执行的还晚


    }

}
  • 测试类
package aopanno;

import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestAopAnno {

    @Test
    public void testAopAnno(){
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("aopAnno.xml");
        User user = context.getBean("user", User.class);
        user.add();

    }
}

小细节:

  1. 相同切入点的抽取
  • 测试类(这个测试类相比之前在通知的注解上做了抽取)
package aopanno;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

//增强的类
@Component
@Aspect //生成代理对象
public class UserProxy {


    /**
     * 抽取相同切入点
     */
    @Pointcut(value = "execution(* aopanno.User.add(..))")//因为下面的切入点是一样的我们现在用这个注解抽取一下,下面那个方法就相当于一个名字,就是为了引用
    public void pointcutDemo(){

    }


    //前置 通知
    //@Before 注解表示前置通知,就是在你的要增强的方法之前执行
    @Before(value = "pointcutDemo()")
    public void Before(){
        System.out.println("before........");
    }
    //后置通知(返回通知)
    @After(value = "pointcutDemo()")
    public void after(){
        System.out.println("after......");
    }

    /**
     * 当有异常发生时afterThorwing通知执行,after通知不执行
     */
    //异常通知
    @AfterThrowing(value = "pointcutDemo()")
    public void afterThorwing(){
        System.out.println("afterThorwing.......");
    }
    //环绕通知,在增强的方法之前和之后都执行
    @Around(value = "pointcutDemo()")
    public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        System.out.println("环绕之前");//环绕之前比before执行的还早

        proceedingJoinPoint.proceed();//这就话是调用执行那个被增强的方法,这里是add()。

        System.out.println("环绕之后");//环绕之后比after执行的还晚


    }

}
  1. 多个增强类对同一个方法进行增强,可以设置一个优先级 实例:现在我们再写一个增强类,也对User类的add()方法做增强。
package aopanno;

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

@Component
@Aspect
@Order(1) //设置对同一个方法增强时 类之间执行的顺序
public class PersonProxy {


    @Before(value = "execution(* aopanno.User.add(..))")
    public void afterReturning(){
        System.out.println("Person Before.........");
    }
}

这个类增加了一个顺序注解@order
我们在刚刚的UserProxy上也加一个注解

image.png

3. AOP完全注解开发

需要一个注解类

package aopanno.config;


import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

/**
 * 该类为完全注解开发的配置类,下面三个注解不能少
 */
@Configuration
@ComponentScan(basePackages = {"aopanno"})  //相当于配置文件中的组件扫描
@EnableAspectJAutoProxy(proxyTargetClass = true) //相当于配置文件中的生成代理对象的配置

public class ConfigClass {
}

在测试类中生成对象时这样写

AnnotationConfigApplicationContext context1 = new AnnotationConfigApplicationContext(ConfigClass.class);

六、springJDBCTemplate操作数据库

什么是 JdbcTemplate
(1)Spring框架对 JDBC 进行封装,使用 JdbcTemplate 方便实现对数据库操作

  • 准备工作 导入maven相关依赖```

    mysql mysql-connector-java 8.0.25 compile com.alibaba druid 1.0.9 org.springframework spring-core 4.1.2.RELEASE compile org.springframework spring-jdbc 4.1.2.RELEASE compile org.springframework spring-tx 4.1.2.RELEASE compile org.springframework spring-orm 5.3.16 net.sourceforge.cglib com.springsource.net.sf.cglib 2.2.0 org.aopalliance com.springsource.org.aopalliance 1.0.0 org.aspectj aspectjweaver 1.9.7 org.springframework spring-aspects 5.2.6.RELEASE org.springframework spring-beans 5.3.16 org.springframework spring-expression 5.3.14 org.springframework spring-core 5.3.14 org.springframework spring-context 5.3.15 commons-logging commons-logging 1.2 org.springframework.boot spring-boot-starter-aop 2.6.4
```

以上是学到JdbcTemplate所用的所有maven依赖。

这个模块除了用xml文件配置一下bean,剩下的和之前学的黑马程序员哪里的javaweb 使用JdbcTemplate操作数据库,原理一样。看看ipad pdf上的笔记吧。

七、spring中事务管理

主要就是后端代码对数据库的操作。本部分没有进行边听边把例子写好,只是听了一下原理,pdf上做了一下记录,还是有一些地方不是很清楚。把数据库在学一遍后在进行详细操作吧。

八、spring5新功能

这一部分没有进行学习,做开发用到在细细的学。
(1)整合日志框架
(2)@Nullable 注解
(3)函数式注册对象
(4)整合 JUnit5单元测试框架
(5)SpringWebflux 使用