spring基础知识(一)

spring基础知识

环境搭建

image-20240712142903074

创建子模块

image-20240712143717408

之后在弹出的框中配置好

image-20240712143854962

在spring-first的pom.xml加入

    <dependencies>
<!--        spring context依赖-->
<!--        当你引入spring Context后,表示将spring的基础依赖引入了-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>6.0.2</version>
        </dependency>
<!--        junit5-->
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter</artifactId>
            <version>5.3.1</version>
        </dependency>
    </dependencies>

更新maven依赖,记得换源

在spring-first中的src java里面建包

image-20240712144818699

起名spring6

在里面建个类

package spring6;

public class User {
    public void add(){
        System.out.println("add...");
    }
}

在resource创建xml配置

image-20240712145440454

image-20240712145331930

image-20240712145550153

之后配置文件xml就初始化好了

这个xml具体作用是:自动创建对象

比如说以前要这样New一个对象

public static void main(String[] args) {
    User user = new User();
    user.add();
}

用Bean.xml可以使用bean标签创建对象,像这样:

<!--完成user对象创建-->
<!--    bean标签-->
<!--        1.id 书写:唯一标识符-->
<!--        2.clas 属性:要创建对象所在类的全路径(包名称+类名称)-->

    <bean id = "user" class="spring6.User"></bean>

添加后,我们新建一个类写一个方法进行测试

package spring6;

import org.junit.jupiter.api.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestUser {
    @Test
    public void testUserObject(){
        // 加载spring配置文件,对象创建
        ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");//配置文件名
        // 获取创建对象
        User user = (User) context.getBean("user");//bean id
        System.out.println(user);

        //使用对象调用方法进行测试
        user.add();
    }
}

image-20240712152512266

总的说就是这样

image-20240712152826922

如果在这里面写无参构造方法

image-20240712162658432

无参构造方法将会被执行

这样新建对象的本质

底层新建对象的流程如下
1.bean.xml配置
2.加载bean.xml
3.反射构造一个类
4.将对象储存于 Map<String, BeanDefinition> beanDefinitionMap

说到这复习了一下反射

        // 获取类Class对象
        Class aClass = Class.forName("spring6.User");
        User user = (User) aClass.getDeclaredConstructor().newInstance();
        System.out.println(user);

Log4j2

apache的一个日志组件,我们将对他的日志信息优先级、输出方式(控制台/文件)、输出格式进行配置

一般而言。优先级

image-20240712163955745

优先级高的会优先输出,如果设置了xx,只会输出优先级大于等于xx的信息

环境搭建

pom.xml

<!--        log4j2依赖-->
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-core</artifactId>
            <version>2.19.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-slf4j2-impl</artifactId>
            <version>2.19.0</version>
        </dependency>

log4j2.xml (resources目录下)

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
    <Appenders>
        <Console name="Console" target="SYSTEM_OUT">
            <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
        </Console>
    </Appenders>
<!--    <File name="log" fileName="./test.log" append="false">-->
<!--        <PatternLayout pattern="%d{HH:mm:ss.SSS} %-5level %class{36} %L %M - %msg%xEx%n"/>-->
<!--    </File>-->
    <Loggers>
        <Root level="DEBUG">
            <AppenderRef ref="Console"/>
        </Root>
    </Loggers>
</Configuration>

测试成功

image-20240712171334151

输出到文件报错了,以后用到再回来学

如果要手动输出到日志,是这样

image-20240712171423866

比较少见,不演示了

Ioc-xml模式

一种面向对象的设计思想,中文为控制反转

意思是通过IoC容器来管理java对象的实例化和初始化,控制对象与对象之间的依赖关系,

由IoC容器管理的java对象称为String Bean

容器房bean,用map集合

xml配置文件 Bean定义信息(BeanDefinition)

抽象 BeanDefinitionReader

IoC容器 Bean定义信息 实例化 BeanFactory工厂+反射

​ 初始化 最终对象

DI依赖注入

DI(Dependency Injection)指Spring创建对象的过程中,将对象依赖属性通过配置进行注入

实现方式:

  • set注入
  • 构造注入

IOC是一种控制反转的思想,而DI是对IoC的一种具体实现

具体实现:

BeanFactory是其具体实现,但是不对外开放,我们可以操作它的子接口ApplicationContext

https://www.cnblogs.com/tanghaorong/p/13432008.html

image-20240713155714647

注解也继承了ApplicationContext

IOC环境搭建

image-20240714201441457

在父项目中新建一个项目spring-ioc-xml

image-20240713164329949

