spring相关知识理解之IOC

本文介绍了Spring5框架的核心组成部分——IOC,包括其概念、目的、底层原理和实现方式。详细阐述了IOC容器的BeanFactory和ApplicationContext接口,以及IOC的三种注入方式:set方法注入、构造器注入和p名称空间注入。此外,还讨论了Bean的作用域、生命周期、BeanPostProcessor以及XML和注解方式的自动装配。文章通过实例展示了如何使用注解实现对象创建和属性注入。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1,Spring5 框架

1,Spring5 框架概述

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

2,测试通过spring创建一个类

  1. 导入spring需要的基础包

  2. 创建spring配置的xml文件

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    
        <bean id="user" class="com.hanlin.User"></bean>
    </beans>
    
  3. 测试从xml配置文件中获取到配置的对象进行输出

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

#2,IOC容器

1,什么是IOC

  1. 控制反转:把对象的创建和对象之间的调用过程,交给spring容器进行管理
  2. 使用IOC的目的:降低代码的耦合度

###2,IOC容器底层原理

  1. 涉及到的技术:xml文件解析,工厂模式,反射技术
  2. IOC 思想基于 IOC 容器完成,IOC 容器底层就是对象工厂

###3,IOC容器接口(BeanFactory,ApplicationContext)

  1. BeanFactory:IOC 容器基本实现,是 Spring 内部的使用接口,不提供开发人员进行使用 加载配置文件时候不会创建对象,在获取对象(使用)才去创建对象
  2. ApplicationContext:BeanFactory 接口的子接口,提供更多更强大的功能,一般由开发人 员进行使用

4,IOC三种注入方式

####1,第一种注入方式:使用 set 方法进行注入

//第一步,先创建一个需要注入到IOC容器中的对象
/**
 * Bean 管理操作基于 xml 配置文件方式实现
 * 1、基于 xml 方式创建对象
 * (1)在 spring 配置文件中,使用 bean 标签,标签里面添加对应属性,就可以实现对象创建
 * (2)在 bean 标签有很多属性,介绍常用的属性
 *  id 属性:唯一标识
 *  class 属性:类全路径(包类路径)
 * (3)创建对象时候,默认也是执行无参数构造方法完成对象创建
 * 2、基于 xml 方式注入属性
 *   第一种注入方式:使用 set 方法进行注入
 */
public class Person {
    private String id;
    private String name;

    public void setId(String id){
        this.id=id;
    }

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

    public void testPerson(){
        System.out.println(id+":"+name);
    }
}

//第二步:在xml配置文件中配置对象和对象属性的信息
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="user" class="com.hanlin.java.User"></bean>

    <bean id="person" class="com.hanlin.java.Person">
        <property name="id" value="中国人"></property>
        <property name="name" value="牛逼"></property>
    </bean>
</beans>
        
//第三步:测试将注入到IOC容器的中对象和对象的属性获取打印
@Test
    public void testPerson(){
        //1,加载spring配置文件
        ApplicationContext context = new ClassPathXmlApplicationContext("beandem1.xml");
        //2,获取配置文件中创建的对象
        Person p1 = context.getBean("person", Person.class);
        System.out.println(p1);
        p1.testPerson();
    }        

####2,第二种注入方式:使用有参数构造进行注入

//第一步,先创建一个需要注入到IOC容器中的对象
/**
 * 第二种注入方式:使用有参数构造进行注入
 */
public class Order {

    private String id;
    private String name;

    public Order(String id, String name) {
        this.id = id;
        this.name = name;
    }

    public void testOrder(){
        System.out.println(id+"::"+name);
    }
}
//第二步:在xml配置文件中配置对象和对象属性的信息
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="user" class="com.hanlin.java.User"></bean>

    <!--set方法注入-->
    <bean id="person" class="com.hanlin.java.Person">
        <property name="id" value="中国人"></property>
        <property name="name" value="牛逼"></property>
    </bean>

    <!--有参构造方法注入-->
    <bean id="order" class="com.hanlin.java.Order">
        <constructor-arg name="id" value="11"></constructor-arg>
        <constructor-arg name="name" value="222"></constructor-arg>
    </bean>
