IOC容器小结

2021/7/17 6:06:58

本文主要是介绍IOC容器小结,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

IOC 容器

一. IOC 底层原理

使用工厂模式+反射+xml的方式达到解耦合的目的,它们就是 IOC 的底层原理。 IOC 容器底层就是对象工厂。

Spring 提供两种 IOC 容器实现方法(两个接口):

  • BeanFactory:IOC 容器基本实现,是 Spring 内部的使用接口,不推荐使用
  • ApplicationContext:是 BeanFactory 子接口,提供更多更强大的功能

区别:BeanFactory 加载配置文件时不会创建对象,在获取对象时才创建(懒汉模式)。ApplicationContext 一加载配置文件就创建。由于Spring 通常用于 WEB,因此第二种在启动服务器时就先创建好对象可以使后续访问更流畅,所以一开始就加载更好。

BeanFactory 有两个实现类:

  • FileSystemXmlApplicationContext,传入磁盘的全路径
  • ClassPathXmlApplicationContext,传入 src 目录下的路径

二. Bean 管理

Bean 管理包括创建对象注入属性

1. 基于 xml 文件

创建对象

默认通过无参构造方法创建

注入基本属性

  • 方法一:使用 set 方法注入

    类里必须有 set 方法

    <bean id="book" class="com.abc.Book">
        <property name="bname" value="hhh"/>
    </bena>
    
  • 方法二:基于有参构造注入

    类里必须有有参构造方法,不必有无参构造方法

    <bean id="book" class="com.abc.Book">
        <constructor-arg name="bname" value="hhh"/>
        <constructor-arg index="0" value="hhh"/>  通过索引注入
    </bean>
    

特殊值注入:

  • 注入 null

    <property name="address">
        <null/>
    </property>
    
  • 包含特殊符号

    1. 使用转义字符,如&amp; &lt; &gt;

    2. 使用 CDATA

      <property name="address">
          <value><![CDATA[<<南京>>]]></value>
      </property>
      

注入外部 bean

<bean id="uesrService" class="com.service.UserService">
    <property name="userDao" ref="userDaoImpl"/>
</bean>
<bean id="uesrDaoImpl" class="com.dao.UserDaoImpl"/>

注入内部 bean

<bean id="uesrService" class="com.service.UserService">
    <property name="userDao">
    	<bean id="userDaoImpl" class="com.dao.UserDaoImpl"/>
    </property>
</bean>

注入集合属性

<bean id="student" class="com.pojo.Student">
    <!--数组类型-->
    <property name="courses">
    	<array>
    		<value>java课程</value>
    		<value>数据库课程</value>
		</array>
	</property>
    
    <!--List类型-->
    <property name="list">
    	<list>
        	<value>张三</value>
        	<value>小三</value>
        </list>
    </property>
    
    <!--map类型-->
    <property name="maps">
    	<map>
        	<entry key="JAVA" value="java"/>
        	<entry key="PHP" value="php"/>
        </map>
    </property>
</bean>
集合中存放对象
<bean id="Student" class="com.pojo.Student">
	<property name="courseList">
    	<list>
        	<ref bean="course1"/>
            <ref bean="course2"/>
        </list>
    </property>
</bean>

<bean id="course1" class="com.pojo.Course">
	<property name="cname" value="Spring5"/>
</bean>
<bean id="course2" class="com.pojo.Course">
	<property name="cname" value="MyBatis"/>
</bean>
提取出公共部分

先引入 util 命名空间

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

    <!--提取 list 集合类型属性-->
	<util:list id="bookList">
	    <value>易筋经</value>
        <value>九阳真经</value>
	</util:list>

    <bean id="book" class="com.pojo.Book">
        <property name="list" ref="bookList"/>
    </bean>                     
</beans>

自动装配

实际用的不多,都是用注解

byName 根据属性名称注入,注入的 bean 的 id 值要求和类属性名称一样

