Spring (2)-IoC Inversion of Control

Table of contents

1. Concept (guiding ideology)

2. Spring's first program

3. The characteristics of the object created by the spring container

4. XML-based DI

4.1 Injection classification

1) set injection

2) Construct injection

4.2 Automatic injection of reference types

1) byName (injection by name)

2) byType (injection by type)

4.3 Ioc case exercises

4.4 Specify multiple configuration files for the application

5. Annotation-based DI (key mastery)

5.1 Define bean annotation @Component

1) demo project

2) Create four annotations for the object

3) Three ways to scan multiple packages

5.2 Simple Type Property Injection @Value

5.3 @Autowired automatic injection

5.4 JDK annotation @Resource automatic injection

6. IoC summary


1. Concept (guiding ideology)

1)IOC(Inversion of Control):

Inversion of control is a theory and a guiding ideology that guides developers on how to use objects, manage objects, and hand over object creation, attribute assignment, and object lifecycle to container management outside the code.

IoC is divided into control and inversion:

Control : object creation, attribute assignment, life cycle management

Before talking about reverse, let's talk about forward rotation.

Forward rotation : Developers use new to create objects in the code. Developers have mastered the creation of objects, attribute assignment, and the entire process of objects from start to destruction. Developers have full control over objects.

Inversion : The developer hands over the management authority of the object to the container implementation outside the code. Object management is done by the container.

Through the container, you can use the object in the container (the container has created the object, the object property has been assigned, and the object has been assembled)

2) Technical implementation of IoC

DI (Dependency Injection): Dependency Injection, abbreviated as DI, is a technical implementation of IoC. The program only needs to provide the object name. How to create the object, how to find it from the container, and how to obtain it are all implemented by the container itself.

3) The Spring framework uses DI to implement IoC

Through the spring framework, you only need to provide the name of the object to be used, and get the object corresponding to the name from the container.

The bottom layer of spring creates objects through reflection, assigns values, and so on.

2. Spring's first program

The first example implementation steps :

1) Create a new maven project

2) Add dependencies and modify the pom.xml file

spring-context: spring dependency

junit: unit test

3) The developer defines the class: interface and implementation

A class can also have no interface

Definition of interface and implementation class: Just like without spring, you can define it as you want

4) Create a spring configuration file, function: life object

Hand over objects to spring creation and management

Use <bean> to represent object declaration, a bean represents a java object

5) Use the object in the container:

Create an object representing the spring container, ApplicationContext

Get the object from the container by name, use getBean("object name")

Directory Structure:

pom.xml

<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.kuang</groupId>
    <artifactId>Spring-01</artifactId>
    <version>1.0.0</version>

    <name>Spring-01</name>
    <description>Demo project</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.2.5.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.11</version>
            <scope>test</scope>
        </dependency>

    </dependencies>

</project>

Configuration file beans.xml

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

    <bean id="someService" class="com.feiyang.service.impl.SomeServiceImpl">
    </bean>

</beans>

Interface and implementation class:

package com.feiyang.service;

public interface SomeService {
    void doSome();
}
package com.feiyang.service.impl;

import com.feiyang.service.SomeService;

/**
 * @author:飞扬
 * @公众hao:程序员飞扬
 * @description:
 */
public class SomeServiceImpl implements SomeService {

    public void doSome() {
        System.out.println("doSome()方法执行了");
    }
}

main method:

package com.feiyang;

import com.feiyang.service.SomeService;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Spring01Application {
    public static void main(String[] args) {
        //传统方法
        /*SomeService someService = new SomeServiceImpl();
        someService.doSome();*/

        //使用spring框架
        String config = "beans.xml";
        ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext(config);
        SomeService someService1 = (SomeService) ctx.getBean("someService");
        someService1.doSome();
    }
}

Results of the:

The doSome() method executes

Spring configuration file:

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

</beans>

Spring standard configuration file:

1) The root tag is beans

