• 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"/>
    

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

    你只有十分努力,才能看上去毫不费力。
  • 相关阅读:
    (转).NET 多线程编程
    [WAP]WML学习笔记总结
    [计划]2010年1月的工作学习计划
    [计划]11月&12月学习与工作计划
    [HTTP]HTTP协议学习总结第一弹:RFC2616初读总结
    [培训总结]海量服务培训总结
    [随想]忙碌的2010
    Android电源管理
    Android 1.5: 飞行模式分析
    android JNI 调用
  • 原文地址:https://www.cnblogs.com/214txdy/p/15022367.html
Copyright © 2020-2023  润新知