在父项目的pom中把之前的依赖引入,原来子项目的依赖会自动引入,可以删了

  <dependencies>
        <!--        spring context依赖-->
        <!--        当你引入spring Context后,表示将spring的基础依赖引入了-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>6.0.2</version>
        </dependency>
        <!--        junit5-->
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter</artifactId>
            <version>5.6.3</version>
        </dependency>
        <!--        log4j2依赖-->
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-core</artifactId>
            <version>2.19.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-slf4j2-impl</artifactId>
            <version>2.19.0</version>
        </dependency>

    </dependencies>

在这个新建的项目中,new一个xml配置

image-20240713182740340

叫bean.xml,新建后记得按右上角那个东西

然后建一个包com.thaistudyspring.iocxml

User.class

package com.thaistudyspring.iocxml;

public class User {
    private String name;
    private Integer age;
    public void run(){
        System.out.println("run......");
    }
}

bean.xml

<bean id = "user" class = "com.thaistudyspring.iocxml.User"></bean>

TestUser

package com.thaistudyspring.iocxml;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestUser {
    public static void main(String[] args) {
        ApplicationContext cont = new ClassPathXmlApplicationContext("bean.xml");
        // 根据id获取bean
        User user = (User) cont.getBean("user");
        System.out.println("根据id获取bean: " + user);
        // 根据类型获取bean
        User user1 = (User)cont.getBean(User.class);
        System.out.println("根据类型获取bean: " + user1);
        // 根据id和类型
        User user2 = cont.getBean("user", User.class);
        System.out.println("根据id和类型: " + user2);

    }
}

跑一下,成功,截图不放了

  • 实验1:当一个类型有多个类实现时,还可以使用类型获取这个类吗

bean.xml

<bean id = "user" class = "com.thaistudyspring.iocxml.User"></bean>
<bean id = "user1" class = "com.thaistudyspring.iocxml.User"></bean>

运行报错

image-20240713183326411

用类型去获取bean就会报错了,因为它只能获取单个bean实例,而这里有多个实现对象

  • 实验2:接口是否也可以获取到其实现的类

接口是否也可以获取到其实现的类呢,答案是可以的

bean.xml

<!--根据接口也能获取到类-->
    <bean id = "userDaoImpl" class="com.thaistudyspring.iocxml.bean.UserDaoImpl"></bean>

写一个userDao接口

package com.thaistudyspring.iocxml.bean;

public interface UserDao {
    public void run();
}

写一个实现(注意快捷键

package com.thaistudyspring.iocxml.bean;

public class UserDaoImpl implements UserDao{
    @Override
    public void run() {
        System.out.println("thaiTest UserDaoImpl !");
    }
}

测试类

package com.thaistudyspring.iocxml.bean;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestUserDao {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
        // 根据类型获取接口对应的bean
        UserDao userDao = context.getBean(UserDao.class);
        System.out.println(userDao);

    }
}

image-20240713185927363

但是如果接口有多个实现类,就不可以根据接口类型获取这个类(参考实验1)

setting和构造器

bean往往有setting和构造器,如何通过xml直接new一个已经设置好属性的对象呢?

比如说book类(alt + insert 生成setter/getter/构造方法)

package com.thaistudyspring.iocxml.di;

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

    //生成set方法

    public Book() {
    }
    public Book(String bname, String author) {
        this.bname = bname;
        this.author = author;
    }

    public String getBname() {
        return bname;
    }

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

    public String getAuthor() {
        return author;
    }

    public void setAuthor(String author) {
        this.author = author;
    }

    @Override
    public String toString() {
        return "Book{" +
                "bname='" + bname + '\'' +
                ", author='" + author + '\'' +
                '}';
    }

    public static void main(String[] args) {
        Book book = new Book();
        // set方法
        book.setBname("jvav");
        book.setAuthor("tha1");

        // 构造器注入
        Book book2 = new Book("jvav", "tha1");

    }

}

通过xml可以这样设置

bean-di.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">
    <!--    set 方法注入-->
    <bean id = "book" class="com.thaistudyspring.iocxml.di.Book">
        <property name="bname" value="前端开发"></property>
        <property name="author" value="tha1"></property>
    </bean>
</beans>

TestBook.java

package com.thaistudyspring.iocxml.di;

import org.junit.jupiter.api.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestBook {
    @Test
    public  void testSetter() {
        ApplicationContext context = new ClassPathXmlApplicationContext("bean-di.xml");
        Book book =  context.getBean("book", Book.class);
        System.out.println(book);
    }
}

image-20240714163908469

还有一种方法,就是使用构造器进行注入

