Spring的使用2.0

前面的博客中已经介绍了Spring的创建和使用第一版,第一版现在已经不怎么在使用了。下面将介绍目前Spring的常见用法。

Spring中想要更简单的存储和读取对象的核心方法是使用注解。 

Spring的创建和使用 

1.先创建出Spring项目出来

2.存储Bean对象

3.获取Bean对象 

创建Spring项目 

和1.0一样创建出一个Spring项目出来并在pom.xml文件中添加核心jar包,以及创建一个启动类:

存储Bean对象

在resources目录下面配置Spring.xml文件,Spring.xml文件中需要配置Spring组件的扫描路径:

<?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:content="http://www.springframework.org/schema/context"
        xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd">
        //下面是配置文件的扫描路径,根据自己的文件所在的位置来处理这个路径
        <content:component-scan base-package="com.user"></content:component-scan>
</beans>

上面是配置文件的扫描路径,根据自己的文件所在的位置来处理这个路径,像我在com.user.Controller目录下面创建了一个控制层文件UserController,那么我的扫描路径就可以写成com.user,这样设置以后Spring在扫描文件的时候,他就会去该目录下面查看。这里的写法不是唯一的,你也可以将路径写大一点,比如直接com也可以,但是不推荐。

给存储Bean对象添加注解 

想要将对象存储在Spring中,就得给对象添加注解,二注解又分两种:类注解、方法注解 

类注解

顾名思义就是在类的前面加上注解,像下面这样:

@Controller
public class UserController {
    public void Hi(String name){
        System.out.println("Hi:"+name);
    }
}

类注解包括:@Controller(控制器存储)、@Service(服务存储)、@Repository(仓库存储)、@Component(组件存储)、@Configuration(配置存储)

首先我们的明白,我们再写一个Spring项目的时候,因为涉及到前后端的交互还有和数据库的交互。各个目录之间的层级关系一定要明确,关于层级关系,它相当于是编程规范,实行这种规范可以方便开发和维护代码,具体的东西还请自己去了解。 

Controller处在控制层,主要负责前端数据的校验 ;

Service处在服务层,主要负责数据的处理还有组装;

Repository处在存储层,主要负责数据库中表的操作,以及将数据存储在数据库中;

Configuration处在配置层,主要负责管理系统的配置信息;

Component处在组件层,主要负责存放编写Spring项目所需要的公共组件。

它们之间的关系如下图:

其中 

@Controller(控制器存储)、@Service(服务存储)、@Repository(仓库存储)、@Configuration(配置存储)都是@Component(组件存储)的子类

方法注解

在方法的上面加上注解,方法注解必须配合类注解才能一起使用(因为Spring在扫描的时候是以类为单位来扫描的,如果类上面不加上注解,就扫描不到) :

@Controller
public class UserController {
    @Bean
    public User GoodBey(){
        User user = new User();
        user.setId(1);
        user.setName("韩梅梅");
        return user;
    }
}
public class User {
    private int Id;
    private String name;

    public void setId(int id) {
        Id = id;
    }

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

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

现在先来看一下它们的使用:

现在来详细讨论一下这两类注解:

方法注解目前包括:@Bean

在使用方法注解的时候要注意:方法注解必须配合类注解才能使用。

在我们写方法注解的时候,有时方法名可能很长,这时可以给Bean对象进行重命名操作,但是重命名以后就不能再使用方法名:

    @Bean(name = "GB")
    public User GoodBey(){
        User user = new User();
        user.setId(1);
        user.setName("韩梅梅");
        return user;
    }

关于Bean的命名 

通常在使用注解的时候,要求在写类名的时候要采用大驼峰,而读取类名的时候要求类名的首字母要小写。如果类名中首个字母和第二个字母都是大写,那么在读取类名的时候就按照类名来读就可以了,这个时候不能在采用类名首字母小写,否者会报错:

我们查看Spring里面的原码就知道原因了:

在IDEA中按查找类的快捷键ctrl+N,找到AnnotationBeanNameGenerator这个类:

然后查看这个方法:

从上面就可以解释为什么会报错了 

获取Bean对象(对象注入) 

获取Bean对象也叫对象注入,是把对象取出放到某个类中。

对象注入的实现有以下3种方式:

1.属性注入

2.Setter注入

3.构造方法注入 

属性注入  

属性注入就是在属性上面添加@Autowired注解。将UserService类注入到UserController类中,像下面这样:

@Service
public class UserService {
    /*
    * 根据ID获取用户数据
    */
    public User findUserById(Integer id){
        User user = new User();
        if(id==1){
            user.setId(1);
            user.setName("张三");
        }else{
            user.setId(2);
            user.setName("李四");
        }
        return user;
    }

    public void Hi(String name){
        System.out.println("Hi:"+name);
    }
}
@Controller
public class UserController {
    //1.属性注入,从Spring中获取一个对象,并注入到当前类
    @Autowired
    private UserService userService;

    public User findSuerById(Integer id){
        return userService.findUserById(id);
    }


    public void Hi(String name){
        System.out.println("Hi:"+name);
    }
}
public class App {
    public static void main(String[] args) {
        //1.获取到Spring的上下文
        ApplicationContext context = new ClassPathXmlApplicationContext("Spring.xml");
        //2.加载类注解Bean对象
        UserController userController = context.getBean("userController", UserController.class);
        //3.使用它里面的方法
        System.out.println(userController.findSuerById(1));
    }
}

特殊类型属性注入  
对象类型属性注入

创建两个类:部门类和员工类

package com.atguigu.spring6.iocxml.ditest;

import java.util.List;

//部门类
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.atguigu.spring6.iocxml.ditest;

import java.util.Arrays;

//员工类
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+"emp work....."+age);
        dept.info();
    }

}

通过外部Bean注入  
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!--
    第一种方式:引入外部bean
        1 创建两个类对象:dept 和 emp
        2 在emp的bean标签里面,使用property引入dept的bean
    -->
    <bean id="dept" class="com.atguigu.spring6.iocxml.ditest.Dept">
        <property name="dname" value="安保部"></property>
    </bean>
    <bean id="emp" class="com.atguigu.spring6.iocxml.ditest.Emp">
        <!--注入对象类型属性
            private Dept dept;
        -->
        <property name="dept" ref="dept"></property>
        <!--普通属性注入-->
        <property name="ename" value="lucy"></property>
        <property name="age" value="50"></property>
    </bean>
</beans>

package com.atguigu.spring6.iocxml.ditest;

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

public class TestDept {

    public static void main(String[] args) {
        ApplicationContext context =
                new ClassPathXmlApplicationContext("bean-dilist.xml");
        //员工对象
        Dept dept = context.getBean("emp", Dept.class);
        dept.info();
    }
}

内部bean注入 
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <!--第二种方式 内部bean注入-->
    <bean id="emp2" class="com.atguigu.spring6.iocxml.ditest.Emp">
        <!--普通属性注入-->
        <property name="ename" value="mary"></property>
        <property name="age" value="20"></property>
        <!--内部bean-->
        <property name="dept">
            <bean id="dept2" class="com.atguigu.spring6.iocxml.ditest.Dept">
                <property name="dname" value="财务部"></property>
            </bean>
        </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="dept3" class="com.atguigu.spring6.iocxml.ditest.Dept">
        <property name="dname" value="技术研发部"></property>
    </bean>

    <bean id="emp3" class="com.atguigu.spring6.iocxml.ditest.Emp">
        <property name="ename" value="tom"></property>
        <property name="age" value="30"></property>
        <property name="dept" ref="dept3"></property>
        <property name="dept.dname" value="测试部"></property>
    </bean>
</beans>

数组类型注入 
package com.atguigu.spring6.iocxml.ditest;

import java.util.Arrays;

//员工类
public class Emp {

    //对象类型属性:员工属于某个部门
    private Dept dept;
    //员工名称
    private String ename;
    //员工年龄
    private Integer age;

