快速梳理Spring知识点 - IOC

目录

一、Spring框架概述

二、Sping 初体验

三、IOC容器

 1. IOC概念和原理

 2. IOC接口(BeanFactory)

 3. Bean管理什么是Bean管理?

  IOC操作Bean管理(基于xml)

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

 4. Bean的作用域

 5. Bean的生命周期

 6. 引入外部属性文件

一、Spring框架概述

  1. Spring 是轻量级的开源JavaEE 框架
  2. Spring 可以解决企业应用开发的复杂性
  3. Spring 的两个核心部分:IOC 和 AOP
    • IOC: 控制反转,把创建对象的过程交给Spring 进行管理
    • AOP: 面向切面,不修改源代码进行功能增强
  4. Spring 特点
    • 方便解耦,简化开发
    • AOP编程支持
    • 方便程序测试
    • 方便和其他框架进行整和
    • 方便进行事务操作
    • 降低API开发难度

二、Sping 初体验

  1. 创建一个maven项目

  2. 引入spring5.x版本基础jar包

    core、context、aop、expression (commons-logging 非Spring框架内)

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-core</artifactId>
        <version>5.2.9.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>5.2.9.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-aop</artifactId>
        <version>5.2.9.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-expression</artifactId>
        <version>5.2.9.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>commons-logging</groupId>
        <artifactId>commons-logging</artifactId>
        <version>1.2</version>
    </dependency>
    
  1. 创建一个普通类,在这个类创建普通方法

    public class User {
        public void add() {
            System.out.println("add...");
        }
    }
    
  2. 创建Spring配置文件,在配置文件配置创建的对象

    • Spring配置文件使用xml
    • 创建bean1.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">
    
        <!--配置User对象创建-->
        <bean id="user" class="com.yang.spring5.User"></bean>
    </beans>
    
  3. 进行测试编码

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

三、IOC容器

1. IOC概念和原理

  • 什么是IOC ?

控制反转,把对象创建和对象之间的调用过程,交给spring管理

使用IOC的目的:为了降低耦合度

  • IOC底层原理

主要使用了xml解析、工厂模式、反射

  • IOC过程

    • 第一步 xml配置文件,配置要创建的对象
    <!--配置User对象创建-->
    <bean id="user" class="com.yang.spring5.User"></bean>
    
    • 第二步 创建工厂类,通过xml解析,获取class属性值,再通过反射创建对象

2. IOC接口(BeanFactory)

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

  • Spring提供IOC容器实现的两种方式

    • BeanFactory:IOC容器基本实现,Spring内部使用接口,不提供开发人员使用

    加载配置文件的时候不会创建对象,获取对象的时候才会去创建对象

    • ApplicationCpntext:BeanFactory的子接口,功能更加强大,一般由开发人员使用

    加载配置文件的时候就会把配置文件中的对象进行创建

    加载配置文件的两个实现类
    - ClassPathXmlApplicationContext
    - FileSystemXmlApplicationContext
    
    这两个实现类的区别
    ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");//类路径
    ApplicationContext context = new FileSystemXmlApplicationContext("D:\\Java_learning\\spring-learning\\src\\main\\resources\\bean1.xml");//绝对路径
    

3. Bean管理

什么是Bean管理?

Bean管理实际上是指两个操作

  1. Spring创建对象
  2. Spring注入属性

IOC操作Bean管理(基于xml)

  • 在Spring配置文件中,使用bean标签,标签里添加对应属性,就可以实现对象创建。