bean-di.xml (记得把前面的注释掉,不然也会new

    <!--    构造器注入-->
    <bean id="bookCon" class="com.thaistudyspring.iocxml.di.Book">
        <constructor-arg name = "bname" value="java开发"></constructor-arg>
        <constructor-arg name = "author" value="tha1"></constructor-arg>
    </bean>

测试

    @Test
    public  void testConstructor() {
        ApplicationContext context = new ClassPathXmlApplicationContext("bean-di.xml");
        Book book =  context.getBean("bookCon", Book.class);
        System.out.println(book);
    }

image-20240714180410878

特殊值处理

  • 字面量赋值,示例如下
    <bean id = "book" class="com.thaistudyspring.iocxml.di.Book">
        <property name="bname" value="前端开发"></property>
        <property name="author" value="tha1"></property>
    </bean>
  • 空值

如何给一个属性赋空值

    <bean id = "book" class="com.thaistudyspring.iocxml.di.Book">
        <property name="bname" value="前端开发"></property>
        <property name="author"><null/></property>
    </bean>
  • xml

如果双引号也要写标签符,用实体编码

<

>

如下:

    <bean id = "book" class="com.thaistudyspring.iocxml.di.Book">
        <property name="bname" value="前端开发"></property>
        <property name="author" value="<>"></property>
    </bean>
  • CDATA节

或者采用另一种xml特有的方法代替实体字符:CDATA节

格式是![CDATA[xxxxxxxxxx]]

a<b将被打印出来

    <bean id = "book" class="com.thaistudyspring.iocxml.di.Book">
        <property name="bname" value="前端开发"></property>
        <property name="author">
            <value><![CDATA[a<b]]></value>
        </property>
    </bean>

image-20240715141329404

特殊类型

1.对象

测试demo

package com.thaistudyspring.iocxml.ditest;

public class Dept {
    private String dname;

    public String getDname() {
        return dname;
    }

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

    public void info(){
        System.out.println("部门名称: " + dname);
    }
}
package com.thaistudyspring.iocxml.ditest;

public class Emp {

    // 员工属于哪个部门
    private Dept dept;
    private String ename;
    private Integer age;

    public Dept getDept() {
        return dept;
    }

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

    public String getEname() {
        return ename;
    }

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

    public Integer getAge() {
        return age;
    }

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

    public void work(){
        System.out.println(ename + " is working for " + age);
        dept.info();
    }
}
  • 第一种方法是外部引入bean

bean-ditest.xml

<!--    创建两个类对象-->
<!--    在emp的bean标签哩,使用property引入dept的bean-->
<!--    -->
    <bean id="dept" class="com.thaistudyspring.iocxml.ditest.Dept">
        <property name="dname" value="安保部"></property>
    </bean>

    <bean id="emp" class="com.thaistudyspring.iocxml.ditest.Emp">
<!--        普通属性注入-->
        <property name="ename" value="lucy"></property>
        <property name="age" value="50"></property>
<!--注入对象属性-->
        <property name="dept" ref="dept"></property>
    </bean>

主要就是先new一个对象,然后用ref(注意不是value)引入这个beanid

package com.thaistudyspring.iocxml.ditest;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.core.io.ClassPathResource;

public class TestDi {

    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("bean-ditest.xml");
        Emp emp = context.getBean("emp", Emp.class);
        emp.work();
    }

}

image-20240715143852386

  • 第二种方法是内部引入bean
<!--    内部bean注入-->
    <!--    在emp的bean标签哩,再创建dept的bean标签-->
    <!--    -->

    <bean id="emp2" class="com.thaistudyspring.iocxml.ditest.Emp">
        <!--        普通属性注入-->
        <property name="ename" value="lucy"></property>
        <property name="age" value="50"></property>
        <!--注入对象属性-->
        <property name="dept">
            <bean id="dept2" class="com.thaistudyspring.iocxml.ditest.Dept">
                <property name="dname" value="安保部"></property>
            </bean>
        </property>
    </bean>
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("bean-ditest.xml");
        Emp emp = context.getBean("emp2", Emp.class);
        emp.work();
    }

image-20240715144207804

  • 第三种 级联赋值

数组类型

比如说给emp加一个这个

    public String[] getLoves() {
        return loves;
    }
    <bean id="dept" class="com.thaistudyspring.iocxml.ditest.Dept">
        <property name="dname" value="技术部"></property>
    </bean>
    <bean id="emp" class="com.thaistudyspring.iocxml.ditest.Emp">
        <!--        普通属性注入-->
        <property name="ename" value="lucy"></property>
        <property name="age" value="50"></property>
        <!--注入对象属性-->
        <property name="dept" ref="dept"></property>
<!--        数组类型-->
        <property name="loves">
            <array>
                <value>吃饭</value>
                <value>睡觉</value>
                <value>敲代码</value>
            </array>
        </property>
    </bean>

集合类型

比如list类型

dept类

    private List<Emp> empList;
    ...
    public void info(){
    System.out.println("部门名称: " + dname);
    for (Emp emp:empList){
    System.out.println(emp.getEname() + " is " + emp.getAge() + " years old");
        }
    }