2) Beans is followed by a constraint file description

3) Inside the beans is the bean declaration

4) What is a bean: a bean is a java object, and the java object managed by the spring container is called a bean

3. The characteristics of the object created by the spring container

1. Container object ApplicationContext: interface

Through the ApplicationContext object, get other java objects to be used, and execute getBean("id")

2. Spring defaults to calling the no-argument constructor of the class to create the object

3. Spring reads the configuration file, creates all java objects at once, and puts them in the map

package com.feiyang;

import com.feiyang.service.SomeService;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.util.Date;

/**
 * @author:飞扬
 * @公众hao:程序员飞扬
 * @description:
 */
public class MyTest {

    //spring创建对象,调用的是类的哪个方法?
    //默认调用类的无参构造方法
    @Test
    public void test01(){
        String config = "beans.xml";
        ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext(config);
        SomeService bean = ctx.getBean(SomeService.class);
        bean.doSome();

        //打印:
        //SomeServiceImpl的无参构造方法执行了
        //doSome()方法执行了
    }


    /**
     * spring什么时候创建对象?
     *
     * spring创建容器对象的时候,会读取配置文件,创建文件中的所有声明的java对象
     */
    @Test
    public void test02(){
        String config = "beans.xml";
        ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext(config);
//        SomeService bean = ctx.getBean(SomeService.class);
//        bean.doSome();

        //打印:
        //SomeServiceImpl的无参构造方法执行了
    }

    /**
     * 获取容器中的对象信息
     */
    @Test
    public void test03(){
        String config = "beans.xml";
        ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext(config);

        //获取容器中有多少个对象
        int beanDefinitionCount = ctx.getBeanDefinitionCount();
        System.out.println("容器中定义的对象数量=" + beanDefinitionCount);

        //获取容器中对象的名称
        String[] beanDefinitionNames = ctx.getBeanDefinitionNames();
        for (String beanDefinitionName : beanDefinitionNames) {
            System.out.println("容器中对象名称=" + beanDefinitionName);
        }
    }
    //打印:
    /**
     * SomeServiceImpl的无参构造方法执行了
     * SomeServiceImpl的无参构造方法执行了
     * 容器中定义的对象数量=3
     * 容器中对象名称=someService
     * 容器中对象名称=someService1
     * 容器中对象名称=myDate
     */

    /**
     * 创建非自定义对象
     */
    @Test
    public void test04() {
        String config = "beans.xml";
        ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext(config);
        Date myDate = (Date) ctx.getBean("myDate");
        System.out.println(myDate);
    }
    //Print:
    /**
     * The parameterless constructor of SomeServiceImpl is executed
     * The parameterless constructor of SomeServiceImpl is executed
     * Sun Oct 02 15:08:52 GMT+08:0
     */

}

4. XML-based DI

4.1 Injection classification

1) set injection

Table of contents:

①Basic type assignment

pom.xml

<?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">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>Spring02-di-xml</artifactId>
    <version>1.0-SNAPSHOT</version>

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

    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.2.5.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.11</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.11</version>
            <scope>test</scope>
        </dependency>

    </dependencies>

</project>

applicationContext.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="myStudent" class="com.feiyang.ba01.Student">
        <property name="name" value="张三"></property>
        <property name="age" value="28"></property>
        <property name="email" value="[email protected]"></property>
    </bean>

    <!-- 给非自定义类属性赋值-->
    <bean id="myDate" class="java.util.Date">
        <property name="time" value="956955551315"></property>
    </bean>
</beans>

Student.java

package com.feiyang.ba01;

/**
 * @author:飞扬
 * @公众hao:程序员飞扬
 * @description:
 */
public class Student {
    private String name;
    private int age;

    public Student() {
        System.out.println("无参构造方法执行了");
    }

    public Student(String name, int age) {
        System.out.println("有参构造执行了");
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        System.out.println("setName方法执行了");
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        System.out.println("setAge方法执行了");
        this.age = age;
    }