</beans>
//第三步:测试将注入到IOC容器的中对象和对象的属性获取打印
  @Test
    public void testOrder(){
        //1,加载spring配置文件
        ApplicationContext context = new ClassPathXmlApplicationContext("beandem1.xml");
        //2,获取配置文件中创建的对象
        Order order = context.getBean("order", Order.class);
        System.out.println(order);
        order.testOrder();
    }        

####3,p 名称空间注入(了解)

  • 使用 p 名称空间注入,可以简化基于 xml 配置方式 第一步 添加 p 名称空间在配置文件中

在这里插入图片描述

###5,IOC 操作 Bean 管理

####1,普通 bean:在配置文件中定义 bean 类型就是返回类型

####2,工厂* bean:在配置文件定义 bean 类型可以和返回类型不一样

  • 第一步 创建类,让这个类作为工厂 bean,实现接口 FactoryBean

  • 第二步 实现接口里面的方法,在实现的方法中定义返回的 bean 类型

    package com.hanlin.java;
    
    import org.springframework.beans.factory.FactoryBean;
    
    /**
     * 自定义工厂Bean
     * 工厂 bean:在配置文件定义 bean 类型可以和返回类型不一样
     * 1,第一步 创建类,让这个类作为工厂 bean,实现接口 FactoryBean
     * 2,第二步 实现接口里面的方法,在实现的方法中定义返回的 bean 类型
     */
    public class MyFactoryBean implements FactoryBean {
        /**
         * 定义返回bean对象的类型
         * @return
         * @throws Exception
         */
        @Override
        public Object getObject() throws Exception {
            return null;
        }
    
        @Override
        public Class<?> getObjectType() {
            return null;
        }
    
        @Override
        public boolean isSingleton() {
            return false;
        }
    }
    
    

####3,Bean的作用域

  • 在Spring中,默认情况下,bean是单例bean
  • scope 属性值 :默认值,singleton,表示是单实例对象;prototype,表示是多实例对象

####4,bean 生命周期

  • 对象从创建到销毁的过程

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

  • 把 bean 实例传递 bean 后置处理器的方法 postProcessBeforeInitialization

  • 调用 bean 的初始化的方法(需要进行配置初始化的方法)

  • bean 实例传递 bean 后置处理器的方法 postProcessAfterInitialization

  • bean 可以使用了(对象获取到了)

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

    bean生周期代码如下:

    1. 创建对象Order1
    public class Order1 {
    
        private String name;
    
        public Order1() {
            System.out.println("第一步:执行无参构造创建对象!!");
        }
    
        public void setName(String name){
            this.name=name;
            System.out.println("第二步:调用set方法设置属性");
        }
    
        public void initialize(){
            System.out.println("第三步:执行初始化方法");
        }
    
        public void destroyMethod(){
            System.out.println("第五步:执行销毁方法");
        }
    }
    
    1. 创建bean后置处理器

      /**
       * 创建bean的后置处理器
       */
      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;
          }
      }
      
    2. xml文件配置对象(包括初始化方法,销毁方法,bean对象和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="order1" class="com.hanlin.java.Order1" init-method="initialize" destroy-method="destroyMethod">
              <property name="name" value="电话"></property>
          </bean>
      
          <!--定义bean的后置处理器对象-->
          <bean id="myBeanPostProcessor" class="com.hanlin.java.MyBeanPostProcessor"></bean>
      </beans>
      
    3. 代码测试bean生命周期

         @Test
          public void test01(){
              //1,加载spring配置文件
              ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("order1.xml");
              //2,获取配置文件中创建的对象
              Order1 order1 = (Order1)context.getBean("order1");
              System.out.println("第四步:获取到创建的对象!");
              System.out.println(order1);
              //手动调用销毁对象方法
              context.close();
          }
      
    4. 如下图:在调用初始化方法之前和之后都会调用bean后置处理器

在这里插入图片描述

####5,BeanPostProcessor( bean 后置处理器)

/**
 * 创建bean的后置处理器,创建了bean的后置处理器之后,容器中创建所有的bean都会在初始bean之前,之后都会执行后置处理器
 */
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;
    }
}