xml

    <bean id="emp1" class="com.thaistudyspring.iocxml.ditest.Emp">
        <property name="ename" value="tha1"></property>
        <property name="age" value="33"></property>
    </bean>
    <bean id="emp2" class="com.thaistudyspring.iocxml.ditest.Emp">
        <property name="ename" value="tha2"></property>
        <property name="age" value="28"></property>
    </bean>
    <bean id="dept" class="com.thaistudyspring.iocxml.ditest.Dept">
        <property name="dname" value="技术部"></property>
        <property name="empList">
            <list>
                <ref bean="emp1"></ref>
                <ref bean="emp2"></ref>
            </list>
        </property>

    </bean>

map集合

image-20240715153939976

如果多个元素

image-20240715154100281

数组bean类型

原本命名空间没有util,需要手动加入

image-20240715180823127

package com.thaistudyspring.iocxml.dimap;

public class Teacher {
    private String teacherId;
    private String teacherName;

    public String getTeacherId() {
        return teacherId;
    }

    public void setTeacherId(String teacherId) {
        this.teacherId = teacherId;
    }

    public String getTeacherName() {
        return teacherName;
    }

    @Override
    public String toString() {
        return "Teacher{" +
                "teacherId='" + teacherId + '\'' +
                ", teacherName='" + teacherName + '\'' +
                '}';
    }

    public void setTeacherName(String teacherName) {
        this.teacherName = teacherName;
    }
}
package com.thaistudyspring.iocxml.dimap;

import java.util.List;
import java.util.Map;

public class Student {

    private List<Lesson> lessonList;
    private Map<String,Teacher> teacherMap;

    private String sid;

    public List<Lesson> getLessonList() {
        return lessonList;
    }

    @Override
    public String toString() {
        return "Student{" +
                "lessonList=" + lessonList +
                ", teacherMap=" + teacherMap +
                ", sid='" + sid + '\'' +
                ", sname='" + sname + '\'' +
                '}';
    }

    public void setLessonList(List<Lesson> lessonList) {
        this.lessonList = lessonList;
    }

    public Map<String, Teacher> getTeacherMap() {
        return teacherMap;
    }

    public void setTeacherMap(Map<String, Teacher> teacherMap) {
        this.teacherMap = teacherMap;
    }

    public String getSid() {
        return sid;
    }

    public void setSid(String sid) {
        this.sid = sid;
    }

    public String getSname() {
        return sname;
    }

    public void setSname(String sname) {
        this.sname = sname;
    }

    private String sname;

    public void run(){
        System.out.println("学生编号: " + sid + " 学生名称:" + sname);
        System.out.println(teacherMap);
        System.out.println(lessonList);
    }

}
package com.thaistudyspring.iocxml.dimap;

public class Lesson {
    private String lessonName;

    public String getLessonName() {
        return lessonName;
    }

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

    public void setLessonName(String lessonName) {
        this.lessonName = lessonName;
    }
}

重头戏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: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/util/spring-util.xsd">

<!--    1.创建3个对象-->
<!--    2.-->

    <bean id="teacherone" class="com.thaistudyspring.iocxml.dimap.Teacher">
        <property name="teacherId" value="2333"></property>
        <property name="teacherName" value="Qka"></property>
    </bean>
    <bean id="teachertwo" class="com.thaistudyspring.iocxml.dimap.Teacher">
        <property name="teacherId" value="6667"></property>
        <property name="teacherName" value="mikujacko"></property>
    </bean>

    <bean id="student" class="com.thaistudyspring.iocxml.dimap.Student">
        <property name="sid" value="666"></property>
        <property name="sname" value="tha1"></property>

        <property name="lessonList" ref="lessonList"></property>
        <property name="teacherMap" ref="teacherMap"></property>

    </bean>

    <util:list id="lessonList">
        <ref bean="lessonone"></ref>
        <ref bean="lessontwo"></ref>
    </util:list>

    <util:map id="teacherMap">
        <entry>
            <key>
                <value>10010</value>
            </key>
            <ref bean="teacherone"></ref>
        </entry>
        <entry>
            <key>
                <value>10012</value>
            </key>
            <ref bean="teachertwo"></ref>
        </entry>
    </util:map>

    <bean id="lessonone" class="com.thaistudyspring.iocxml.dimap.Lesson">
        <property name="lessonName" value="java开发"></property>
    </bean>
    <bean id="lessontwo" class="com.thaistudyspring.iocxml.dimap.Lesson">
        <property name="lessonName" value="前端开发"></property>
    </bean>

</beans>

测试成功

image-20240715181608639

命名空间

为了区别同名的变量,我们会在前面加上命名空间

demo

image-20240803135600732

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

在xml前面声明命名空间