    //爱好
    private String[] loves;

    public void work() {
        System.out.println(ename+"emp work....."+age);
        dept.info();
        System.out.println(Arrays.toString(loves));
    }

    public String[] getLoves() {
        return loves;
    }
    public void setLoves(String[] loves) {
        this.loves = loves;
    }
    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;
    }
}
<?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="dept" class="com.atguigu.spring6.iocxml.ditest.Dept">
        <property name="dname" value="技术部"></property>
    </bean>
    <bean id="emp" class="com.atguigu.spring6.iocxml.ditest.Emp">
        <!--普通属性-->
        <property name="ename" value="lucy"></property>
        <property name="age" value="20"></property>
        <!--对象类型属性-->
        <property name="dept" ref="dept"></property>
        <!--数组类型属性-->
        <property name="loves">
            <array>
                <value>吃饭</value>
                <value>睡觉</value>
                <value>敲代码</value>
            </array>
        </property>
    </bean>
</beans>
package com.atguigu.spring6.iocxml.ditest;

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

public class TestEmp {

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

List集合类型属性注入
package com.atguigu.spring6.iocxml.ditest;

import java.util.List;

//部门类
public class Dept {

    //一个部门有很多员工
    private List<Emp> empList;

    private String dname;

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

    public List<Emp> getEmpList() {
        return empList;
    }

    public void setEmpList(List<Emp> empList) {
        this.empList = empList;
    }

    public void info() {
        System.out.println("部门名称:"+dname);
        for (Emp emp:empList) {
            System.out.println(emp.getEname());
        }
    }
}
<?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="empone" class="com.atguigu.spring6.iocxml.ditest.Emp">
        <property name="ename" value="lucy"></property>
        <property name="age" value="20"></property>
    </bean>
    <bean id="emptwo" class="com.atguigu.spring6.iocxml.ditest.Emp">
        <property name="ename" value="mary"></property>
        <property name="age" value="30"></property>
    </bean>

    <bean id="dept" class="com.atguigu.spring6.iocxml.ditest.Dept">
      <property name="dname" value="技术部"></property>
      <property name="empList">
            <list>
                <ref bean="empone"></ref>
                <ref bean="emptwo"></ref>
            </list>
      </property>
    </bean>
</beans>
package com.atguigu.spring6.iocxml.ditest;

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

public class TestEmp {

    public static void main(String[] args) {
        ApplicationContext context =
                new ClassPathXmlApplicationContext("bean-diarray.xml");
        //员工对象
        Emp emp = context.getBean("emp", Emp.class);
        emp.work();
    }
}
Map集合类型属性注入 
package com.atguigu.spring6.iocxml.dimap;

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

public class Student {

    private Map<String,Teacher> teacherMap;

    private String sid;
    private String sname;

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

    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;
    }
}
package com.atguigu.spring6.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;
    }

    public void setTeacherName(String teacherName) {
        this.teacherName = teacherName;
    }

    @Override
    public String toString() {
        return "Teacher{" +
                "teacherId='" + teacherId + '\'' +
                ", teacherName='" + teacherName + '\'' +
                '}';
    }
}
<?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">

    <!--
        1 创建两个对象
        2 注入普通类型属性
        3 在学生bean注入map集合类型属性
    -->
    <bean id="teacherone" class="com.atguigu.spring6.iocxml.dimap.Teacher">
        <!--注入普通类型属性-->
        <property name="teacherId" value="100"></property>
        <property name="teacherName" value="西门讲师"></property>
    </bean>
    <bean id="teachertwo" class="com.atguigu.spring6.iocxml.dimap.Teacher">
        <!--注入普通类型属性-->
        <property name="teacherId" value="200"></property>
        <property name="teacherName" value="上官讲师"></property>
    </bean>

    <bean id="student" class="com.atguigu.spring6.iocxml.dimap.Student">
        <!--注入普通类型属性-->
        <property name="sid" value="2000"></property>
        <property name="sname" value="张三"></property>
        <!--在学生bean注入map集合类型属性-->
        <property name="teacherMap">
            <map>
                <entry>
                    <key>
                        <value>10010</value>
                    </key>
                    <ref bean="teacherone"></ref>
                </entry>
                <entry>
                    <key>
                        <value>10086</value>
                    </key>
                    <ref bean="teachertwo"></ref>
                </entry>
            </map>
        </property>
    </bean>