<!--配置User对象创建-->
<bean id="user" class="com.yang.spring5.User"></bean>
  • bean标签中常用属性
    • id:唯一标识
    • class:类全路径
    • name:类似与id属性,区别是name可以加特殊标识,如 “/” 等。
  • 创建对象的时候,默认执行无参构造方法,完成对象创建。
  • 属性注入(DI)

    set注入、构造器注入、P名称空间注入

    • 第一种:使用set方法注入。
    1. 创建类,定义属性和它的set方法
    /**
     * @Author: csy
     * @Date: 2020/12/17 20:38
     * @Description: 使用set方法进行属性注入
     */
    public class Book {
    
        private String name;
    
        public void setName(String name) {
            this.name = name;
        }
    
        public void show() {
            System.out.println("name:" + name);
        }
    }
    
    1. 在spring配置文件中,配置对象创建和属性注入
    <!--配置Book对象创建-->
    <bean id="book" class="com.yang.spring5.Book">
        <!--使用property完成属性注入-->
        <property name="name" value="语文"></property>
    </bean>
    
    1. 测试
    public class Spring5Test {
    
        @Test
        public void testAdd() {
            //1 加载spring配置文件
            ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
            //2 获取配置创建的对象
            Book book = context.getBean("book", Book.class);
            book.show();
        }
    }
    
    1. 输出
    name:语文
    
    • 第二种:使用有参构造方法注入。
    1. 创建类,定义属性和有参构造方法。
    /**
     * @Author: csy
     * @Date: 2020/12/17 21:15
     * @Description: 使用有参构造方法注入
     */
    public class Orders {
    
        private String name;
    
        public Orders(String name) {
            this.name = name;
        }
    
        public void show(){
            System.out.println("name:"+ name);
        }
    }
    
    1. 在Spring配置文件中,配置对象创建和属性注入
    <!--配置Orders对象创建-->
    <bean id="orders" class="com.yang.spring5.Orders">
        <!--使用 constructor-arg 完成属性注入-->
        <constructor-arg name="name" value="销售订单"/>
    </bean>
    
    1. 测试
    public class Spring5Test {
    
        @Test
        public void testAdd() {
            //1 加载spring配置文件
            ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
            //2 获取配置创建的对象
            Orders orders = context.getBean("orders", Orders.class);
            orders.show();
        }
    }
    
    1. 结果
    name:销售订单
    
    • 第三种:P名称空间注入

      使用P名称空间注入,可以简化基于XML配置方式

    1. 在配置文件中添加P名称空间
    xmlns:p="http://www.springframework.org/schema/p"
    
    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:p="http://www.springframework.org/schema/p"
         xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    
      <!--使用P标签注入-->
      <bean id="book" class="com.yang.spring5.Book" p:name="数学">
      </bean>
    
    </beans>
    
  • 特殊类型值注入
    • null
    <!--通过<null></null>标签注入-->
    <!--配置Book对象创建-->
    <bean id="book" class="com.yang.spring5.Book">
     <!--使用property完成属性注入-->
     <property name="name">
         <null></null>
     </property>
    </bean>
    
    • 特殊符号
    <!--1.把特殊符号转义-->
    <!--2.把带特殊符号的内容写到CDATA中-->
    <!--配置Book对象创建-->
    <bean id="book" class="com.yang.spring5.Book">
        <!--使用property完成属性注入-->
        <property name="name">
            <value><![CDATA[<<语文>>]]></value>
        </property>
    </bean>
    
  • 注入属性-外部bean

    场景:service类中引用dao类

    代码示例:

    1. 创建两个类,service类和dao类
    2. 在service类中调用dao里的方法
    3. 在spring配置文件中进行配置
    public class UserService {
    
        /**
         * 创建UserDao类型属性,生成set方法
         */
        private UserDao userDao;
    
        public void setUserDao(UserDao userDao) {
            this.userDao = userDao;
        }
    
        public void add() {
            System.out.println("service add....");
            userDao.update();
        }
    }
    
    public interface UserDao {
        public void update();
    }
    
    public class UserDaoImpl implements UserDao {
    
        @Override
        public void update() {
            System.out.println("dao update....");
        }
    }
    
    <?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="userService" class="com.yang.spring5.service.UserService">
            <!--  注入userDao对象    -->
            <!--  name属性:类里的属性名称   -->
            <!--  ref属性:创建userDao对象bean标签id值 -->
            <property name="userDao" ref="userDao"></property>
        </bean>
        <bean id="userDao" class="com.yang.spring5.dao.UserDaoImpl"></bean>
    </beans>
    
    public class Spring5Test2 {
    
        @Test
        public void testAdd() {
            //1 加载spring配置文件
            ApplicationContext context = new ClassPathXmlApplicationContext("bean2.xml");
            //2 获取配置创建的对象
            UserService userService = context.getBean("userService", UserService.class);
            userService.add();
        }
    
    }
    
  • 注入属性-内部bean和级联赋值

    内部bean

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

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

    部门是一,员工是多

    代码实例:

    1. 创建员工类与部门类(员工类中有部门属性)
    2. xml配置文件中进行内部bean配置
    package com.yang.spring5.bean;
    
    /**
     * @Description: 部门
     * @author: caoshenyang
     * @date: 2020.12.31
     */
    public class Dept {
    
        private String name;
    
        public void setName(String name) {
            this.name = name;
        }
    
        @Override
        public String toString() {
            return "Dept{" +
                    "name='" + name + '\'' +
                    '}';
        }
    }
    
    package com.yang.spring5.bean;
    
    /**
     * @Description: 员工
     * @author: caoshenyang
     * @date: 2020.12.31
     */
    public class Emp {
    
        private String name;
        private String gender;
        private Dept dept;
    
        public void setName(String name) {
            this.name = name;
        }
    
        public void setGender(String gender) {
            this.gender = gender;
        }
    
        public void setDept(Dept dept) {
            this.dept = dept;
        }
    
        @Override
        public String toString() {
            return "Emp{" +
                    "name='" + name + '\'' +
                    ", gender='" + gender + '\'' +
                    ", dept=" + dept +
                    '}';
        }
    }
    
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    
        <bean name="emp" class="com.yang.spring5.bean.Emp">
            <property name="name" value="张三"></property>
            <property name="gender" value="男"></property>
            <!--内部bean注入-->
            <!--当然也可以采用外部bean的方式来实现 1.外部创建dept的bean 2.内部通过ref标签引用-->
            <property name="dept" >
                <bean id="dept" class="com.yang.spring5.bean.Dept">
                    <property name="name" value="IT部门"></property>
                </bean>
            </property>
        </bean>
    </beans>
    
    package com.yang.spring5.testdemo;
    
    import com.yang.spring5.bean.Emp;
    import com.yang.spring5.service.UserService;
    import org.junit.Test;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    /**
     * @Author: csy
     * @Date: 2020/12/28 22:16
     * @Description:
     */
    public class Spring5Test3 {
    
        @Test
        public void testAdd() {
            //1 加载spring配置文件
            ApplicationContext context = new ClassPathXmlApplicationContext("bean3.xml");
            //2 获取配置创建的对象
            Emp emp = context.getBean("emp", Emp.class);
            System.out.println(emp);
        }
    }
    

    输出:

    Emp{name='张三', gender='男', dept=Dept{name='IT部门'}}
    

    级联赋值

    <?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 name="emp" class="com.yang.spring5.bean.Emp">
            <property name="name" value="张三"></property>
            <property name="gender" value="男"></property>
            <!--内部bean注入-->
            <!--当然也可以采用外部bean的方式来实现 1.外部创建dept的bean 2.内部通过ref标签引用-->
            <property name="dept" ref="dept" > </property>
            <!--依赖于get方法获取dept对象,然后给dept对象属性赋值,所以在Emp对象中需要实现对应的get方法-->
            <property name="dept.name" value="财务部门"></property>
        </bean>
        <bean id="dept" class="com.yang.spring5.bean.Dept"></bean>
    </beans>
    
    package com.yang.spring5.testdemo;
    
    import com.yang.spring5.bean.Emp;
    import org.junit.Test;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    /**
     * @Author: csy
     * @Date: 2020/12/28 22:16
     * @Description:
     */
    public class Spring5Test4 {
    
        @Test
        public void testAdd() {
            //1 加载spring配置文件
            ApplicationContext context = new ClassPathXmlApplicationContext("bean4.xml");
            //2 获取配置创建的对象
            Emp emp = context.getBean("emp", Emp.class);
            System.out.println(emp);
        }
    }
    

    输出:

    Emp{name='张三', gender='男', dept=Dept{name='财务部门'}
    
  • 注入集合属性
    • 注入数组类型属性
    • 注入List集合属性
    • 注入Map集合属性
    • 注入Set集合属性

    场景:当我们需要注入集合类型属性值的时候

    代码示例:

    1. 创建Stu类
    2. xml配置
    package com.yang.spring5.bean;
    
    import java.util.Arrays;
    import java.util.List;
    import java.util.Map;
    import java.util.Set;
    
    /**
     * @Description: 学生
     * @author: caoshenyang
     * @date: 2020.12.31
     */
    public class Student {
    
        private String[] course;
    
        private List<String> lists;
    
        private Map<String, String> maps;
    
        private Set<String> sets;
    
        public void setCourse(String[] course) {
            this.course = course;
        }
    
        public void setLists(List<String> lists) {
            this.lists = lists;
        }
    
        public void setMaps(Map<String, String> maps) {
            this.maps = maps;
        }
    
        public void setSets(Set<String> sets) {
            this.sets = sets;
        }
    
        @Override
        public String toString() {
            return "Student{" +
                    "course=" + Arrays.toString(course) +
                    ", lists=" + lists +
                    ", maps=" + maps +
                    ", sets=" + sets +
                    '}';
        }
    }
    
    <?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 name="student" class="com.yang.spring5.bean.Student">
            <property name="course">
                <array>
                    <value>语文</value>
                    <value>数学</value>
                </array>
            </property>
            <property name="lists">
                <list>
                    <value>JAVA</value>
                    <value>C语言</value>
                </list>
            </property>
            <property name="maps">
                <map>
                    <entry key="1" value="MySql"/>
                    <entry key="2" value="Redis"/>
                </map>
            </property>
            <property name="sets">
                <set>
                    <value>C++</value>
                    <value>C#</value>
                </set>
            </property>
        </bean>
    </beans>
    

    输出:

    Student{course=[语文, 数学], lists=[JAVA, C语言], maps={1=MySql, 2=Redis}, sets=[C++, C#]}
    
  • 在集合里设置对象类型值

    场景:教师类的课程属性为课程类

    1. 创建2个类Teacher类和Course类
    2. xml配置

    代码示例:

    package com.yang.spring5.bean;
    
    import java.util.List;
    
    /**
     * @Description: 教师
     * @author: caoshenyang
     * @date: 2020.12.31
     */
    public class Teacher {
    
       private List<Course> courses;
    
        public void setCourses(List<Course> courses) {
            this.courses = courses;
        }
    
        @Override
        public String toString() {
            return "Teacher{" +
                    "courses=" + courses +
                    '}';
        }
    }
    
    package com.yang.spring5.bean;
    
    /**
     * @Description: 课程
     * @author: caoshenyang
     * @date: 2020.12.31
     */
    public class Course {
    
        private String name;
    
        public void setName(String name) {
            this.name = name;
        }
    
        @Override
        public String toString() {
            return "Course{" +
                    "name='" + name + '\'' +
                    '}';
        }
    }
    
    <?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 name="teacher" class="com.yang.spring5.bean.Teacher">
            <property name="courses">
                <list>
                    <ref bean="course1"/>
                    <ref bean="course2"/>
                </list>
            </property>
    
        </bean>
    
        <bean name="course1" class="com.yang.spring5.bean.Course">
            <property name="name" value="JAVA"/>
        </bean>
        <bean name="course2" class="com.yang.spring5.bean.Course">
            <property name="name" value="VUE"/>
        </bean>
    </beans>
    

    输出:

    Teacher{courses=[Course{name='JAVA'}, Course{name='VUE'}]}
    
  • 把集合注入部分提取出来
    1. spring配置文件中引入名称空间util
  1. 使用util标签完成list集合注入提取
<?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">


    <util:list id="courses">
        <ref bean="course1"/>
        <ref bean="course2"/>
    </util:list>

    <bean name="teacher" class="com.yang.spring5.bean.Teacher">
        <property name="courses" ref="courses"/>
    </bean>

    <bean name="course1" class="com.yang.spring5.bean.Course">
        <property name="name" value="JAVA"/>
    </bean>
    <bean name="course2" class="com.yang.spring5.bean.Course">
        <property name="name" value="VUE"/>
    </bean>
</beans>

输出:

Teacher{courses=[Course{name='JAVA'}, Course{name='VUE'}]}
  • FactoryBean
    • 普通bean:xml中定义什么类型的bean,即返回什么类型的bean

    前面介绍的都为普通bean

    • 工厂bean:xml中定义的类型可以和返回的类型不一样

    代码示例:

    1. 创建工厂类,实现FactoryBean接口
    2. 实现接口中的方法,在方法中定义返回的类型
package com.yang.spring5.factoryBean;

import com.yang.spring5.bean.Course;
import org.springframework.beans.factory.FactoryBean;

/**
* @Description: 工厂bean
* @author: caoshenyang
* @date: 2020.12.31
*/
public class MyFactoryBean implements FactoryBean<Course> {
   @Override
   public Course getObject() throws Exception {
       Course course = new Course();
       course.setName("JAVA");
       return course;
   }

   @Override
   public Class<?> getObjectType() {
       return null;
   }

   @Override
   public boolean isSingleton() {
       return false;
   }
}
<?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 name="myFactoryBean" class="com.yang.spring5.factoryBean.MyFactoryBean"></bean>
</beans>
package com.yang.spring5.testdemo;

import com.yang.spring5.bean.Course;
import com.yang.spring5.bean.Teacher;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
* @Author: csy
* @Date: 2020/12/28 22:16
* @Description:
*/
public class Spring5Test8 {

   @Test
   public void testAdd() {
       //1 加载spring配置文件
       ApplicationContext context = new ClassPathXmlApplicationContext("bean8.xml");
       //2 获取配置创建的对象
       Course course = context.getBean("myFactoryBean", Course.class);
       System.out.println(course);
   }

}

输出:

Course{name='JAVA'}

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

  1. 什么是注解

    (1)注解是代码特殊标记,格式:@注解名称(属性名称=属性值, 属性名称=属性值…)

    (2)使用注解,注解作用在类上面,方法上面,属性上面

    (3)使用注解目的:简化 xml 配置

  2. Spring针对Bean管理提供的注解(下面四个注解功能一样,都可以用来创建实例)

    (1)@Component

    (2)@Service

    (3)@Controller

    (4)@Repository

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

    (1)引入AOP依赖

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-aop</artifactId>
        <version>5.2.9.RELEASE</version>
    </dependency>
    

    (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/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">
    
        <!--开启注解扫描
            1.扫描多个包,多个包使用逗号隔开
            2.扫描包的上层目录
        -->
        <context:component-scan base-package="com.yang.spring5"></context:component-scan>
    </beans>
    

    (3)创建类,加上注解

    //在注解里面 value 属性值可以省略不写,
    //默认值是类名称,首字母小写
    //StudentService -- studentService
    @Service(value = "studentService") //注解等同于XML配置文件:<bean id="studentService" class=".."/>
    public class StudentService {
        public void show() {
            System.out.println("service show ......");
        }
    }
    

    测试:

    @Test
    public void testAdd() {
        //1 加载spring配置文件
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("bean12.xml");
        //2 获取配置创建的对象
        StudentService studentService = context.getBean("studentService", StudentService.class);
        studentService.show();
    }
    

    输出:

    service show ......
    
  4. 开启组件扫描细节配置

<!--示例 1
     use-default-filters="false" 表示现在不使用默认 filter,自己配置 filter
     context:include-filter ,设置扫描哪些内容
-->
<context:component-scan base-package="com.yang.spring5" use-default-filters="false">
    <!--代表只扫描Controller注解的类-->
    <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
<!--示例 2
 下面配置扫描包所有内容
 context:exclude-filter: 设置哪些内容不进行扫描
-->
<context:component-scan base-package="com.yang.spring5">
    <!--表示Controller注解的类之外一切都进行扫描-->
    <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
  1. 基于注解方式实现属性注入

    (1)@AutoWired:根据属性类型进行自动装配

    ​ 第一步 把 service 和 dao 对象创建,在 service 和 dao 类添加创建对象注解

    ​ 第二步 在 service 注入 dao 对象,在 service 类添加 dao 类型属性,在属性上面使用注解

    @Service
    public class UserService {
     //定义 dao 类型属性
     //不需要添加 set 方法
     //添加注入属性注解
     @Autowired
     private UserDao userDao;
     public void add() {
     System.out.println("service add.......");
     userDao.add();
     }
    }
    
    //Dao实现类
    @Repository
    public class UserDaoImpl implements UserDao {
        @Override
        public void add() {
            System.out.println("dao add.....");
        }
    }
    

    (2)@Qualifier:根据属性名称进行注入,这个@Qualifier 注解的使用,和上面@Autowired 一起使用

    @Autowired
    //根据名称进行注入(目的在于区别同一接口下有多个实现类,根据类型就无法选择,从而出错!)
    @Qualifier(value = "userDaoImpl1") 
    private UserDao userDao;
    

    (3)@Resource:可以根据类型注入,也可以根据名称注入

    //@Resource //根据类型进行注入
    @Resource(name = "userDaoImpl1") //根据名称进行注入
    private UserDao userDao;
    

    (4)@Value:普通类型值注入

    @Value(value = "abc")
    private String name
    
  2. 完全注解开发

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

    @Configuration //作为配置类,替代 xml 配置文件
    @ComponentScan(basePackages = {"com.yang.spring5"})
    public class SpringConfig {
        
    }
    

    (2)编写测试类

    @Test
    public void testService2() {
     //加载配置类
     ApplicationContext context
     = new AnnotationConfigApplicationContext(SpringConfig.class);
     UserService userService = context.getBean("userService",
    UserService.class);
     System.out.println(userService);
     userService.add();
    }
    

4. Bean的作用域

bean作用域是用来确定从Spring容器中返回哪种类型的bean实例给调用者。

  1. spring里配置的bean是单例还是多实例的?

    默认为单例,可进行配置 使用 scope 标签, prototype 多实例 、 singleton 单例 (默认)

    <--多实例-->
    <bean id="user" class="com.yang.spring5.User" scope="prototype"></bean>
    <--单例-->
    <bean id="user" class="com.yang.spring5.User" scope="singleton "></bean>
    
  2. scope设置prototypesingleton 的区别?

    1. singleton 单例 prototype 多实例
    2. singleton bean在配置加载的时候进行创建,prototype bean在调用getBean方法的时候创建

5. Bean的生命周期

从对象创建到对象销毁的过程(5步)

  1. 通过构造器创建 bean 实例(无参数构造)

  2. 为 bean 的属性设置值和对其他 bean 引用(调用 set 方法)

  3. 调用 bean 的初始化的方法(需要进行配置初始化的方法,调用init方法)

  4. bean 可以使用了(对象获取到了,调用getBean方法)

  5. 当容器关闭时候,调用 bean 的销毁的方法(需要进行配置销毁的方法,调用destroy方法)

代码示例

package com.yang.spring5.bean;

/**
 * @Description: 订单
 * @author: caoshenyang
 * @date: 2021.01.04
 */
public class Order {
    private String name;

    public Order() {
        System.out.println("第一步 执行无参构造方法创建 bean 实例");
    }

    public void setName(String name) {
        this.name = name;
        System.out.println("第二步 调用setter方法设置属性值");
    }

    public void initMethod(){
        System.out.println("第三步 执行初始化方法");
    }

    public void destroyMethod(){
        System.out.println("第五步 执行销毁方法");
    }
}
<?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="order" class="com.yang.spring5.bean.Order" init-method="initMethod" destroy-method="destroyMethod">
        <property name="name" value="手机"/>
    </bean>
</beans>
@Test
public void testAdd() {
    //1 加载spring配置文件
    ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("bean9.xml");
    //2 获取配置创建的对象
    Order order = context.getBean("order", Order.class);
    System.out.println("第四步 获取创建bean实例对象");
    System.out.println(order);

    context.close();
}

输出:

第一步 执行无参构造方法创建 bean 实例
第二步 调用setter方法设置属性值
第三步 执行初始化方法
第四步 获取创建bean实例对象
com.yang.spring5.bean.Order@ed9d034
第五步 执行销毁方法

添加bean的后置处理器(bean的生命周期为7步)

  1. 创建后置处理器类,需要实现BeanPostProcessor接口
  2. 配置后置处理器
package com.yang.spring5.bean;

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

/**
 * @Description: 后置处理器
 * @author: caoshenyang
 * @date: 2021.01.04
 */
public class MyBeanPostProcessor implements BeanPostProcessor {

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("在初始化之前执行的方法");
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("在初始化之后执行的方法");
        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="order" class="com.yang.spring5.bean.Order" init-method="initMethod" destroy-method="destroyMethod">
        <property name="name" value="手机"/>
    </bean>
    <!--配置后置处理器-->
    <bean id="myBeanPostProcessor" class="com.yang.spring5.bean.MyBeanPostProcessor"></bean>
</beans>
@Test
public void testAdd() {
    //1 加载spring配置文件
    ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("bean9.xml");
    //2 获取配置创建的对象
    Order order = context.getBean("order", Order.class);
    System.out.println("第四步 获取创建bean实例对象");
    System.out.println(order);

    context.close();
}

输出:

第一步 执行无参构造方法创建 bean 实例
第二步 调用setter方法设置属性值
在初始化之前执行的方法
第三步 执行初始化方法
在初始化之后执行的方法
第四步 获取创建bean实例对象
com.yang.spring5.bean.Order@4eb7f003
第五步 执行销毁方法

6. 引入外部属性文件

下面以配置数据库连接作为示例。

  • 方式一:直接配置数据库信息
  1. 引入Druid连接池依赖
  2. 配置连接池
<!-- https://mvnrepository.com/artifact/com.alibaba/druid -->
<dependency>
  <groupId>com.alibaba</groupId>
  <artifactId>druid</artifactId>
  <version>1.2.4</version>
</dependency>
<!--直接配置连接池-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
  <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
  <property name="url" value="jdbc:mysql://localhost:3306/userDb"></property>
  <property name="username" value="root"></property>
  <property name="password" value="root"></property>
</bean>
  • 方式二:引入外部属性文件配置数据库连接池
  1. 创建外部属性文件,properties类型文件(jdbc.properties)
  2. 写数据库信息
  3. 引入到Spring配置文件中
    1. 设置context名称空间
    2. 引入数据
prop.driverClass=com.mysql.jdbc.Driver
prop.url=jdbc:mysql://localhost:3306/userDb
prop.userName=root
prop.password=root
<?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"/>

    <!--配置连接池-->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="${prop.driverClass}"></property>
        <property name="url" value="${prop.url}"></property>
        <property name="username" value="${prop.userName}"></property>
        <property name="password" value="${prop.password}"></property>
    </bean>
</beans>
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,390评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,821评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,632评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,170评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,033评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,098评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,511评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,204评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,479评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,572评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,341评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,213评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,576评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,893评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,171评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,486评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,676评论 2 335

推荐阅读更多精彩内容