• spring5


    文章目录

    spring5

    一、spring框架基本概述

    spring是轻量级的开源javaee框架

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

    二、IOC容器

    1、什么是IOC

    IOC是控制反转,是面向对象编程中的一种设计原则,可以用来减低计算机代码之间的耦合。把对象创建和对象之间的调用过程,交给Spring进行管理。

    2、IOC底层原理

    (1)xml解析、工厂模式、反射

    原始调用方法的方式

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-h212ByOL-1661318832244)(C:\Users\28908\AppData\Roaming\Typora\typora-user-images\image-20220725185523387.png)]

    工厂模式

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Q9ubRSly-1661318832245)(C:\Users\28908\AppData\Roaming\Typora\typora-user-images\image-20220725191846168.png)]

    IOC过程(进一步降低耦合度)

    第一步 xml配置文件,配置创建的对象

    <bean id="dao" class="com.xue.UserDao">bean>
    
    • 1

    第二部 有service类和dao类,创建工厂类

    class UserFactory{
        public static User getDao(){
            //使用xml解析+反射做到
            String classValue = class属性值;//1.xml解析
            class clazz = Class.forName(classValue);//2.通过反射创建对象
           return (UserDao)clazz.newInstance();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    (2) IOC(接口)

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

    2.Spring提供IOC容器实现两种方式:(两个接口)

    (1)BeanFactory:IOC容器基本实现,spring自带的使用接口,一般不提供给我们这些开发人员使用。加载配置文件的时候不会创建对象,而是在获取对象或使用对象的时候他才去创建对象。

    (2)ApplicationContext:Bean Factory的一个子接口,提供了更多更强大的功能,一般由开发人员进行使用。加载配置文件的时候就会把在配置文件中的对象进行创建。(一般用这个)

    3.ApplicationContext接口有实现类

    他有两个实现类

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PbE3yTM7-1661318832245)(C:\Users\28908\AppData\Roaming\Typora\typora-user-images\image-20220725195223727.png)]

    第一个是全路径 第二个是类路径

    (3) Bean管理

    注:bean管理就是通过set方法实现的,所以如果某个类的属性没有set方法的话在bean里是找不到这个属性的。

    第一种方式:使用set方法进行注入
    • 创建对象:基于xml配置文件方式实现
    • 注入属性:基于注解方式实现
    a、基于xml方式创建对象
    <bean id="dao" class="com.xue.UserDao">bean>
    
    • 1

    在spring配置文件中,使用bean标签,标签里面添加对应的属性,就可以实现对象创建。创建对象的时候,默认走无参构造函数创建。

    id:表示给对象起个别名,通过名字可以得到对象,唯一标识

    class:创建对象所在类的全路径(包 类路径)

    name:早期的属性,里面可以加特殊符号,id里面不可以

    b、基于xml方式注入属性

    DI:依赖注入,就是注入属性,是IOC的一个具体实现。

    第一种注入的方式,使用set方法进行注入。

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Sv1kfYCr-1661318832246)(C:\Users\28908\AppData\Roaming\Typora\typora-user-images\image-20220725201309558.png)]

    User类

    public class User {
    //    public void add(){
    //        System.out.println("add()");
    //    }
    private String name;
    private String author;
    
    public void setName(String name) {
        this.name = name;
    }
    
    public void setAuthor(String author) {
        this.author = author;
    }
    
    public void testDemo(){
       System.out.println(name+"::"+author);
    }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    注入属性xml

    
    <bean id="user" class="xue.User">
    
    
        <property name="name" value="bbb">property>
        <property name="author" value="ccc">property>
    bean>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    测试类

    public class springTest {
    @Test
    public void testAdd(){
    //        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml")类路径
    //        2、获取配置创建的对象k
    //        "user"是xml文件里的id
        ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
    
        User user = context.getBean("user", User.class);
    //        user.add();
    
        System.out.println(user);
        user.testDemo();
    }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    第二种方式:使用有参构造进行注入

    (1) 创建类,定义属性,创建属性对应的有参数的构造方法

    (2) 在spring文件中进行配置

    注意

    无参构造注入属性

    
    
    <bean id="orders" class="xue.Orders">bean>
    
    • 1
    • 2
    • 3

    有参构造注入属性

    <bean id="orders" class="xue.Orders">
    <constructor-arg name="oname" value="abc">constructor-arg>
    <constructor-arg name="address" value="china">constructor-arg>
    bean>
    
    • 1
    • 2
    • 3
    • 4
    
    <constructor-arg index="0" value="">constructor-arg>
    
    • 1
    • 2
    第三种方式:p名称空间注入

    (1) 使用p名称空间注入,可以简化基于xml配置方式

    第一步 添加p名称空间在配置文件中

    xmlns:p="http://www.springframework.org/schema/p"
    
    • 1
    <bean id="user" class="xue.User" p:name="aaa" p:author="bbb">bean>
    
    • 1

    向属性里注入空值

    <bean id="user" class="xue.User">
        <property name="name">
            <null>null>
        property>
    bean>
    
    • 1
    • 2
    • 3
    • 4
    • 5

    属性值包含特殊符号:把特殊符号内容写到CDATA中去

    <bean id="user" class="xue.User">
        <property name="name" >
            <value>
                value>
            value>
        property>
    bean>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    第四种方式:注入属性-外部bean

    (1)创建两个类service类和dao类

    (2)在service调用dao里面的方法

    (3)在spring配置文件中进行配置

    配置文件bean.xml

    
    <bean id="userService" class="xue.service.UserService">
    
        <property name="userDao" ref="userDao">property>
    bean>
    <bean id="userDao" class="xue.dao.UserDaoImpl">bean>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    UserDao接口

    public interface UserDao  {
        public void update();
    }
    
    • 1
    • 2
    • 3

    UserDaoImpl实现类

    public class UserDaoImpl implements UserDao{
        @Override
        public void update() {
            System.out.println("update");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    UserService

    public class UserService {
        private UserDao userDao;
        public void setUserDao(UserDao userDao){
            this.userDao=userDao;
        }
        public void add(){
            System.out.println("add()");
            userDao.update();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    测试类

    @Test
    public void testUser(){
        ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
        UserService userService = context.getBean("userService", UserService.class);
       userService.add();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    第五种方式:注入属性-内部bean

    (1)一对多关系:部门和员工

    一个部门有多个员工,一个员工属于一个部门

    部门是一,员工是多

    (2)在实体类之间表示一对多关系,员工表示所属部门,使用对象类型属性进行表示

    Dept类

    public class Dept {
        private String name;
    
        public void setName(String name) {
            this.name = name;
        }
    
    //    如果这里不重写toString方法的话,那么在输出dept的时候输出的就是一个对象的地址
    //    如果写了toString那么她就会按照toString里返回的东西输出
        @Override
        public String toString() {
            return "Dept{" +
                    "name='" + name + '\'' +
                    '}';
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    Emp类

    //员工
    public class Emp {
        private String name;
        private String gender;
    
    //    员工属于某一个部门,使用对象形式表示
        private Dept dept;
    
        public void setName(String name) {
            this.name = name;
        }
    
        public void setGender(String gender) {
            this.gender = gender;
        }
    
        public void setDept(Dept dept) {
            this.dept = dept;
        }
        public void add(){
            System.out.println("emp=====add()");
            System.out.println(name+"=="+gender+"=="+dept);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    配置文件bean.xml

    <bean id="emp" class="xue.bean.Emp">
        <property name="name" value="lucy" >property>
        <property name="gender" value="nv">property>
        <property name="dept">
            <bean id="dept" class="xue.bean.Dept">
                <property name="name" value="安保部">property>
            bean>
        property>
     bean>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    测试类

    @Test
    public void testEmp(){
        ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
        Emp emp = context.getBean("emp", Emp.class);
        emp.add();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    第五种方式:注入属性-级联赋值
    <bean id="emp" class="xue.bean.Emp">
        <property name="name" value="lucy" >property>
        <property name="gender" value="nv">property>
    
        <property name="dept" ref="dept">property>
     bean>
    <bean id="dept" class="xue.bean.Dept">
        <property name="name" value="级联赋值">property>
    bean>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    <bean id="emp" class="xue.bean.Emp">
        <property name="name" value="lucy" >property>
        <property name="gender" value="nv">property>
    
        <property name="dept" ref="dept">property>
    
    
        <property name="dept.name" value="aaa">property>
     bean>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    getDet方法:返回dept对象

    public Dept getDept() {
        return dept;
    }
    
    • 1
    • 2
    • 3
    xml注入集合属性

    1.注入数组类型的属性

    2.注入List集合类型的属性

    3.注入Map集合类型的属性

    Stu类

    public class Stu {
        private String[] courses;
    
        private List<String> list;
    
        private Map<String,String> maps;
    
        private Set<String> sets;
    
        public void setSets(Set<String> sets) {
            this.sets = sets;
        }
    
        public void setList(List<String> list) {
            this.list = list;
        }
    
        public void setMaps(Map<String, String> maps) {
            this.maps = maps;
        }
    
        public void setCourses(String[] courses) {
            this.courses = courses;
        }
        public void test(){
            System.out.println("courses:"+ Arrays.toString(courses));
            System.out.println("list:"+list);
            System.out.println("map:"+maps);
            System.out.println("set:"+sets);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    bean.xml

    
    <bean id="stu" class="xue.collectionType.Stu">
        <property name="courses">
    
            <array>
                <value>语文value>
                <value>数学value>
            array>
        property>
        <property name="list">
            <list>
                <value>张三value>
                <value>小三value>
            list>
        property>
        <property name="maps">
            <map>
                <entry key="0" value="aaa">entry>
                <entry key="1" value="bbb">entry>
            map>
        property>
        <property name="sets">
            <set>
                <value>mysqlvalue>
                <value>redisvalue>
                <value>mysqlvalue>
            set>
        property>
    bean>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    测试类

    @Test
    public void testStu(){
        ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
        Stu stu = context.getBean("stu", Stu.class);
        stu.test();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    输出

    courses:[语文, 数学]
    list:[张三, 小三]
    map:{0=aaa, 1=bbb}
    set:[mysql, redis]

    在集合里面设置对象类型值

    Stu类多加属性

    //    学生所学的多门课程
    private List<Course> courseList;
    
    public void setCourseList(List<Course> courseList) {
        this.courseList = courseList;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    xml配置文件

    
    <bean id="stu" class="xue.collectionType.Stu">
    
        <property name="courseList">
            <list>
                <ref bean="course1">ref>
                <ref bean="course2">ref>
            list>
        property>
    bean>
    
    
    <bean id="course1" class="xue.collectionType.Course">
        <property name="name" value="spring5框架课程">property>
    bean>
    <bean id="course2" class="xue.collectionType.Course">
        <property name="name" value="mybatis框架课程">property>
    bean>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    把集合注入的部分提取出来

    在spring配置文件中引入名称空间util

    
    <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:util="http://www.springframework.org/schema/util"
           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/beans/spring-util.xsd">
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    book类

    public class Book {
        private List<String> list;
    
        public void setList(List<String> list) {
            this.list = list;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    配置文件

    <util:list id="bookList">
        <value>book1value>
        <value>book2value>
        <value>book3value>
    util:list>
    
    
    <bean id="book" class="xue.collectionType.Book">
        <property name="list" ref="bookList">property>
    bean>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    IOC操作Bean管理(FactoryBean)

    1、Spring有两种类型Bean,一种普通bean,另外一种工厂bean(FactoryBean)

    2、普通bean:在配置文件中定义bean类型就是返回类型

    3、工厂bean:在配置文件定义bean类型可以和返回类型不一样

    第一步 创建类,让这个类作为工厂bean,实现接口FactoryBean

    第二步 实现接口里面的方法,在实现的方法中定义返回的bean类型

    MyBean类

    public class MyBean implements FactoryBean<Course> {
    //    定义返回bean的对象
    //    虽然是MyBean类但是通过重写getObject方法,可以返回一个course对象 这样就更改了他的返回值类型
        @Override
        public Course getObject() throws Exception {
            Course course = new Course();
            course.setName("aaa");
            return course;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    配置文件

    
    <bean id="myBean" class="xue.factoryBean.MyBean">bean>
    
    • 1
    • 2

    测试类

    @Test
    public void testBean(){
        ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
        //这里的getBean的第二个参数也要改成需要返回的对象的类型
        Course course = context.getBean("myBean", Course.class);
        System.out.println(course);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    IOC操作Bean管理(bean作用域)

    1、在spring里面,设置创建bean实例是单例还是多例

    2、在spring里默认情况下,bean是一个单实例对象

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-choWbhjI-1661318832247)(C:\Users\28908\AppData\Roaming\Typora\typora-user-images\image-20220727133607086.png)]

    3、如何设置单实例还是多实例

    (1)spring配置文件bean标签里面有属性(scope)用于设置单实例还是多实例

    (2)scope属性值

    第一个值 默认值,singleton,表示单实例对象

    第二个值 prototype,表示是多实例对象

    <bean id="myBean" class="xue.factoryBean.MyBean" scope="prototype">bean>
    
    • 1

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ile6uCOi-1661318832247)(C:\Users\28908\AppData\Roaming\Typora\typora-user-images\image-20220727134202856.png)]

    (3)singleton和prototype区别

    第一 singleton是单实例,prototype是多实例

    第二 设置scope值是singleton时候,加载spring配置文件时候就会创建单实例对象

    设置scope的值为prototype时,不是在加载spring配置文件时创建对象,而是在调用getBean方法的时候创建对象

    request

    session

    4、bean生命周期

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ixKBfSP5-1661318832248)(C:\Users\28908\AppData\Roaming\Typora\typora-user-images\image-20220727135815252.png)]

    销毁IOC容器的方法

    context.close()

    
    <bean id="myBean" class="xue.factoryBean.MyBean" scope="singleton" init-method="a()" destroy-method="b()">bean>
    
    • 1
    • 2

    5、演示添加后置处理器效果

    (1)创建类,实现接口BeanPostProcessor,创建后置处理器

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BLMZMKum-1661318832248)(C:\Users\28908\AppData\Roaming\Typora\typora-user-images\image-20220727150217632.png)]

    MyBeanPost方法

    public class MyBeanPost implements BeanPostProcessor {
        @Override
        public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
            System.out.println("在初始化之前执行的方法 ");
            return BeanPostProcessor.super.postProcessBeforeInitialization(bean, beanName);
        }
    
        @Override
        public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
            System.out.println("在初始化之后执行的方法 ");
            return BeanPostProcessor.super.postProcessAfterInitialization(bean, beanName);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    配置文件

    <bean id="myBeanPost" class="xue.bean.MyBeanPost">bean>
    
    • 1
    IOC操作Bean管理(xml自动装配)

    1、什么是自动装配

    (1)根据指定装配规则(属性名称或者属性类型),spring自动将匹配的属性值进行注入

    2、演示自动装配的过程

    根据属性名称自动装配

    
    
    
    
    <bean id="emp" class="xue.autowire.Emp" autowire="byName">
    
    bean>
    <bean id="dept" class="xue.autowire.Dept">bean>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    (2)根据属性类型自动装配

    <bean id="emp" class="xue.autowire.Emp" autowire="byType">
    
    bean>
    <bean id="dept" class="xue.autowire.Dept">bean>
    
    • 1
    • 2
    • 3
    • 4
    IOC操作Bean管理(外部属性文件)

    1、直接配置数据库信息

    (1)配置德鲁伊连接池

    
    <bean id="druid" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver">property>
        <property name="url" value="jdbc:mysql://localhost:3306/userDb">property>
        <property name="username" value="root">property>
        <property name="password" value="root">property>
    bean>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    (2)引入德鲁伊连接池依赖jar包

    2、引入外部属性文件配置数据库连接池

    (1)创建外部属性文件,properties格式文件,写数据库信息

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JpWrFole-1661318832248)(C:\Users\28908\AppData\Roaming\Typora\typora-user-images\image-20220727170423854.png)]

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bJZIVp8r-1661318832249)(C:\Users\28908\AppData\Roaming\Typora\typora-user-images\image-20220727173009130.png)]

    IOC操作Bean管理(基于注解方式)

    注解默认是单例

    创建bean实例 也就是创建对象

    @Component

    @Service

    @Controller

    @Repository

    这四个都是一样 的作用,作用在类上面,只是使用的位置不一样,方便使用者分清角色

    基于注解方式实现创建对象

    第一步 引入依赖 aop依赖

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5khjM3er-1661318832249)(C:\Users\28908\AppData\Roaming\Typora\typora-user-images\image-20220727174043451.png)]

    第二步 开启组件的扫描

    只有开启组件的扫描,spring才知道哪里有注解

    
    
    
    
    
        <context:component-scan base-package="xue">context:component-scan>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    例如:

    //在注解里面value属性值可以不写,默认值是类名称,首字母小写
    @Component(value = "userService")//是等价的
    public class UserService {
        public void add(){
            System.out.println("add()");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    开启组件扫描细节配置

    1、配置哪些类扫描哪些类不扫描

    use-default-filters="false"表示现在不使用默认filter,自己配置filter context:include-filter,设置扫描哪些内容

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GY7BkWAD-1661318832250)(C:\Users\28908\AppData\Roaming\Typora\typora-user-images\image-20220728095029130.png)]

    只扫描Controller注解

    2、设置哪些内容不去扫描[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iMzRYa8u-1661318832250)(C:\Users\28908\AppData\Roaming\Typora\typora-user-images\image-20220728095224564.png)]

    基于注解方式实现属性注入

    (1)@Autowired

    • 根据属性类型进行自动注入

    (2)@Qualitiler

    • 根据属性的名称进行注入 和@Autowired一起使用
    @Service
    public class UserService {
    //    添加注入属性注解 不需要添加set方法
        @Autowired
    //    一个接口有多个实现类,她不知道该找哪个实现类,所以加个名字
    //    如果不写的话,默认就是她首字母小写的实现类
        @Qualifier(value = "userDaoImpl")
        private UserDao userDao;
        public void add(){
            System.out.println("service----add()");
            userDao.add();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    (3)@Resource

    • 可以根据类型注入,也可以根据名称注入

    (4)@Value

    • 注入普通类型属性
    @Value(value = "aaa")
    private String name;
    
    • 1
    • 2

    纯注解开发

    (1)创建配置类,替代xml配置文件

    @Configuration//作为配置类,替代xml配置文件
    @ComponentScan(basePackages = "xue")//相当于xml配置扫描某个包
    public class SpringConfig {
        
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    (2)编写测试类

        @Test
        public void test(){
    //        代替了之前的bean.xml文件
             ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
    //         如果不写@Component(value = "userService"),那么getBean的第一个参数就是类名的首字母小写
            UserService userservice = context.getBean("userService", UserService.class);
            userservice.add();
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    三、AOP

    1、什么是AOP

    面向切面(方面)编程,可以对业务逻辑的各个部分进行隔离,从而使业务逻辑各个部分进行隔离,从而使业务逻辑各个部分之间的耦合度降低,降低程序的可重用性。

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uHyFjYqb-1661318832251)(C:\Users\28908\AppData\Roaming\Typora\typora-user-images\image-20220728131622563.png)]

    通俗描述:不改源代码,添加新功能

    2、底层原理

    AOP底层使用动态代理

    第一种 有接口情况,使用JDK动态代理

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FQJvPzQx-1661318832252)(C:\Users\28908\AppData\Roaming\Typora\typora-user-images\image-20220728133122594.png)]

    第二种 没有接口情况,

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-b9FbyTXv-1661318832253)(C:\Users\28908\AppData\Roaming\Typora\typora-user-images\image-20220728133633200.png)]

    AOP(jdk动态代理)

    使用jdk动态代理,使用Proxy类里面的方法创建代理对象 调用newProxyInstance方法

    这个方法里有三个参数,第一个类加载器classLoader,第二个增强方法所在的类,这个类实现的接口支持多个接口,第三个InvocationHandler(interface)实现这个接口创建代理的对象,写增强的方法。

    编写jdk动态代理代码

    (1)创建接口,定义方法

    public interface UserDao  {
        public int add(int a ,int b);
        public void update(String id);
    }
    
    • 1
    • 2
    • 3
    • 4

    (2)创建接口实现类,实现方法

    @Repository
    public class UserDaoImpl implements UserDao{
        @Override
        public int add(int a, int b) {
            return a+b;
        }
    
        @Override
        public String update(String id) {
            return id;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    JDKProxy代理类

    public class JDKProxy {
        public static void main(String[] args) {
            Class[] interfaces = {UserDao.class};
    //        Proxy.newProxyInstance(
    //                JDKProxy.class.getClassLoader(),
    //                interfaces,
    //                new InvocationHandler() {
    //                    @Override
    //                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    //                        return null;
    //                    }
    //                }
    //        );
            UserDaoImpl userDao = new UserDaoImpl();
    
            Proxy.newProxyInstance(
                    JDKProxy.class.getClassLoader(),
                    interfaces,
                    new UserDaoProxy(userDao)
            );
        }
    }
    
    //创建代理对象的代码
    class UserDaoProxy implements InvocationHandler{
    //    把创建的是谁的代理对象,把谁给传递过来
    //    通过一个有参构造进行传递
        private Object obj;
        public UserDaoProxy(Object obj){
            this.obj = obj;
        }
    
    
    //    写增强的逻辑
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    //        写增强的逻辑
    //        方法之前执行
            System.out.println("qian");
    //        被增强的方法执行
    
    //        方法之后
            return 1;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45

    3、AOP(术语)

    1、连接点

    类里面的哪些方法可以被增强,这些方法成为连接点。

    2、切入点

    实际被真正增强的方法,成为切入点

    3、通知(增强)

    (1)实际增强的逻辑部分成为通知(增强)

    (2)通知有多种类型

    • 前置通知 方法前执行
    • 后置通知 方法后执行
    • 环绕通知 前后都执行
    • 异常通知 有异常执行
    • 最终通知 finally

    4、切面

    是动作

    (1)把通知应用到切入点的过程

    4、AOP操作(准备)

    1、Spring框架一般基于AspectJ实现AOP操作

    (1)什么是AspectJ

    • AspectJ不是spring组成部分,独立AOP框架,一般把AspectJ和spring框架一起使用,进行AOP操作

    2、基于AspectJ实现AOP操作

    (1)基于xml配置文件实现

    (2)基于注解方式实现(使用)

    3、在项目的工程里面先引入AOP相关依赖

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BlOusJPb-1661318832254)(C:\Users\28908\AppData\Roaming\Typora\typora-user-images\image-20220729105045645.png)]

    主要是

    <dependency> 
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-aopartifactId>
        <version>2.7.0version>
    dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5

    4、切入点表达式

    (1)切入点表达式作用:知道对哪个类里面的哪个方法进行增强

    (2)语法结构:

    Execution([权限修饰符] [返回类型] [类全路径] ([参数列表]))

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-M3SOeqBX-1661318832254)(C:\Users\28908\AppData\Roaming\Typora\typora-user-images\image-20220729105816764.png)]

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2S4l6r7w-1661318832254)(C:\Users\28908\AppData\Roaming\Typora\typora-user-images\image-20220729105953869.png)]

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-igNHbteF-1661318832255)(C:\Users\28908\AppData\Roaming\Typora\typora-user-images\image-20220729110131579.png)]

    5、AOP操作(AspectJ注解)

    1. 创建类 在类里面增强方法
    //被增强的类
    public class User {
        public void add(){
            System.out.println("add====");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    1. 创建增强类,编写增强逻辑

    (1)在增强类里面创建方法,让不同方法代表不同通知类型

    //增强的类
    public class UserProxy {
    //    前置通知 在add()方法前执行
        public void before(){
            System.out.println("before======");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    1. 通知的配置

    如果切面不起作用的话,在User类上加注解:@EnableAspectJAutoProxy(exposeProxy = true)

    (1)在spring的配置文件中,开启注解的扫描

    
    <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="xue.aopanno">context:component-scan>
    beans>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    (2)使用注解创建User和UserProxy对象

    @Component
    public class UserProxy {}
    @Component
    public class User {}
    
    • 1
    • 2
    • 3
    • 4

    (3)在你的增i强的类上面添加注解@Aspect

    @Component
    @Aspect
    public class UserProxy {}
    
    • 1
    • 2
    • 3

    (4)在spring的配置文件中开启生成代理对象

    
    
        <aop:aspectj-autoproxy>aop:aspectj-autoproxy>
    
    • 1
    • 2
    • 3
    1. 配置不同类型的通知

    (1)在增强类的里面,在作为通知方法上面添加通知类型注解,使用切入点表达式配置

    //增强的类
    @Component
    @Aspect
    public class UserProxy {
    //    前置通知 在add()方法前执行
    //    @Before表示作为前置通知
    //    后置@After
    //        @AfterReturning在方法返回结果后执行,最终通知
    //    异常通知@AfterThrowing
    //        环绕通知@Around
        @Before(value = "execution(* xue.aopanno.User.add(..))")
        public void before(){
            System.out.println("before======");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    环绕通知:

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hZltFGdA-1661318832255)(C:\Users\28908\AppData\Roaming\Typora\typora-user-images\image-20220729135254694.png)]

    结果:

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ScxQ7z89-1661318832255)(C:\Users\28908\AppData\Roaming\Typora\typora-user-images\image-20220729135537861.png)]

    测试

    public class TestAop {
        @Test
        public void testAopAnno(){
            ApplicationContext context = new ClassPathXmlApplicationContext("bean2.xml");
            User user = context.getBean("user", User.class);
            user.add();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    注意:这个test必须要引入依赖包

    <dependency> <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-testartifactId>
        <version>2.7.0version>
    dependency>
    
    • 1
    • 2
    • 3
    • 4

    输出

    before==
    add====

    1. 抽取相同的切入点

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CeuRgLYK-1661318832256)(C:\Users\28908\AppData\Roaming\Typora\typora-user-images\image-20220729145734408.png)]

    1. 多个增强类对同一个方法进行增强,设置增强类优先级

    (1)在增强类上面添加注释@Order(数组型值),数字型值越小优先级越高

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jZlyYibY-1661318832256)(C:\Users\28908\AppData\Roaming\Typora\typora-user-images\image-20220729150305371.png)]

    AOP操作(AspectJ注解)

    ConfigAop.java

    @Configuration
    @ComponentScan(basePackages = {"xue"})
    //开启Aspect生成代理对象
    @EnableAspectJAutoProxy(proxyTargetClass = true)
    public class ConfigAop {
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    四、事务

    概念

    1、什么是事务

    (1)事务是数据库操作最基本单元,逻辑上一组操作,要么都成功,如果有一个失败所有操作都失败

    (2)典型场景:银行转账

    2、事务四个特性ACID

    (1)原子性

    (2)一致性

    (3)隔离性

    (4)持久性

    搭建事务操作环境

    转账环境

    web:

    service:业务操作(创建转账的方法1.调用dao两个方法)

    dao:数据库操作不写业务(创建两个方法:1.少钱的方法2.多钱的方法)

    spring任务管理介绍

    spring事务管理api,提供一个接口代表事务管理器,这个接口针对不同的框架提供不同的实现类。[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kfQqCg6M-1661318832256)(C:\Users\28908\AppData\Roaming\Typora\typora-user-images\image-20220801132956230.png)]

    注解声明式事务管理

    1、在spring配置文件中,配置事务管理器

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fOYZ4Jar-1661318832257)(C:\Users\28908\AppData\Roaming\Typora\typora-user-images\image-20220801133313388.png)]

    2、开启事务注解

    (1)在spring配置文件引入名称空间

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tgq79NOY-1661318832257)(C:\Users\28908\AppData\Roaming\Typora\typora-user-images\image-20220801133419035.png)]

    (2)开启事务注解

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Kb0HuU3D-1661318832257)(C:\Users\28908\AppData\Roaming\Typora\typora-user-images\image-20220801133523391.png)]

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-z6UBAAmU-1661318832258)(C:\Users\28908\AppData\Roaming\Typora\typora-user-images\image-20220801150948242.png)]

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kgYkhBvH-1661318832258)(C:\Users\28908\AppData\Roaming\Typora\typora-user-images\image-20220801151515618.png)]

    3、在service类上面(获取service类里面方法上面)添加事务注解

    (1)@Transactional这个注解添加到类上面,也可以添加方法上面

    (2)如果把这个注解添加类上面,这个类里面所有的方法都添加事务

    (3)如果把这个注解添加方法上面,为这个方法添加事务[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dkvoaksS-1661318832258)(C:\Users\28908\AppData\Roaming\Typora\typora-user-images\image-20220801133840496.png)]

    Transactional第一个属性-propagation:事务传播行为

    @Transactional(propagation= Propagation.SUPPORTS)

    当一个事务的方法被另外一个事务方法调用的时候,这个事务方法如何执行

    REQUIRED:如果有事务在运行,那当前方法就在这个事务内运行,否则,就启动一个新的事务,并在自己的事务内运行

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3amAaU4q-1661318832259)(C:\Users\28908\AppData\Roaming\Typora\typora-user-images\image-20220801134622879.png)]

    REQUIRED_NEW:当前的方法必须启动新事务,并在它自己的事务内运行,如果有事务正在运行,应将他挂起

    SUPPORTS:如果有事务在运行,当前的方法就在这个事务内运行,否则它可以不运行在事务中。

    https://blog.csdn.net/wojiaoxubo/article/details/85158445

    Transactional第二个属性-ioslation:事务隔离级别

    1、事务有特性成为隔离性,多事务操作之间不会产生影响,不考虑隔离性产生很多问题

    2、有三个读问题:脏读、不可重复读、虚(幻)读

    3、脏读:多事务之间,一个未提交的事务,读取到了另一个未提交事务的数据

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2Mb1z5b2-1661318832260)(C:\Users\28908\AppData\Roaming\Typora\typora-user-images\image-20220801141215452.png)]

    4、不可重复读:在同一次事务中前后查询不一致的问题

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uTWxDWRn-1661318832260)(C:\Users\28908\AppData\Roaming\Typora\typora-user-images\image-20220801141153029.png)]

    5、幻读:一次事务中前后数据量发生变化,用户产生不可预料的问题

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-l1Qu8Z0d-1661318832261)(C:\Users\28908\AppData\Roaming\Typora\typora-user-images\image-20220801141122224.png)]

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3dxYGpG5-1661318832262)(C:\Users\28908\AppData\Roaming\Typora\typora-user-images\image-20220801141406392.png)]

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mSnWcUxg-1661318832262)(C:\Users\28908\AppData\Roaming\Typora\typora-user-images\image-20220801142030428.png)]

    Transactional第三个属性-timeout

    (1)事务需要在一定时间内进行提交,如果不提交进行回滚

    (2)默认值是-1,设置时间以秒单位进行计算

    Transactional第四个属性-readOnly是否只读

    (1)读:查询操作,写:添加修改删除操作

    (2)readOnly默认值false,表示可以查询,可以添加修改删除操作

    (3)设置成true,只能查询,不可以添加修改删除操作

    Transactional第五个属性-roobackFor回滚

    (1)设置出现哪些异常进行事务的回滚

    Transactional第六个属性-noRollbackFor-不回滚

    (1)设置出现哪些异常进行事务的不进行回滚

    五、整合日志框架

    整个spring5框架的代码基于java8,运行时兼容jdk9,旭东不建议使用的类和方法在电脑中删除,建议log4j2

    整合log4j2日志

    片转存中…(img-dkvoaksS-1661318832258)]

    Transactional第一个属性-propagation:事务传播行为

    @Transactional(propagation= Propagation.SUPPORTS)

    当一个事务的方法被另外一个事务方法调用的时候,这个事务方法如何执行

    REQUIRED:如果有事务在运行,那当前方法就在这个事务内运行,否则,就启动一个新的事务,并在自己的事务内运行

    [外链图片转存中…(img-3amAaU4q-1661318832259)]

    REQUIRED_NEW:当前的方法必须启动新事务,并在它自己的事务内运行,如果有事务正在运行,应将他挂起

    SUPPORTS:如果有事务在运行,当前的方法就在这个事务内运行,否则它可以不运行在事务中。

    https://blog.csdn.net/wojiaoxubo/article/details/85158445

    Transactional第二个属性-ioslation:事务隔离级别

    1、事务有特性成为隔离性,多事务操作之间不会产生影响,不考虑隔离性产生很多问题

    2、有三个读问题:脏读、不可重复读、虚(幻)读

    3、脏读:多事务之间,一个未提交的事务,读取到了另一个未提交事务的数据

    [外链图片转存中…(img-2Mb1z5b2-1661318832260)]

    4、不可重复读:在同一次事务中前后查询不一致的问题

    [外链图片转存中…(img-uTWxDWRn-1661318832260)]

    5、幻读:一次事务中前后数据量发生变化,用户产生不可预料的问题

    [外链图片转存中…(img-l1Qu8Z0d-1661318832261)]

    [外链图片转存中…(img-3dxYGpG5-1661318832262)]

    [外链图片转存中…(img-mSnWcUxg-1661318832262)]

    Transactional第三个属性-timeout

    (1)事务需要在一定时间内进行提交,如果不提交进行回滚

    (2)默认值是-1,设置时间以秒单位进行计算

    Transactional第四个属性-readOnly是否只读

    (1)读:查询操作,写:添加修改删除操作

    (2)readOnly默认值false,表示可以查询,可以添加修改删除操作

    (3)设置成true,只能查询,不可以添加修改删除操作

    Transactional第五个属性-roobackFor回滚

    (1)设置出现哪些异常进行事务的回滚

    Transactional第六个属性-noRollbackFor-不回滚

    (1)设置出现哪些异常进行事务的不进行回滚

    五、整合日志框架

    整个spring5框架的代码基于java8,运行时兼容jdk9,旭东不建议使用的类和方法在电脑中删除,建议log4j2

    整合log4j2日志

  • 相关阅读:
    Spring-Cloud-Gateway Filter详细配置说明
    Web前端:NextJS与React——主要差异、优势和局限性
    最长异或路径 ---- (字典树求异或最大)
    使用python调用ssh操作linux远程服务器办法
    2.5 晶体管单管放大电路的三种基本接法
    五张图带你理解 RocketMQ 顺序消息实现机制
    9.前端初步设计
    【白嫖当福利】MeterSphere 部署篇
    数据库管理-第220期 Oracle的高可用-03(20240715)
    数据库管理-第104期 RAC上升级SSH的坑(20230918)
  • 原文地址:https://blog.csdn.net/qq_46503396/article/details/126502708