</beans>
package com.atguigu.spring6.iocxml.dimap;

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

public class TestStu {

    @Test
    public void testStu() {
        ApplicationContext context =
                new ClassPathXmlApplicationContext("bean-dimap.xml");
        Student student = context.getBean("student", Student.class);
        student.run();
    }
}

引用集合类型Bean注入 
package com.atguigu.spring6.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;
    private String sname;

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

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

    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;
    }
}
package com.atguigu.spring6.iocxml.dimap;

public class Lesson {

    private String lessonName;

    public String getLessonName() {
        return lessonName;
    }

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

    @Override
    public String toString() {
        return "Lesson{" +
                "lessonName='" + lessonName + '\'' +
                '}';
    }
}
<?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/util
       http://www.springframework.org/schema/util/spring-util.xsd
       http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd">


    <!--
        1 创建三个对象
        2 注入普通类型属性
        3 使用util:类型 定义
        4 在学生bean引入util:类型定义bean,完成list、map类型属性注入
    -->
    <bean id="student" class="com.atguigu.spring6.iocxml.dimap.Student">
        <property name="sid" value="10000"></property>
        <property name="sname" value="lucy"></property>
        <!--注入list、map类型属性-->
        <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>10086</value>
            </key>
            <ref bean="teachertwo"></ref>
        </entry>
    </util:map>

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

    <bean id="teacherone" class="com.atguigu.spring6.iocxml.dimap.Teacher">
        <property name="teacherId" value="100"></property>
        <property name="teacherName" value="西门讲师"></property>
    </bean>
    <bean id="teachertwo" class="com.atguigu.spring6.iocxml.dimap.Teacher">
        <property name="teacherId" value="200"></property>
        <property name="teacherName" value="欧阳讲师"></property>
    </bean>

</beans>
package com.atguigu.spring6.iocxml.dimap;

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

public class TestStu {

    @Test
    public void testStu() {
        ApplicationContext context =
                new ClassPathXmlApplicationContext("bean-diref.xml");
        Student student = context.getBean("student", Student.class);
        student.run();
    }
}
P命令空间注入 
<?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"
       xmlns:p="http://www.springframework.org/schema/p"
       xsi:schemaLocation="http://www.springframework.org/schema/util
       http://www.springframework.org/schema/util/spring-util.xsd
       http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd">

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

    <!--
        1 创建三个对象
        2 注入普通类型属性
        3 使用util:类型 定义
        4 在学生bean引入util:类型定义bean,完成list、map类型属性注入
    -->
    <bean id="student" class="com.atguigu.spring6.iocxml.dimap.Student">
        <property name="sid" value="10000"></property>
        <property name="sname" value="lucy"></property>
        <!--注入list、map类型属性-->
        <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>10086</value>
            </key>
            <ref bean="teachertwo"></ref>
        </entry>
    </util:map>

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

    <bean id="teacherone" class="com.atguigu.spring6.iocxml.dimap.Teacher">
        <property name="teacherId" value="100"></property>
        <property name="teacherName" value="西门讲师"></property>
    </bean>
    <bean id="teachertwo" class="com.atguigu.spring6.iocxml.dimap.Teacher">
        <property name="teacherId" value="200"></property>
        <property name="teacherName" value="欧阳讲师"></property>
    </bean>

</beans>
package com.atguigu.spring6.iocxml.dimap;

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

public class TestStu {

    @Test
    public void testStu() {
        ApplicationContext context =
                new ClassPathXmlApplicationContext("bean-diref.xml");
        Student student = context.getBean("studentp", Student.class);
        student.run();
    }
}