    //set注入,和属性名无关,有set方法就执行
    public void setEmail(String email){
        System.out.println("setEmail方法执行了");
    }

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

Mytest01:

package com.feiyang.ba01;

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

import java.util.Date;

/**
 * @author:飞扬
 * @公众hao:程序员飞扬
 * @description:
 */
public class Mytest01 {

    @Test
    public void test01(){
        String config = "ba01/applicationContext.xml";
        ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext(config);

        //简单类型set注入
        Object student = ctx.getBean("myStudent");
        System.out.println(student);

        //给非自定义对象属性赋值
        Date date = (Date)ctx.getBean("myDate");
        System.out.println("date===" + date);

    }
}

Results of the:

The parameterless constructor is executed

The setName method executes

The setAge method executes

The setEmail method executes

Student{name='Zhang San', age=28}

date===Sat Apr 29 04:59:11 GMT+08:00 2000

②Reference type assignment

School.java

package com.feiyang.ba02;

/**
 * @author:飞扬
 * @公众hao:程序员飞扬
 * @description:
 */
public class School {
    private String name;
    private String address;

    public School() {
    }

    public School(String name, String address) {
        this.name = name;
        this.address = address;
    }

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

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

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

Student.java

package com.feiyang.ba02;

/**
 * @author:飞扬
 * @公众hao:程序员飞扬
 * @description:
 */
public class Student {
    private String name;
    private int age;
    private School school;

    public Student() {
        System.out.println("无参构造方法执行了");
    }

    public Student(String name, int age) {
        System.out.println("有参构造执行了");
        this.name = name;
        this.age = age;
    }

    public void setName(String name) {
        System.out.println("setName方法执行了");
        this.name = name;
    }

    public void setAge(int age) {
        System.out.println("setAge方法执行了");
        this.age = age;
    }

    public void setSchool(School school) {
        this.school = school;
    }

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

applicationContext.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="myStudent" class="com.feiyang.ba02.Student">
        <property name="name" value="张三"></property>
        <property name="age" value="28"></property>
        <property name="school" ref="mySchool"></property>
    </bean>

    <bean id="mySchool" class="com.feiyang.ba02.School">
        <property name="name" value="同济大学"></property>
        <property name="address" value="四平路"></property>
    </bean>
</beans>

Mytest02:

package com.feiyang.ba02;

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

import java.util.Date;

/**
 * @author:飞扬
 * @公众hao:程序员飞扬
 * @description:
 */
public class Mytest02 {

    @Test
    public void test02(){
        String config = "ba02/applicationContext.xml";
        ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext(config);

        Object student = ctx.getBean("myStudent");
        System.out.println(student);
    }
}

Results of the:

The parameterless constructor is executed

The setName method executes

The setAge method executes

Student{name='Zhang San', age=28, school=School{name='Tongji University', address='Siping Road'}}

2) Construct injection

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

    <!-- 构造注入-使用name属性 -->
    <bean id="myStudent" class="com.feiyang.ba03.Student">
        <constructor-arg name="name" value="lisi"></constructor-arg>
        <constructor-arg name="age" value="25"></constructor-arg>
        <constructor-arg name="school" ref="mySchool"></constructor-arg>
    </bean>

    <!-- 构造注入-使用index属性,index属性表示参数的索引,0,1,2... -->
    <bean id="myStudent2" class="com.feiyang.ba03.Student">
        <constructor-arg index="0" value="王五"></constructor-arg>
        <constructor-arg index="1" value="28"></constructor-arg>
        <constructor-arg index="2" ref="mySchool"></constructor-arg>
    </bean>

    <!-- 构造注入-省略index属性 -->
    <bean id="myStudent3" class="com.feiyang.ba03.Student">
        <constructor-arg value="赵六"></constructor-arg>
        <constructor-arg value="22"></constructor-arg>
        <constructor-arg ref="mySchool"></constructor-arg>
    </bean>

