• spring深入学习(三)-----spring容器内幕


    之前都是说了怎么配置bean以及用法之类的,这篇博文来介绍下spring容器内幕。

    内部容器工作机制

    Spring中AbstractApplicationContext抽象类的refresh()方法是用来刷新Spring的应用上下文的。

    @Override
    public void refresh() throws BeansException, IllegalStateException {
        //初始化BeanFactory
        prepareBeanFactory(beanFactory);
        //调用工厂后处理器
        invokeBeanFactoryPostProcessors(beanFactory);
        //注册bean后处理器
        registerBeanPostProcessors(beanFactory);
        //初始化消息源
        initMessageSource();
        //初始化应用上下文事件广播器
        initApplicationEventMulticaster();
        //初始化其他特殊的bean,由具体子类实现
        onRefresh();
        //注册事件监听器
        registerListeners();
        //初始化所有单实例的bean,使用懒加载模式的bean除外
        finishBeanFactoryInitialization(beanFactory);
        //完成刷新并发布容器刷新事件
        finishRefresh();
    }

    直接看图解吧:

    使用外部属性文件

    项目中经常有很多配置,例如数据源相关数据、日志相关数据,按照习惯,大部分喜欢配置在properties文件中,那么在项目中如何使用这些属性呢?

    jdbc.properties

    jdbc.driverClassName=com.mysql.jdbc.Driver
    
    jdbc.url=jdbc:mysql://localhost/mysqldb?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=round;
    
    jdbc.username=root
    
    jdbc.password=123456

    applicationContext.xml

    <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"
      p:location="classpath:com/ty/jdbc.properties"/>
    
    <bean id="dataSource"class="org.apache.commons.dbcp.BasicDataSource"destroy-method="close">
    
      <property name="driverClassName"value="${jdbc.driverClassName}" />
    
      <property name="url" value="${jdbc.url}" />
    
      <property name="username" value="${jdbc.username}"/>
    
      <property name="password"value="${jdbc.password}" />
    
    </bean>

    不过这种写法略显麻烦,看下另外一种写法:

    <context:property-placeholder location="classpath:com/ty/jdbc.properties""/>
    <bean id="dataSource"class="org.apache.commons.dbcp.BasicDataSource"destroy-method="close">
    
      <property name="driverClassName"value="${jdbc.driverClassName}" />
    
      <property name="url" value="${jdbc.url}" />
    
      <property name="username" value="${jdbc.username}"/>
    
      <property name="password"value="${jdbc.password}" />
    
    </bean>

    注:location中的路径用“/”分隔。

    不过这种也不是很方便,来看下最推荐的写法:

    @Component
    public class DataSource() {
        @Value("${jdbc.driverClassName}")
        private String driverClassName;
        
        @Value("${jdbc.url}")
        private String url;
        
        @Value("${jdbc.username}")
        private String username;
        
        @Value("${jdbc.password}")
        private String password;
    }

    引用bean的属性值

    当一个bean需要引用另外一个bean的属性值的时候,也可以这么写:

    @Component
    public class ApplicationManager() {
        @Value("#{sysConfig.sessionTimeout}")
        private int sessionTimeout;
        
        @Value("#{sysConfig.maxTabPageNum}")
        private int maxTabPageNum;
    }

    spring容器事件

    applicationContext能够发布事件以及允许注册相应的事件监听器,事件很好理解,就是当容器中出现了什么操作的时候,比如服务器启动、关闭,各个组件需要去怎么做。事件监听器则是负责监听这个事件的发生,来看下事件体系图:

    • 事件源:事件的产生者,任何一个EventObject都必须拥有一个事件源。
    • 事件监听器注册表:容器中有很多事件监听器,事件监听器注册表就是存放所有事件监听器的容器,然后容器统一来管理此注册表。
    • 事件广播器:事件产生后,由事件广播器将事件通知给事件监听器。

    1、applicationEvent

    2、ApplicationListener

    3、事件广播器

    4、spring事件体系

    5、示例

    测试一下:

    sendMail方法中,首先创建了一个MailSendEvent,然后调用applicationContext.publishEvent(event)方法将事件发送给所有的事件监听器(内部机制就是基于事件广播器)。因为sendMail中需要用到applicationContext上下文,因此MailSender实现了ApplicationContextAware接口。另外applicationContext在初始化的时候提供了一个默认的事件广播器(用户也可自定义),然后applicationContext根据反射机制,将容器中所有实现了ApplicationListener接口的bean注册到事件监听器注册表中。

  • 相关阅读:
    在位图上写字
    删除文件到回收站中
    Blog改名字了
    [C#]强类型
    [C#] 如何选择一个目录
    [.NET]Visual Studio 2003的一个bug
    PHP句法规则详解
    php获取本地实际IP
    从0开始学编程(1)115 大致了解
    httpd2.2.21 + php5.3.8 自动安装脚本
  • 原文地址:https://www.cnblogs.com/alimayun/p/10776934.html
Copyright © 2020-2023  润新知