注入外部文件  

1.引入数据库相关依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>spring6</artifactId>
        <groupId>com.atguigu</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>spring6-ioc-xml</artifactId>

    <properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
    </properties>

    <dependencies>
        <!-- MySQL驱动 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.30</version>
        </dependency>
        <!-- 数据源 -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.2.15</version>
        </dependency>
    </dependencies>
</project>

2.创建外部属性文件(properties格式——定义数据信息:用户名、密码、地址等)

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

 3.创建spring配置文件,引入context命令空间(引入属性文件,使用表达式完成注入) 

package com.atguigu.spring6.iocxml.jdbc;

import com.alibaba.druid.pool.DruidDataSource;
import org.junit.jupiter.api.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestJdbc {

    @Test
    public void demo() {
        ApplicationContext context =
                new ClassPathXmlApplicationContext("bean-jdbc.xml");
        DruidDataSource dataSource = context.getBean(DruidDataSource.class);
        System.out.println(dataSource.getUrl());
    }
}

Setter注入 

基于XML方式的Setter注入 
package com.atguigu.spring6.iocxml.di;

public class Book {

    private String bname;
    private String author;

    private String others;

    public Book() {

    }


    //生成set方法
    public String getBname() {
        return bname;
    }

    public String getOthers() {
        return others;
    }

    public void setOthers(String others) {
        this.others = others;
    }

    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 + '\'' +
                ", others='" + others + '\'' +
                '}';
    }
}
<?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">
    <!--1 set方法注入-->
    <bean id="book" class="com.atguigu.spring6.iocxml.di.Book">
        <property name="bname" value="前端开发"></property>
        <property name="author" value="尚硅谷"></property>
        <property name="others">
            <null/>
        </property>
    </bean>
</beans>
package com.atguigu.spring6.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);
    }
}

通过获得setter方法,然后在set方法上面加上@Autowired,将UserService类注入到UserController类中,像下面这样:

@Controller
public class UserController2 {
    private UserService userService;
    //1.Setter注入
    @Autowired
    public void setUserService(UserService userService) {
        this.userService = userService;
    }

    public User findUserById(Integer id){
        return userService.findUserById(id);
    }
}
public class App {
    public static void main(String[] args) {
        //1.获取到Spring的上下文
        ApplicationContext context = new ClassPathXmlApplicationContext("Spring.xml");
        //2.加载类注解Bean对象
        UserController2 controller2 = context.getBean("userController2", UserController2.class);
        //3.使用它里面的方法
        System.out.println(controller2.findUserById(1));
    }
}

利用Setter注入方式的步骤:1.定义属性 、2.生成属性setter方法、3.给setter方法添加@Autowired注解

构造方法注入 

基于XML方式的构造器注入  
package com.atguigu.spring6.iocxml.di;

public class Book {

    private String bname;
    private String author;

    private String others;

    public Book() {
        System.out.println("无参数构造执行了...");
    }

    //有参数构造方法
    public Book(String bname, String author) {
        System.out.println("有参数构造执行了...");
        this.bname = bname;
        this.author = author;
    }

    //生成set方法
    public String getBname() {
        return bname;
    }

    public String getOthers() {
        return others;
    }

    public void setOthers(String others) {
        this.others = others;
    }

    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 + '\'' +
                ", others='" + others + '\'' +
                '}';
    }
}
<?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">
    <!--2 构造器注入-->
    <bean id="bookCon" class="com.atguigu.spring6.iocxml.di.Book">
        <constructor-arg name="bname" value="java开发"></constructor-arg>
        <constructor-arg name="author" value="尚硅谷"></constructor-arg>
    </bean>

</beans>
package com.atguigu.spring6.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 testConstructor() {
        ApplicationContext context =
                new ClassPathXmlApplicationContext("bean-di.xml");
        Book book = context.getBean("bookCon", Book.class);
        System.out.println(book);
    }
}