    <bean id="myFile" class="java.io.File">
        <constructor-arg name="pathname" value="d:\\myFile.txt"></constructor-arg>
    </bean>

    <bean id="mySchool" class="com.feiyang.ba03.School">
        <property name="name" value="同济大学"></property>
        <property name="address" value="四平路"></property>
    </bean>
</beans>

package com.feiyang.ba03;

/**
 * @author:飞扬
 * @公众hao:程序员飞扬
 * @description:
 */
public class Student {
    private String name;
    private int age;
    private School school;

    public Student() {
    }

    public Student(String name, int age, School school) {
        this.name = name;
        this.age = age;
        this.school = school;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", school=" + school +
                '}';
    }
}
package com.feiyang.ba03;

/**
 * @author:飞扬
 * @公众hao:程序员飞扬
 * @description:
 */
public class School {
    private String name;
    private String address;

    public School() {
    }

    public School(String name, String address) {
        this.name = name;
        this.address = address;
    }

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

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

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

package com.feiyang.ba03;

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

import java.io.File;
import java.io.IOException;

/**
 * @author:飞扬
 * @公众hao:程序员飞扬
 * @description:
 */
public class Mytest03 {

    @Test
    public void test03() throws IOException {
        String config = "ba03/applicationContext.xml";
        ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext(config);

        Object student = ctx.getBean("myStudent");
        System.out.println(student);

        Object student2 = ctx.getBean("myStudent2");
        System.out.println(student2);

        Object student3 = ctx.getBean("myStudent3");
        System.out.println(student3);

        File myFile = (File)ctx.getBean("myFile");
        myFile.createNewFile();
        System.out.println(myFile + ",创建成功");

    }
}

Results of the:

Student{name='lisi', age=25, school=School{name='Tongji University', address='Siping Road'}}

Student{name='Wang Wu', age=28, school=School{name='Tongji University', address='Siping Road'}}

Student{name='Zhao Liu', age=22, school=School{name='Tongji University', address='Siping Road'}}

d:\myFile.txt, created successfully

4.2 Automatic injection of reference types

1) byName (injection by name)

: The name of the attribute in the java class is the same as the id name of the bean in the spring container, and the data type is the same. Such a bean can be automatically assigned to the reference type.

语法:<bean id="xxx" class="yyy" autowire="byName"> </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">

    <!-- byName方式,自动注入 -->
    <bean id="myStudent" class="com.feiyang.ba04.Student" autowire="byName">
        <property name="name" value="张三"></property>
        <property name="age" value="28"></property>
        <!--<property name="school" ref="mySchool"></property>-->
    </bean>

    <bean id="school" class="com.feiyang.ba04.School">
        <property name="name" value="同济大学"></property>
        <property name="address" value="四平路"></property>
    </bean>

</beans>
package com.feiyang.ba04;

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

/**
 * @author:飞扬
 * @公众hao:程序员飞扬
 * @description:自动注入byName
 */
public class Mytest04 {

    @Test
    public void test04(){
        String config = "ba04/applicationContext.xml";
        ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext(config);

        Object student = ctx.getBean("myStudent");
        System.out.println(student);

    }
}

Results of the:

The parameterless constructor is executed

The setName method executes

The setAge method executes

Student{name='Zhang San', age=28, school=School{name='Tongji University', address='Siping Road'}}

2) byType (inject by type)

: The data type of the imported type in the java object is the same as the value of the bean class; or the parent-child relationship; or the interface and implementation relationship

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

    <!-- byType方式,自动注入 -->
    <bean id="myStudent2" class="com.feiyang.ba05.Student" autowire="byType">
        <property name="name" value="韩梅梅"></property>
        <property name="age" value="16"></property>
        <!--<property name="school" ref="mySchool"></property>-->
    </bean>