<!--    p命名空间注入-->
    <bean id="studentp" class="com.thaistudyspring.iocxml.dimap.Student" p:sid="100" p:sname="mary"
          p:lessonList-ref="lessonList" p:teacherMap-ref="teacherMap"></bean>

特点就是p:xxxxx这种格式,这是有命名空间的Bean的初始化格式

测试

        ApplicationContext context = new ClassPathXmlApplicationContext("bean-diref.xml");
        Student student = context.getBean("studentp", Student.class);
        student.run();

image-20240803141052727

测试成功

引入外部文件

比如数据库账号密码地址,可写在文件里,从而减少xml的冗余,此外,如果需要修改时,显然修改配置文件会比在xml里面修改要方便明了

  1. 引入依赖
<!--        mysql驱动-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.13</version>
        </dependency>
<!--        数据源-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.0.31</version>
        </dependency>
  1. 静态文件

一搬都是properties为后缀,放在resources目录

jdbc.properties

jdbc.user=root
jdbc.password=atguigu
jdbc.url=jdbc:mysql://localhost:3306/spring?serverTimezone=UTC
jdbc.driver=com.mysql.cj.jdbc.Driver
  1. 加载

bean-jdbc.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:property-placeholder location="classpath:jdbc.properties"></context:property-placeholder>

<!--    完成数据库信息注入-->
    <bean id="druidDataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="url" value="${jdbc.url}"></property>
        <property name="username" value="${jdbc.user}"></property>
        <property name="password" value="${jdbc.password}"></property>
        <property name="driverClassName" value="${jdbc.driver}"></property>
    </bean>

</beans>

一方面我们依旧需要在头部进行声明xmlns:context="http://www.springframework.org/schema/context",http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd

然后引入外部依赖(需要借助德鲁伊druid提供的类)

<?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:property-placeholder location="classpath:jdbc.properties"></context:property-placeholder>

<!--    完成数据库信息注入-->
    <bean id="druidDataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="url" value="${jdbc.url}"></property>
        <property name="username" value="${jdbc.user}"></property>
        <property name="password" value="${jdbc.password}"></property>
        <property name="driverClassName" value="${jdbc.driver}"></property>
    </bean>

</beans>

使用${xxxxx}语法进行传参

测试

    @Test
    public void demo1(){
        DruidDataSource druidDataSource = new DruidDataSource();
        druidDataSource.setUrl("jdbc:mysql://localhost:3306/spring?serverTimezone=UTC");
        druidDataSource.setUsername("root");
        druidDataSource.setPassword("root");
        System.out.println(druidDataSource.getUrl());

    }

    @Test
    public void demo2(){
        ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("bean-jdbc.xml");
        DruidDataSource datasource = classPathXmlApplicationContext.getBean(DruidDataSource.class);
        System.out.println(datasource.getUrl());
    }

image-20240803152034990

image-20240803152047627

都正常输出,

demo2是我们引入外部文件的例子

作用域(单实例和多实例)

image-20240803154830083

默认是单实例!

bean-scope.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">
<!--    通过scope属性配置单实例 多实例-->
    <bean id="orders" class="com.thaistudyspring.iocxml.scope.Orders"
          scope="singleton"></bean>
</beans>

Orders

package com.thaistudyspring.iocxml.scope;

public class Orders {
}

测试

package com.thaistudyspring.iocxml.scope;

import com.thaistudyspring.iocxml.dimap.Student;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Test {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("bean-scope.xml");
        Orders orders = context.getBean("orders", Orders.class);
        System.out.println(orders);

        Orders orders1 = context.getBean("orders", Orders.class);
        System.out.println(orders1);
    }
}

输出了同一个地址对象

image-20240803160340920

这就是单实例

多实例如下,修改一下scope

    <bean id="orders" class="com.thaistudyspring.iocxml.scope.Orders"
          scope="prototype"></bean>

对象地址不一样了

image-20240803160710827

bean的生命周期

image-20240803162104320

起一个新的包

User.class

package com.thaistudyspring.iocxml.lifecycle;

public class User {
    private String name;

    public User(){
        System.out.println("1 bean调用无参构造");
    }

    public void initMethod(){
        System.out.println("4 bean对象初始化,调用指定的初始化方法");
    }

    public void destroyMethod(){
        System.out.println("7 bean对象销毁,调用指定的销毁方法");
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        System.out.println("2 给bean对象设置属性值");
        this.name = name;
    }

}

bean-life.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: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 https://www.springframework.org/schema/util/spring-util.xsd">
    <bean id="user" class="com.thaistudyspring.iocxml.lifecycle.User" scope="singleton"
      init-method="initMethod" destroy-method="destroyMethod">
        <property name="name" value="lucy"></property>
    </bean>
</beans>

测试

public class Test {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("bean-life.xml");
        User user = context.getBean("user", User.class);
        System.out.println("6 bean对象创建完成了,可以使用了");
        System.out.println(user);
        context.close();

    }
}