构造方法注入是在类的构造方法中注入,将UserService类注入到UserController类中,像下面这样:

@Controller
public class UserController3 {
    private UserService userService;

    @Autowired
    public UserController3(UserService userService) {
        this.userService = userService;
    }

    public User findUserById(Integer id){
        return userService.findUserById(id);
    }
}
public class App {
    public static void main(String[] args) {
        //1.获取到Spring的上下文
        ApplicationContext context = new ClassPathXmlApplicationContext("Spring.xml");
        //2.加载类注解Bean对象
        UserController3 userController3 = context.getBean("userController3", UserController3.class);
        //3.使用它里面的方法
        System.out.println(userController3.findUserById(1));
    }
}

注意:在使用构造方法注入的时候,如果类中只存在一个构造方法,那么可以省略这个构造方法上面的注解@Autowired,但是两个和两个以上的构造方法的时候@Autowired不能省略。 

三种注解优缺点:

  • 属性注解的优点是简洁,使用方便;缺点是只能用于IoC容器,如果是非IoC容器用属性注入,则会报空指针异常,还有就是不能注入不可变对象(final修饰的对象);
  • Setter方式注入的优点符合单一设计原则;缺点是不能注入不可变对象(final修饰的对象)而且通用性不如构造方法;
  • 构造方法注入的优点是通用性好,在使用之前一定能保证注入的类不为空,而且可以注入不可变对象;缺点是如果有多个注入会显得比较臃肿; 

@Resource 

我们在使用依赖注入的时候,不光只有@Autowired一种方式,还有另一种方式@Resource

@ Autowired和@Resource的区别

  •  它们两个出身不同,@Autowired来自于Spring,而@Resource来自于JDK的注解;
  •  @Resource注解不能使用在构造方法上,而@Autowired可以;
  • 使用时设置的参数不同,@Resource对于@Autowired来说支持更多的参数设置,比如name,利用这一点可以给类名起别名。
  • @Autowired默认是按照类型进行注入,@Resource默认是按照名称进行注入,如果按名称找不到要注入的属性,则按照类型进行注入

 

@Component
public class UserBean {
    @Bean(name = "GB1")
    public User GoodBey1(){
        User user = new User();
        user.setId(1);
        user.setName("韩梅梅");
        return user;
    }
    @Bean(name = "GB2")
    public User GoodBey2(){
        User user = new User();
        user.setId(2);
        user.setName("李华");
        return user;
    }
}
@Controller
public class UserController4 {
    @Resource(name="GB1")
    private User user;

    public User findClient(){
        return user;
    }
}
public class App {
    public static void main(String[] args) {
        //1.获取到Spring的上下文
        ApplicationContext context = new ClassPathXmlApplicationContext("Spring.xml");
        //2.加载类注解Bean对象
        UserController4 userController4 = context.getBean("userController4", UserController4.class);
        //3.使用它里面的方法
        System.out.println(userController4.findClient());
    }
}

同一个类型多个Bean报错的问题 

之前在1.0版本中,我们讨论过获取Bean的时候,对于多个对象的同一种类型的Bean获取会报错

比如像下面这样:

@Component
public class UserBean {
    @Bean(name = "GB1")
    public User GoodBey1(){
        User user = new User();
        user.setId(1);
        user.setName("韩梅梅");
        return user;
    }
    @Bean(name = "GB2")
    public User GoodBey2(){
        User user = new User();
        user.setId(2);
        user.setName("李华");
        return user;
    }
}
@Controller
public class UserController5 {
    @Autowired
    private User user;

    public User findClient(){
        return user;
    }
}
import com.user.Controller.*;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class App {
    public static void main(String[] args) {
        //1.获取到Spring的上下文
        ApplicationContext context = new ClassPathXmlApplicationContext("Spring.xml");
        //2.加载类注解Bean对象
        UserController5 userController5 = context.getBean("userController5", UserController5.class);
        //3.使用它里面的方法
        System.out.println(userController5.findClient());
    }
}