    <!-- byType自动注入条件①:java对象中的引用类型属性的数据类型和bean的class对象相同 -->
    <!--<bean id="school2" class="com.feiyang.ba05.School">
        <property name="name" value="同济大学"></property>
        <property name="address" value="上海四平路"></property>
    </bean>-->

    <!-- byType自动注入条件②:或者java对象中的引用类型属性的数据类型和bean的class是继承关系 -->
    <bean id="primarySchool" class="com.feiyang.ba05.PrimarySchool">
        <property name="name" value="实验小学"></property>
        <property name="address" value="上海淮海路"></property>
    </bean>
</beans>
package com.feiyang.ba05;

/**
 * @author:飞扬
 * @公众hao:程序员飞扬
 * @description:
 */
public class PrimarySchool extends School{
    private String name;
    private String address;

    public PrimarySchool() {
    }

    public PrimarySchool(String name, String address) {
        this.name = name;
        this.address = address;
    }

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

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

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

package com.feiyang.ba05;

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

/**
 * @author:飞扬
 * @公众hao:程序员飞扬
 * @description:自动注入byType
 */
public class Mytest05 {

    @Test
    public void test05(){
        String config = "ba05/applicationContext.xml";
        ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext(config);

        Object student2 = ctx.getBean("myStudent2");
        System.out.println(student2);
    }
}

Results of the:

The parameterless constructor is executed

The setName method executes

The setAge method executes

Student{name='Han Meimei', age=16, school=School{name='Experimental Primary School', address='Shanghai Huaihai Road'}}

The way spring works:

4.3 Ioc case exercises

Directory Structure:

applicationContext.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="mysqlUserDao" class="com.feiyang.dao.impl.MysqlUserDao"></bean>

    <bean id="userService" class="com.feiyang.service.impl.UserServiceImpl">
        <property name="userDao" ref="mysqlUserDao"></property>
    </bean>
</beans>

package com.feiyang.domain;

/**
 * @author:飞扬
 * @公众hao:程序员飞扬
 * @description:
 */
public class SysUser {
    private String name;
    private Integer age;

    public String getName() {
        return name;
    }

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

    public Integer getAge() {
        return age;
    }

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

package com.feiyang.dao;

import com.feiyang.domain.SysUser;

public interface UserDao {
    void addUser(SysUser user);
}
package com.feiyang.dao.impl;

import com.feiyang.dao.UserDao;
import com.feiyang.domain.SysUser;

/**
 * @author:飞扬
 * @公众hao:程序员飞扬
 * @description:
 */
public class MysqlUserDao implements UserDao {

    @Override
    public void addUser(SysUser user) {
        System.out.println("使用了dao执行了user的添加");
    }
}
package com.feiyang.service;

import com.feiyang.domain.SysUser;

public interface UserService {
    void addUser(SysUser user);
}
package com.feiyang.service.impl;

import com.feiyang.dao.UserDao;
import com.feiyang.domain.SysUser;
import com.feiyang.service.UserService;

/**
 * @author:飞扬
 * @公众hao:程序员飞扬
 * @description:
 */
public class UserServiceImpl implements UserService {

    private UserDao userDao;

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

    @Override
    public void addUser(SysUser user) {
        userDao.addUser(user);
    }
}

Test class Mytest01:

package com.feiyang;

import com.feiyang.domain.SysUser;
import com.feiyang.service.UserService;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * @author:飞扬
 * @公众hao:程序员飞扬
 * @description:
 */
public class Mytest01 {

    @Test
    public void test01(){
        String config = "applicationContext.xml";
        ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext(config);
        UserService userService = (UserService) ctx.getBean("userService");

        SysUser sysUser = new SysUser();
        sysUser.setName("胖虎");
        sysUser.setAge(8);
        userService.addUser(sysUser);
    }
}

Results of the:

Use dao to execute user addition

IoC can achieve decoupling:

Added dao implementation:

package com.feiyang.dao.impl;

import com.feiyang.dao.UserDao;
import com.feiyang.domain.SysUser;

/**
 * @author:飞扬
 * @公众hao:程序员飞扬
 * @description:
 */
public class OracleUserDao implements UserDao {