image-20240803165021644

后置处理器

新建一个类MyBeanPost,需要继承BeanPostProcessor并实现postProcessBeforeInitialization和postProcessAfterInitialization(字面意思)

package com.thaistudyspring.iocxml.lifecycle;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;

public class MyBeanPost implements BeanPostProcessor {

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("3 bean后置处理器,初始化之前执行");
        System.out.println(beanName + "::" + bean);
        return bean;
    }
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("5 bean后置处理器,初始化之后执行");
        System.out.println(beanName + "::" + bean);
        return bean;
    }

}

new它就需要写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: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 https://www.springframework.org/schema/util/spring-util.xsd">
    <bean id="user" class="com.thaistudyspring.iocxml.lifecycle.User" scope="singleton"
      init-method="initMethod" destroy-method="destroyMethod">
        <property name="name" value="lucy"></property>
    </bean>

    <bean id="myBeanPost" class="com.thaistudyspring.iocxml.lifecycle.MyBeanPost">

    </bean>

</beans>

测试

public class Test {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("bean-life.xml");
        User user = context.getBean("user", User.class);
        System.out.println("6 bean对象创建完成了,可以使用了");
        System.out.println(user);
        context.close();

    }
}

image-20240803170141771

FactoryBean

当xml的class="xxxx"指向继承factorybean的工厂类时,返回的是getObject的方法定义的类

常用于整合第三方框架

bean-factory.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="user" class="com.thaistudyspring.iocxml.factorybean.MyFactoryBean"></bean>
</beans>
package com.thaistudyspring.iocxml.factorybean;

import org.springframework.beans.factory.FactoryBean;

public class MyFactoryBean implements FactoryBean<User> {
    @Override
    public User getObject()  throws Exception{
        return new User();
    }

    @Override
    public Class<?> getObjectType(){
        return User.class;
    }

}
package com.thaistudyspring.iocxml.factorybean;

public class User {
}
package com.thaistudyspring.iocxml.factorybean;

import org.springframework.context.support.ClassPathXmlApplicationContext;

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

image-20240804150548769

虽然xml的class=MyFactoryBean,但输出的不是MyFactoryBean,而是getObject决定的User

image-20240804150942268

自动装配

自动装配的特点是一句autowire就可以把相应的类自己new起来,不用在property里面写

先这么建类和接口

image-20240804153319693

package com.thaistudyspring.iocxml.auto.dao;

public interface UserDao {
    public void addUserDao();
}
package com.thaistudyspring.iocxml.auto.dao;

public class UserDaoImpl implements UserDao{
    @Override
    public void addUserDao(){
        System.out.println("userDao方法执行了");
    }
}
package com.thaistudyspring.iocxml.auto.service;

public interface UserService {
    public void addUserService();
}
package com.thaistudyspring.iocxml.auto.service;

import com.thaistudyspring.iocxml.auto.dao.UserDaoImpl;

public class UserServiceImpl implements UserService{
    private UserDaoImpl userDao;

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

    @Override
    public void addUserService(){
        System.out.println("userService方法执行了...");
//        UserDaoImpl userDao = new UserDaoImpl();
//        userDao.addUserDao();

        userDao.addUserDao();
    }
}
package com.thaistudyspring.iocxml.auto.controller;

import com.thaistudyspring.iocxml.auto.service.UserService;
import com.thaistudyspring.iocxml.auto.service.UserServiceImpl;

public class UserController {

    private UserService userService;

    public void setUserService(UserService userService) {
        this.userService = userService;
    }

    public void addUser(){
        System.out.println("controller方法执行了...");
        // 传统方法
//        UserServiceImpl userService = new UserServiceImpl();
//        userService.addUserService();
        // 调用service的方法
        userService.addUserService();

    }
}

然后在外面new 一个test

package com.thaistudyspring.iocxml.auto;

import com.thaistudyspring.iocxml.auto.controller.UserController;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestUser {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("bean-auto.xml");
        UserController usercontroller = context.getBean("usercontroller", UserController.class);
        usercontroller.addUser();
    }
}

image-20240804164711698

Ioc-注解

注解是代码中的一种特殊标记

格式 @注解名称(属性1=属性值...)

类上面,属性上面,方法上面

环境搭建:开启组件扫描

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

<!--    开启组件扫描-->
    <context:component-scan base-package="com.thaistudyspring"></context:component-scan>
</beans>
package com.thaistudyspring.spring6.bean;

import org.springframework.stereotype.Component;

@Component(value="user") //<bean id="user" class="xxx">

public class User {
}

image-20240804182902929

这几个注解在实际使用上没有区别,但是我们应尽可能遵守惯例

value="user"不写的话,默认id就是类首字母小写

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