在分析出现上述错误之前,我们的先明白一个事情,那就是@Autowired和@Resource两个注解获取Bean对象是通过两种方式来获取的:

1.通过类型来获取 

context.getBean(UserController5.class)

2.通过名称来获取

context.getBean("userController5")

如果根据名称来获取,获取不到,那么这两个注解就会去根据类型来获取,如果都获取不到就会报错。

现在再来分析上面报错的原因,在UserBean类里面,有两个方法,这两个方法的类型都是User,其中一个方法名是GB1,另一个是GB2。而我们在UserController5类里面将User类通过属性注入的方式注入进来,但是我们取Bean的名称为user,@Autowired就会在com.user目录下面去找这个Bean对象,很明显是找不到的。然后@Autowired就会采用类型User的方式来找,在UserBean类里面他发现有两个User类型的Bean对象,这是它就不知道调用那一个了,所以就会报错。 

通过上面的分析,我们就可以在UserController5类里面修改Bean的名称,比如改为GB1:

@Controller
public class UserController5 {
    @Autowired
    private User GB1;

    public User findClient(){
        return GB1;
    }
}

但是如果现在不能修改Bean对象的名称,那就通过一下的方法来解决了:

使用@Resource(name="指定Bean的名称")

这种方式在介绍@Resource就演示过了,所以不在演示。

使用@Autowired+@Qualifier(value = "") 

@Controller
public class UserController5 {
    @Autowired
    @Qualifier(value = "GB1")
    private User user;

    public User findClient(){
        return user;
    }
}

Bean的作用域

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!--通过scope属性配置单实例 多实例-->
    <bean id="orders" class="com.atguigu.spring6.iocxml.scope.Orders"
          scope="singleton"></bean>
</beans>
package com.atguigu.spring6.iocxml.scope;

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

public class TestOrders {

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

<?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.atguigu.spring6.iocxml.scope.Orders"
          scope="prototype"></bean>
</beans>

Bean的生命周期 

  • bean对象创建(调用无参构造器)
  • 给bean对象设置属性
  • bean的后置处理器(初始化之前)
  • bean对象的初始化(需在配置bean时指定初始化方法)
  • bean的后置处理器(初始化之后)
  • bean对象就绪可以使用
  • bean对象销毁(需在配置bean时指定销毁方法)
  • IoC容器关闭 
package com.atguigu.spring6.iocxml.life;

public class User {

    //无参数构造
    public User() {
        System.out.println("1 bean对象创建,调用无参数构造");
    }


    private String name;

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

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

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

}
package com.atguigu.spring6.iocxml.life;

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;
    }
}
<?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.atguigu.spring6.iocxml.life.User"
          scope="singleton" init-method="initMethod" destroy-method="destroyMethod">
        <property name="name" value="lucy"></property>
    </bean>

    <!-- bean的后置处理器要放入IOC容器才能生效 -->
    <bean id="myBeanPost" class="com.atguigu.spring6.iocxml.life.MyBeanPost"/>
</beans>
package com.atguigu.spring6.iocxml.life;

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

public class TestUser {

    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(); //销毁
    }
}

FactoryBean 

FactoryBean是Spring提供的一种整合第三方框架的常用机制。和普通的bean不同,配置一个FactoryBean类型的bean,在获取bean的时候得到的并不是class属性中配置的这个类的对象,而是getObject()方法的返回值。通过这种机制,Spring可以帮我们把复杂组件创建的详细过程和繁琐细节都屏蔽起来,只把最简洁的使用界面展示给我们。

package com.atguigu.spring6.iocxml.factorybean;

public class User {
}
package com.atguigu.spring6.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;
    }
}
<?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.atguigu.spring6.iocxml.factorybean.MyFactoryBean"></bean>
</beans>
package com.atguigu.spring6.iocxml.factorybean;

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