    @Override
    public void addUser(SysUser user) {
        System.out.println("oracle使用了dao执行了user的添加");
    }
}

Modify the configuration file:

<?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="mysqlUserDao" class="com.feiyang.dao.impl.MysqlUserDao"></bean>

    <bean id="oracleUserDao" class="com.feiyang.dao.impl.OracleUserDao"></bean>

    <!--<bean id="userService" class="com.feiyang.service.impl.UserServiceImpl">
        <property name="userDao" ref="mysqlUserDao"></property>
    </bean>-->

    <bean id="userService" class="com.feiyang.service.impl.UserServiceImpl">
        <property name="userDao" ref="oracleUserDao"></property>
    </bean>
</beans>

No other code needs to be moved, and the execution result is:

Oracle uses dao to add user

4.4 Specify multiple configuration files for the application

There are several ways to load multiple configuration files:

①Use import to load multiple configuration files

②Use wildcards to load multiple configuration files

package com.feiyang.ba06;

/**
 * @author:飞扬
 * @公众hao:程序员飞扬
 * @description:
 */
public class School {
    private String name;
    private String address;

    public School() {
    }

    public School(String name, String address) {
        this.name = name;
        this.address = address;
    }

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

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

    @Override
    public String toString() {
        return "School{" +
                "name='" + name + '\'' +
                ", address='" + address + '\'' +
                '}';
    }
}
package com.feiyang.ba06;

/**
 * @author:飞扬
 * @公众hao:程序员飞扬
 * @description:
 */
public class Student {
    private String name;
    private int age;
    private School school;

    public Student() {
        //System.out.println("无参构造方法执行了");
    }

    public Student(String name, int age) {
        //System.out.println("有参构造执行了");
        this.name = name;
        this.age = age;
    }

    public void setName(String name) {
        //System.out.println("setName方法执行了");
        this.name = name;
    }

    public void setAge(int age) {
        //System.out.println("setAge方法执行了");
        this.age = age;
    }

    public void setSchool(School school) {
        this.school = school;
    }

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

spring-school.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">

    <!-- byType自动注入条件①:java对象中的引用类型属性的数据类型和bean的class对象相同 -->
    <bean id="school" class="com.feiyang.ba06.School">
        <property name="name" value="同济大学"></property>
        <property name="address" value="上海四平路"></property>
    </bean>

</beans>

spring-student.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">

    <!-- byType方式,自动注入 -->
    <bean id="myStudent2" class="com.feiyang.ba06.Student" autowire="byType">
        <property name="name" value="韩梅梅"></property>
        <property name="age" value="16"></property>
        <!--<property name="school" ref="school2"></property>-->
    </bean>

</beans>

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

    <!-- import方式加载多个配置文件 -->
    <!--<import resource="classpath:/ba06/spring-school.xml"></import>
    <import resource="classpath:/ba06/spring-student.xml"></import>-->

    <!-- 通配符方式加载多个配置文件-->
    <import resource="classpath:/ba06/spring-*"></import>

</beans>

Test class:

package com.feiyang.ba06;

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

/**
 * @author:飞扬
 * @公众hao:程序员飞扬
 * @description:自动注入byType
 */
public class Mytest06 {

    @Test
    public void test06(){
        String config = "ba06/applicationContext.xml";
        ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext(config);

        Object student2 = ctx.getBean("myStudent2");
        System.out.println(student2);
    }
}

Results of the:

Student{name='Han Meimei', age=16, school=School{name='Tongji University', address='Shanghai Siping Road'}}

5. Annotation-based DI (key mastery)

5.1 Define bean annotation @Component

Annotation-based DI: Use annotations provided by spring to complete java object creation and property assignment

The core steps used by annotations:

1. Add annotations to the source code, for example: @Component

2. In the spring configuration file, add the label of the component scanner

<context:component-scan base-package="com.feiyang.ba01"></context:component-scan>

1) demo project

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

