快速梳理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框架内)

    
        org.springframework
        spring-core
        5.2.9.RELEASE
    
    
        org.springframework
        spring-context
        5.2.9.RELEASE
    
    
        org.springframework
        spring-aop
        5.2.9.RELEASE
    
    
        org.springframework
        spring-expression
        5.2.9.RELEASE
    
    
        commons-logging
        commons-logging
        1.2
    
    
  1. 创建一个普通类,在这个类创建普通方法

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

    • Spring配置文件使用xml
    • 创建bean1.xml
    
    
    
        
        
    
    
  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配置文件,配置要创建的对象
    
    
    
    • 第二步 创建工厂类,通过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标签,标签里添加对应属性,就可以实现对象创建。


  • 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配置文件中,配置对象创建和属性注入
    
    
        
        
    
    
    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配置文件中,配置对象创建和属性注入
    
    
        
        
    
    
    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. 配置对象创建和属性注入
    
    
    
      
      
      
    
    
    
  • 特殊类型值注入
    • null
    
    
    
     
     
         
     
    
    
    • 特殊符号
    
    
    
    
        
        
            >]]>
        
    
    
  • 注入属性-外部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....");
        }
    }
    
    
    
    
        
            
            
            
            
        
        
    
    
    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 +
                    '}';
        }
    }
    
    
    
    
        
            
            
            
            
            
                
                    
                
            
        
    
    
    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部门'}}
    

    级联赋值

    
    
    
        
            
            
            
            
             
            
            
        
        
    
    
    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 lists;
    
        private Map maps;
    
        private Set sets;
    
        public void setCourse(String[] course) {
            this.course = course;
        }
    
        public void setLists(List lists) {
            this.lists = lists;
        }
    
        public void setMaps(Map maps) {
            this.maps = maps;
        }
    
        public void setSets(Set sets) {
            this.sets = sets;
        }
    
        @Override
        public String toString() {
            return "Student{" +
                    "course=" + Arrays.toString(course) +
                    ", lists=" + lists +
                    ", maps=" + maps +
                    ", sets=" + sets +
                    '}';
        }
    }
    
    
    
    
        
            
                
                    语文
                    数学
                
            
            
                
                    JAVA
                    C语言
                
            
            
                
                    
                    
                
            
            
                
                    C++
                    C#
                
            
        
    
    

    输出:

    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 courses;
    
        public void setCourses(List 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 + '\'' +
                    '}';
        }
    }
    
    
    
    
        
            
                
                    
                    
                
            
    
        
    
        
            
        
        
            
        
    
    

    输出:

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




    
        
        
    

    
        
    

    
        
    
    
        
    

输出:

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



   

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依赖

    
        org.springframework
        spring-aop
        5.2.9.RELEASE
    
    

    (2)开启注解扫描

    
    
    
        
        
    
    

    (3)创建类,加上注解

    //在注解里面 value 属性值可以省略不写,
    //默认值是类名称,首字母小写
    //StudentService -- studentService
    @Service(value = "studentService") //注解等同于XML配置文件:
    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. 基于注解方式实现属性注入

    (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 单例 (默认)

    <--多实例-->
    
    <--单例-->
    
    
  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("第五步 执行销毁方法");
    }
}



    
        
    

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



    
        
    
    
    

@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. 配置连接池


  com.alibaba
  druid
  1.2.4



  
  
  
  

  • 方式二:引入外部属性文件配置数据库连接池
  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



    
    

    
    
        
        
        
        
    

你可能感兴趣的:(快速梳理Spring知识点 - IOC)