public class TestUser {

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

Spring基于Xml自动装配 

自动装配:根据指定的策略,在IoC容器中某一个bean,自动为指定的Bean中依赖的类或接口中的属性赋值 

在没有使用自动装配前:

package com.atguigu.spring6.iocxml.auto.dao;

public interface UserDao {

    public void addUserDao();
}
package com.atguigu.spring6.iocxml.auto.dao;

public class UserDaoImpl  implements UserDao{

    @Override
    public void addUserDao() {
        System.out.println("userDao方法执行了...");
    }
}
package com.atguigu.spring6.iocxml.auto.service;

public interface UserService {

    public void addUserService();
}
package com.atguigu.spring6.iocxml.auto.service;

import com.atguigu.spring6.iocxml.auto.dao.UserDao;
import com.atguigu.spring6.iocxml.auto.dao.UserDaoImpl;

public class UserServiceImpl  implements UserService{

    @Override
    public void addUserService() {
        System.out.println("userService方法执行了...");
        userDao.addUserDao();
        UserDao userDao = new UserDaoImpl();
        userDao.addUserDao();
    }
}
package com.atguigu.spring6.iocxml.auto.controller;

import com.atguigu.spring6.iocxml.auto.service.UserService;
import com.atguigu.spring6.iocxml.auto.service.UserServiceImpl;

public class UserController {

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

使用自动装配:
1.在controller里面设置service类型的属性,生成service属性set方法;在service里面设置dao类型的属性,生成dao属性set方法;

package com.atguigu.spring6.iocxml.auto.service;

import com.atguigu.spring6.iocxml.auto.dao.UserDao;
import com.atguigu.spring6.iocxml.auto.dao.UserDaoImpl;

public class UserServiceImpl  implements UserService{

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

    @Override
    public void addUserService() {
        System.out.println("userService方法执行了...");
        userDao.addUserDao();
    }
}
package com.atguigu.spring6.iocxml.auto.controller;

import com.atguigu.spring6.iocxml.auto.service.UserService;
import com.atguigu.spring6.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方法执行了...");
        //调用service的方法
        userService.addUserService();
    }
}

2. 编写配置文件

a)根据类型自动装配

<?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="userController" class="com.atguigu.spring6.iocxml.auto.controller.UserController"
          autowire="byType">
    </bean>
    <bean id="userService" class="com.atguigu.spring6.iocxml.auto.service.UserServiceImpl"
          autowire="byType">

    </bean>
    <bean id="userDao" class="com.atguigu.spring6.iocxml.auto.dao.UserDaoImpl">
    </bean>
</beans>
package com.atguigu.spring6.iocxml.auto;

import com.atguigu.spring6.iocxml.auto.controller.UserController;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestUser {

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

注意 :若在IOC中,没有任何一个兼容类型的bean能够为属性赋值,则该属性不装配,即值为默认值null。若在IOC中,有多个兼容类型的bean能够为属性赋值,则抛出异常NoUniqueBeanDefinitionException

b)根据名称自动装配:
 

<?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="userController" class="com.atguigu.spring6.iocxml.auto.controller.UserController"
          autowire="byName">
    </bean>
    <bean id="userService" class="com.atguigu.spring6.iocxml.auto.service.UserServiceImpl"
          autowire="byName">
    </bean>
    <bean id="userDao" class="com.atguigu.spring6.iocxml.auto.dao.UserDaoImpl">
    </bean>
</beans>

基于注解实现自动装配

Spring 从 2.5 版本开始提供了对注解技术的全面支持,我们可以使用注解来实现自动装配,简化 Spring 的 XML 配置。 

Spring 通过注解实现自动装配的步骤如下:

  1. 引入依赖
  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"
       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.atguigu.spring6"></context:component-scan>


</beans>
  1. 使用注解定义 Bean
package com.atguigu.spring6.bean;

import org.springframework.stereotype.Component;
import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Repository;
import org.springframework.stereotype.Service;


@Controller
public class User {
}
  1. 依赖注入

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

咸鱼吐泡泡

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

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

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

打赏作者

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

抵扣说明:

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

余额充值