    <context:component-scan base-package="com.feiyang.ba01"></context:component-scan>
</beans>

package com.feiyang.ba01;

import org.springframework.stereotype.Component;

/**
 * @author:飞扬
 * @公众hao:程序员飞扬
 * @description:
 */

//使用value指定对象的名称
//@Component(value = "myStudent")

//value可以省略
//@Component("myStudent")

//没有指定名称,则框架默认的名称是,类名首字母小写,例如:student
@Component()
public class Student {
    private String name;

    private int age;

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

package com.feiyang.ba01;

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

/**
 * @author:飞扬
 * @公众hao:程序员飞扬
 * @description:
 */
public class Mytest01 {

    @Test
    public void test01(){
        String config = "/ba01/applicationContext.xml";
        ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext(config);
        //Student student = (Student) ctx.getBean("myStudent");
        Student student = (Student) ctx.getBean("student");//没有指定名称,则为默认名称
        System.out.println(student);
    }
}

Results of the:

Student{name='null', age=0}

2) Create four annotations for the object

① @Component

Annotation for creating objects with the same function as @Component

② @Repository is placed on the implementation class of the dao interface, indicating the creation of dao objects, persistence layer objects, and access to the database.

③ @Service is placed on the implementation class of the business layer interface, indicating the creation of business layer objects, which have transaction functions.

④ Putting @Controller on the controller class means creating a controller object, which belongs to the presentation layer object. The controller object can receive the request and display the processing result of the request to the client.

The above four annotations can create objects, but the last three have role descriptions, indicating that the objects are hierarchical. And the latter three annotations are all extended on the basis of the first annotation.

3) Three ways to scan multiple packages

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

    <context:component-scan base-package="com.feiyang.ba01"></context:component-scan>

    <!-- 扫描多个包的三种方式 -->
    <!-- 第一种:使用多次组件扫描 -->
    <context:component-scan base-package="com.feiyang.ba01"></context:component-scan>
    <context:component-scan base-package="com.feiyang.ba02"></context:component-scan>

    <!-- 第二种:使用分隔符(;或,),指定多个包 -->
    <context:component-scan base-package="com.feiyang.ba01;com.feiyang.ba01"></context:component-scan>

    <!-- 第三种:指定父包 -->
    <context:component-scan base-package="com.feiyang"></context:component-scan>
</beans>

5.2 Simple Type Property Injection @Value

Two ways: ① Annotate the attribute directly and specify the value

@Value("张三")
private String name;

②Refer to external configuration files

@Value("${myname}")
private String name;

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

    <context:component-scan base-package="com.feiyang.ba02"></context:component-scan>

    <!-- 读取外部配置文件 -->
    <context:property-placeholder location="classpath:/myconf.properties"></context:property-placeholder>

</beans>

package com.feiyang.ba02;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Repository;
import org.springframework.stereotype.Service;

/**
 * @author:飞扬
 * @公众hao:程序员飞扬
 * @description:
 */

//使用value指定对象的名称
@Component(value = "myStudent")

//value可以省略
//@Component("myStudent")

//没有指定名称,则框架默认的名称是,类名首字母小写,例如:student
//@Component()
public class Student {

    //@Value("张三")

    //读取外部配置文件
    @Value("${myname}")
    private String name;

    @Value("${myage}")
    private int age;

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

package com.feiyang.ba02;

import com.feiyang.ba02.Student;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * @author:飞扬
 * @公众hao:程序员飞扬
 * @description:
 */
public class Mytest02 {