image-20240804183010525

测试成功,可以看到我们不需要依赖xml了,而实际上企业中也大部分是用注解的方法进行

属性注入

先这么建

image-20240804202633962

步骤:

1 bean对象创建

2 定义相关属性,在属性上添加注解

一般来说,都是controller->service->dao,所以我们建类的时候,会按照这个顺序,把类写在属性里(有点像pop链,也叫做调用链)

测试如下

package com.thaistudyspring.spring6.autorwired.controller;

import com.thaistudyspring.spring6.autorwired.service.UserService;
import com.thaistudyspring.spring6.autorwired.service.UserServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;

@Controller
public class UserController {

    //注入service
    @Autowired //根据类型找到对应对象,完成注入
    private UserServiceImpl userServiceimpl;

    public void add(){
        System.out.println("controller......");
        userServiceimpl.add();
    }

}
package com.thaistudyspring.spring6.autorwired.dao;

public interface UserDao {
    public void add();
}
package com.thaistudyspring.spring6.autorwired.dao;

import org.springframework.stereotype.Repository;

@Repository
public class UserDaoImpl implements UserDao{
    @Override
    public void add() {
        System.out.println("Dao.........");
    }
}
package com.thaistudyspring.spring6.autorwired.service;

public interface UserService {
    public void add();
}
package com.thaistudyspring.spring6.autorwired.service;

import com.thaistudyspring.spring6.autorwired.dao.UserDaoImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class UserServiceImpl implements UserService{

    @Autowired
    private UserDaoImpl userDaoimpl;

    @Override
    public void add(){
        System.out.println("service.......");
        userDaoimpl.add();
    }
}
package com.thaistudyspring.spring6.autorwired;

import com.thaistudyspring.spring6.autorwired.controller.UserController;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestUserController {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
        UserController bean = context.getBean(UserController.class);
        bean.add();
    }
}

运行成功

image-20240804223228353

set方法注入

    //注入service
//    @Autowired //根据类型找到对应对象,完成注入
//    private UserServiceImpl userServiceimpl;

    // 第二种方法 set方法注入
    private UserServiceImpl userServiceimpl;
    @Autowired
    public void setUserServiceimpl(UserServiceImpl userServiceimpl) {
        this.userServiceimpl = userServiceimpl;
    }

具体不演示了,idea傻逼了

image-20240805160125930

构造方法注入

//    // 第二种方法 set方法注入
//    private UserServiceImpl userServiceimpl;
//    @Autowired
//    public void setUserServiceimpl(UserServiceImpl userServiceimpl) {
//        this.userServiceimpl = userServiceimpl;
//    }

    // 第三章方式:构造方法注入
    private UserServiceImpl userServiceimpl;
    @Autowired
    public UserController(UserServiceImpl userServiceimpl) {
        this.userServiceimpl = userServiceimpl;
    }

形参上进行注入

    // 第三章方式:构造方法注入
//    private UserServiceImpl userServiceimpl;
//    @Autowired
//    public UserController(UserServiceImpl userServiceimpl) {
//        this.userServiceimpl = userServiceimpl;
//    }

    //第四章方式:形参注入
    private UserServiceImpl userServiceimpl;

    public UserController(@Autowired UserServiceImpl userServiceimpl) {
        this.userServiceimpl = userServiceimpl;
    }

只有一个有参构造

只有一个有参构造函数,@Autowired可以省略

注解联合

比如 AdminServerImpl和UserServiceImpl都继承UserService

image-20240805164434498

如果这样写的话,不知道加载哪个

    @Autowired
    private UserService userServiceimpl;

用一个新的注解Qualifier,可以通过名称获取

    //两个注解,根据名称注入
    @Autowired
    @Qualifier(value="adminServerImpl")
    private UserService userServiceimpl;

Resource

Resource是jdk拓展包的,Autorwired是spring自带的,也就说Resource普适性更强

Resource 会先根据名称进行注入,如果没有再根据 属性类型 进行注入

Resource只能在属性上、setter方法上注入

jdk11以上需要引入这个依赖,jdk11以下不用

        <dependency>
            <groupId>jakarta.annotation</groupId>
            <artifactId>jakarta.annotation-api</artifactId>
            <version>2.1.1</version>
        </dependency>

根据名称进行注入的例子如下

// 根据名称进行注入
@Resource(name = "myUserService")
private UserService userService;
@Service("myUserService")
public class UserServiceImpl implements UserService {

如果不指定名称,则默认找变量名名称进行注入