byType 根据属性类型注入,要求只能定义一个相同类型的 bean

<bean id="emp" class="com.pojo.Emp" autowire="byType"/>

引入外部属性文件

须引入context 命名空间

<context:property-placeholder location="a.property"/>

2. 基于注解

  • @Component
  • @Service
  • @Controller
  • @Repository

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

步骤

  • 引入依赖

spring-aop-5.2.6.RELEASE.jar

  • 开启组件扫描

首先要引入 context 名称空间

xmlns:context="http://www.springframework.org/schema/context"
http://www.springframework.org/schema/context                https://www.springframework.org/schema/context/spring-context.xsd

<!--扫描多个包,逗号隔开-->
<context:component-scan base-package="com.pojo,com.dao"/>

<!--只扫描 Controller 注解-->
<context:component-scan base-package="com.kuang.controller" use-default-filters="false">
    <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
    
<!--除了 Controller 注解都扫描-->
<context:component-scan base-package="com.pojo">
    <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
  • 在类上添加注解
package com.service;

import org.springframework.stereotype.Service;

// 如果不写 value 值,则默认 id 为类名,其中首字母小写
@Service("userService")
public class UserService {
}

属性注入

  • @AutoWired:根据属性类型进行注入
  • @Qualifier:根据属性名称进行注入
  • @Resource:可以根据名称也可以根据类型注入
  • @Value:注入基本类型属性

注解注入不依靠 set 方法

@Service("userService")
public class UserService {

    @Autowired
    private UserDao userDao;

    public UserDao getUserDao() {
        return userDao;
    }
}
package com.dao;

import org.springframework.stereotype.Repository;

@Repository
public class UserDaoImpl implements UserDao{

    @Override
    public void add() {
        System.out.println("hhh");
    }
}

@Qualifier 通常和 @Autowired 一起使用

  • @Resource 根据类型注入
  • @Resource(name="name") 根据名字注入
@Value("abc")
private String name;

完全注解开发

package com.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

// 作为配置类替代 xml 文件
@Configuration
@ComponentScan(basePackages = {"com.pojo"})
public class SpringConfig {
}
public class MyTest {
    @Test
    public void dest() {
        ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
        UserService service = context.getBean("userService", UserService.class);
    }
}

3. FactoryBean(工厂 bean)

Spring 有两种类型的 bean,一种普通 bean,一种工厂 bean。

普通 bean 中定义的类型就是返回类型,而工厂 bean 可以和返回类型不一样。

package com.pojo;

import org.springframework.beans.factory.FactoryBean;

public class MyBean implements FactoryBean<Course> {

    // 定义返回的bean
    @Override
    public Course getObject() throws Exception {
        Course course = new Course();
        course.setCname("abc");
        return course;
    }

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

    @Override
    public boolean isSingleton() {
        return false;
    }
}
<!--会返回一个 Course 类型对象-->
<bean id="myBean" class="com.pojo.MyBean"/>

4. bean 作用域

默认是单例(singleton)工厂,可以通过 scope 属性设置

scope=prototype 是多实例

5. bean 生命周期

  1. 创建 bean 实例
  2. 为 bean 的属性设置值和对其他 bean 的引用(set 方法)
  3. 调用 bean 的初始化方法
  4. 使用 bean
  5. 容器关闭时,调用 bean 销毁方法
package com.pojo;

public class Order {

    private String oname;

    // 第一步
    public void Order(){};
    
    // 第二步
    public void setOname(String oname) {
        this.oname = oname;
    }

    public void initMethod() {
        System.out.println("第三步");
    }
    
    public void destoryMethod() {
        System.out.println("第五步");
    }
}
<!--第三、五步的初始化方法用 init-method、destory-method 参数配置-->
<bean id="order" class="com.pojo.Order" init-method="initMethod" destory-method="destory-method"/>

如果引入后置处理器就会在第三步前后各插入一步,变成七步



这篇关于IOC容器小结的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程