    @Test
    public void test01(){
        String config = "/ba01/applicationContext.xml";
        ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext(config);
        Student student = (Student) ctx.getBean("myStudent");
        System.out.println(student);
    }
}

Results of the:

Student{name='Li Lei', age=16}

5.3 @Autowired automatic injection

There are two ways: ①byType automatically inject @Autowired

②byName automatically injects @Autowired and @Qualifier

@Autowired attribute, require: Boolean type attribute
true: spring starts, when creating a container object, it will check whether the reference type is assigned successfully, if the assignment fails, terminate the program and report an error
false: if the application type fails to assign, the program executes normally without reporting an error, The value of a reference type is null.

package com.feiyang.ba03;

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

/**
 * @author:飞扬
 * @公众hao:程序员飞扬
 * @description:
 */

@Component(value = "mySchool")
public class School {

    @Value("复旦大学")
    private String name;

    @Value("上海市四平路校区")
    private String address;

    @Override
    public String toString() {
        return "School{" +
                "name='" + name + '\'' +
                ", address=" + address +
                '}';
    }
}
package com.feiyang.ba03;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Required;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.xml.ws.RequestWrapper;

/**
 * @author:飞扬
 * @公众hao:程序员飞扬
 * @description:
 */

//使用value指定对象的名称
@Component(value = "myStudent")

//value可以省略
//@Component("myStudent")

//没有指定名称,则框架默认的名称是,类名首字母小写,例如:student
//@Component()
public class Student {

    //@Value("张三")

    //读取外部配置文件
    @Value("${myname}")
    private String name;

    @Value("${myage}")
    private int age;

    /**
     * 引用类型
     * @Autowired spring提供的注解,给引用类型赋值,使用自动注入原理,支持byName,byType。默认是byType
     * 位置:1)在属性上面,无set方法(推荐使用)
     *      2)在set方法上面
     *
     */
    //第一种方式:byType
//    @Autowired
//    private School school;

    //第二中方式:byName
            //@Qualifier:指定对象

    /**
     * 属性,require:布尔类型的属性
     * true:spring启动,创建容器对象时,会检查引用类型是否赋值成功,如果赋值失败,终止程序并报错
     * false:应用类型若赋值失败,程序正常执行不报错,引用类型的值是null.
      */
    @Autowired(required = true)
    @Qualifier("mySchool")
    private School school;

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", school=" + school +
                '}';
    }
}
package com.feiyang;

import com.feiyang.ba03.Student;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * @author:飞扬
 * @公众hao:程序员飞扬
 * @description:
 */
public class Mytest03 {

    @Test
    public void test03(){
        String config = "/ba01/applicationContext.xml";
        ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext(config);
        Student student = (Student) ctx.getBean("myStudent");
        System.out.println(student);
    }
}

Results of the:

Student{name='Li Lei', age=16, school=School{name='Fudan University', address=Shanghai Siping Road Campus}}

5.4 JDK annotation @Resource automatic injection

Spring provides support for the jdk@Resource annotation. The @Resource annotation can match beans either by name or by type. The default is to inject by name. Using this annotation requires that the JDK version must be 6 or above. @Resource can be on a property or on a set method.

//Assign byName by default, if the assignment fails, use byType to assign
    @Resource
    private School school;

//Only use the byName method to assign
    @Resource(name="mySchool")
    private School school;

6. IoC summary

1. Annotations for creating objects

@Component

@Repository

@Service

@Controller

2. Simple type attribute assignment

@Value

3. Reference type assignment

@Autowired : Annotation provided by spring, supports byName, byType

@Autowired : The default is byType

@Autowired @Qualifier : use byName

@Resource : An annotation from jdk, assigned to the reference type, the default is byName

@Resource : first use byName, then byType

@Resource(name="bean's name") : Only use byName injection

IoC: Manage objects, put objects into containers, create, assign, and manage dependencies.

IoC: Decoupling is achieved through management objects. IoC solves the coupling relationship between processing business logic objects, that is, the decoupling between service and dao.

Guess you like

Origin blog.csdn.net/lu_xin5056/article/details/128973159