    @Resource
    private UserDao userMyDao;
@Repository("userMyDao")
public class UserDaoImpl implements UserDao {

变量名名称也找不到的话,则根据属性名称首字母小写(byType)

image-20240805174004593

目录结构一样的

image-20240805174028946

演示demo

package com.thaistudyspring.spring6.resource.controller;

import com.thaistudyspring.spring6.resource.service.UserService;
import com.thaistudyspring.spring6.resource.service.UserServiceImpl;
import jakarta.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Controller;

@Controller("myUsercontroller")
public class UserController {

    // 根据名称进行注入
    @Resource(name = "myUserService")
    private UserService userService;

    public void add(){
        System.out.println("controller......");
        userService.add();
    }

}
package com.thaistudyspring.spring6.resource.dao;

public interface UserDao {
    public void add();
}
package com.thaistudyspring.spring6.resource.dao;

import org.springframework.stereotype.Repository;

@Repository("userMyDao")
public class UserDaoImpl implements UserDao {
    @Override
    public void add() {
        System.out.println("Dao.........");
    }
}
package com.thaistudyspring.spring6.resource.service;

public class AdminServerImpl implements UserService {

    @Override
    public void add() {
        System.out.println("AdminServerImpl........");
    }
}
package com.thaistudyspring.spring6.resource.service;

public interface UserService {
    public void add();
}
package com.thaistudyspring.spring6.resource.service;

import com.thaistudyspring.spring6.resource.dao.UserDao;
import com.thaistudyspring.spring6.resource.dao.UserDaoImpl;
import jakarta.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service("myUserService")
public class UserServiceImpl implements UserService {

    @Resource
    private UserDao userMyDao;

    @Override
    public void add(){
        System.out.println("service.......");
        userMyDao.add();
    }
}
package com.thaistudyspring.spring6.resource;

import com.thaistudyspring.spring6.resource.controller.UserController;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestController {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
        UserController bean = context.getBean("myUsercontroller",UserController.class);
        bean.add();
    }
}

spring全注解

全注解,不用xml的做法

image-20240805180004292

就是加config包

写一个配置类

package com.thaistudyspring.spring6.config;

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

@Configuration  //配置类
@ComponentScan("com.thaistudyspring.spring6") // 开启组件扫描,代替xml
public class SpringConfig {
}

TestController

package com.thaistudyspring.spring6.resource;

import com.thaistudyspring.spring6.config.SpringConfig;
import com.thaistudyspring.spring6.resource.controller.UserController;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestController {
    public static void main(String[] args) {
        //ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
        ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
        UserController bean = context.getBean("myUsercontroller",UserController.class);
        bean.add();
    }
}

image-20240805180237386

手写IOC

回顾java反射

image-20240806105108328

package com.thaistudyspring.reflect;

public class Car {
    private String name;
    private int age;
    private String color;

    public Car() {

    }

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

    private void run(){
        System.out.println("私有方法-run...");
    }

    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;
    }

    public String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }
}

Testclass自己测,知识写注释里了

    //1、获取class对象多种方式
    @Test
    public void test01() throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, ClassNotFoundException {
        //1 类名.class
        Class clazz1 = Car.class;

        //2 对象.getClass()
        Class clazz2 = new Car().getClass();

        //3 Class.forname(“全路径”)
        Class clazz3 = Class.forName("com.thaistudyspring.reflect.Car");

        //实例化
        Car car = (Car)clazz3.getDeclaredConstructor().newInstance();
        System.out.println(car);

    }
    //2、获取构造方法
    @Test
    public void test02(){
    Class clazz = Car.class;
        Constructor[] constructors = clazz.getConstructors();
        for(Constructor c:constructors){
            System.out.println("方法名称:" + c.getName() + " 参数个数:" + c.getParameterCount());
        }

    }

image-20240806105844795

但是如果改为private

image-20240806111041312

改为

    private Car(String name, int age, String color) {
        this.name = name;
        this.age = age;
        this.color = color;
    }

我们演示一下如何拿到private方法

    @Test
    public void test02() throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        Class clazz = Car.class;
        // clazz.getConstructors(); 获取public构造方法
        //Constructor[] constructors = clazz.getConstructors();
        // clazz.getDeclaredConstructors() 获取所有构造方法 含public、private
        Constructor[] constructors = clazz.getDeclaredConstructors();
        for(Constructor c:constructors){
            System.out.println("方法名称:" + c.getName() + " 参数个数:" + c.getParameterCount());
        }

        //指定有参数构造方法
        //1 构造public
//        Constructor constructor = clazz.getConstructor(String.class, int.class, String.class);
//        Car car = (Car)constructor.newInstance("Benz", 10, "红色");
//        System.out.println(car);

        //2 构造private
        Constructor declaredConstructor = clazz.getDeclaredConstructor(String.class, int.class, String.class);
        declaredConstructor.setAccessible(true);
        Car car = (Car)declaredConstructor.newInstance("捷达", 15, "白色");
        System.out.println(car);
    }

image-20240806111312829

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