###6,IOC 操作 Bean 管理(xml自动装配)

####1,什么是自动装配

  1. 根据指定装配规则(属性名称或者属性类型),Spring 自动将匹配的属性值进行注入

  2. 不用自己在xml文件中手动对属性进行设置

  3. 案例演示

    //将Dept对象注入到Emp对象中,按照set方法注入
    public class Emp {
    
        private Dept dept;
    
        public void setDept(Dept dept) {
            this.dept = dept;
        }
    
        @Override
        public String toString() {
            return "Emp{" +
                    "dept=" + dept +
                    '}';
        }
    
        public void test(){
            System.out.println(dept);
        }
    }
    
    public class Dept {
        @Override
        public String toString() {
            return "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 标签属性 autowire,配置自动装配
                autowire 属性常用两个值:
                byName 根据属性名称注入 ,注入值 bean 的 id 值和类属性名称一样
                byType 根据属性类型注入
        -->
        <bean id="emp" class="com.hanlin.java.autowire.Emp" autowire="byType">
    <!--        <property name="dept" ref="dept"></property>-->
        </bean>
        <bean id="dept" class="com.hanlin.java.autowire.Dept"></bean>
    </beans>
    

###7,IOC 操作 Bean 管理(基于注解方式)

####1,什么是注解

  • 注解是代码特殊标记,格式:@注解名称(属性名称=属性值, 属性名称=属性值…)
  • 使用注解,注解作用在类上面,方法上面,属性上面
  • 使用注解目的:简化 xml 配置

####2,Spring 针对 Bean 管理中创建对象提供注解

  • @Component

  • @Service

  • @Controller

  • @Repository

    上面四个注解功能是一样的,都可以用来创建 bean 实例

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

  1. 第一步 引入依赖:依赖AOP包

  2. 第二步 开启组件扫描

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:context="http://www.springframework.org/schema/context"
           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
                               http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
    
        <!--开启组件扫描
            1 如果扫描多个包,多个包使用逗号隔开
            2 扫描包上层目录
            -->
        <context:component-scan base-package="com.hanlin.java.noxml"></context:component-scan>
    </beans>
    
  3. 第三步 创建类,在类上面添加创建对象注解

    /**
     * 在注解里面 value 属性值可以省略不写,
     * 默认值是类名称,首字母小写
     */
    @Component(value = "userService") //<bean id="userService" class=".."/>
    public class UserService {
    
        public void add(){
            System.out.println("注解注入");
        }
    }
    
  4. 测试结果

        @Test
        public void test03(){
            ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("bean6.xml");
            UserService userService = context.getBean("userService", UserService.class);
            System.out.println(userService);
            userService.add();
        }
    
  5. 打印结果如下图:
    在这里插入图片描述

  6. 开启组件扫描细节配置

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

    1. @Autowired:根据属性类型进行自动装配
    2. @Qualifier:根据名称进行注入
    3. @Resource:可以根据类型注入,可以根据名称注入
    4. @Value:注入普通类型属性
  8. 完全注解开发

    1. 编写配置类,代替xml实现完全注解开发

      @Configuration //作为配置类,替代 xml 配置文件
      @ComponentScan(basePackages = {"com.hanlin"})//开启组件扫描
      public class SpringConfig {
      }
      
    2. 测试结果

          @Test
          public void test04(){
              ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
              UserService userService = context.getBean("userService", UserService.class);
              System.out.println(userService);
              userService.add();
          }
      
    3. 测试结果如下图:

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值