zoukankan      html  css  js  c++  java
  • spring容器、BeanFactory、ApplicatContext、WebApplicationContext

    1、BeanFactory接口

    package org.springframework.beans.factory;
    
    import org.springframework.beans.BeansException;
    import org.springframework.core.ResolvableType;
    
    public interface BeanFactory {
        String FACTORY_BEAN_PREFIX = "&";
        // getBean()方法从容器中返回Bean
        Object getBean(String var1) throws BeansException;
    
        <T> T getBean(String var1, Class<T> var2) throws BeansException;
    
        Object getBean(String var1, Object... var2) throws BeansException;
    
        <T> T getBean(Class<T> var1) throws BeansException;
    
        <T> T getBean(Class<T> var1, Object... var2) throws BeansException;
        // 容器里有没有一个Bean
        boolean containsBean(String var1);
        // 一个Bean是不是单例的
        boolean isSingleton(String var1) throws NoSuchBeanDefinitionException;
        // 一个Bean是不是复例的
        boolean isPrototype(String var1) throws NoSuchBeanDefinitionException;
    
        boolean isTypeMatch(String var1, ResolvableType var2) throws NoSuchBeanDefinitionException;
    
        boolean isTypeMatch(String var1, Class<?> var2) throws NoSuchBeanDefinitionException;
    
        Class<?> getType(String var1) throws NoSuchBeanDefinitionException;
    
        String[] getAliases(String var1);
    }
    View Code

    BeanFactory的子接口ListableBeanFactory

    package org.springframework.beans.factory;
    
    import java.lang.annotation.Annotation;
    import java.util.Map;
    import org.springframework.beans.BeansException;
    import org.springframework.core.ResolvableType;
    
    public interface ListableBeanFactory extends BeanFactory {
        // BeanDefinition
        boolean containsBeanDefinition(String var1);
        // BeanDefinition
        int getBeanDefinitionCount();
        // BeanDefinition
        String[] getBeanDefinitionNames();
    
        String[] getBeanNamesForType(ResolvableType var1);
    
        String[] getBeanNamesForType(Class<?> var1);
    
        String[] getBeanNamesForType(Class<?> var1, boolean var2, boolean var3);
    
        <T> Map<String, T> getBeansOfType(Class<T> var1) throws BeansException;
    
        <T> Map<String, T> getBeansOfType(Class<T> var1, boolean var2, boolean var3) throws BeansException;
    
        String[] getBeanNamesForAnnotation(Class<? extends Annotation> var1);
    
        Map<String, Object> getBeansWithAnnotation(Class<? extends Annotation> var1) throws BeansException;
    
        <A extends Annotation> A findAnnotationOnBean(String var1, Class<A> var2) throws NoSuchBeanDefinitionException;
    }
    View Code

    BeanFactory的子接口HierarchicalBeanFactory  [ˌhaɪəˈrɑːkɪkl] 

    通过这个接口Spring的IoC容器可以建立父子层级关联的容器体系,子容器可以访问父容器中的Bean,但父容器不能访问子容器中的Bean。

    package org.springframework.beans.factory;
    
    public interface HierarchicalBeanFactory extends BeanFactory {
        // 获得父级的BeanFactory
        BeanFactory getParentBeanFactory();
    
        boolean containsLocalBean(String var1);
    }
    View Code

    AutowireCapableBeanFactory接口

    定义了自动装配

    DefaultSingletonBeanRegistry接口

    DefaultSingletonBeanRegistry里有一个addSingleton()方法,会把单例的Bean保存到一个ConcurrentHashMap

        // 缓存到一个map里
        private final Map<String, Object> singletonObjects = new ConcurrentHashMap(256); 
    
        protected void addSingleton(String beanName, Object singletonObject) {
            Map var3 = this.singletonObjects;
            synchronized(this.singletonObjects) {
                // 添加单对象到map
                this.singletonObjects.put(beanName, singletonObject != null ? singletonObject : NULL_OBJECT);
                this.singletonFactories.remove(beanName);
                this.earlySingletonObjects.remove(beanName);
                this.registeredSingletons.add(beanName);
            }
        }
    View Code

    DefaultListableBeanFactory 实现类

    这个类实现了上面所有的接口

    <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="tank" class="my.Tank"></bean>
    
    </beans>
    View Code
    package my;
    
    import org.springframework.beans.factory.support.DefaultListableBeanFactory;
    import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
    import org.springframework.core.io.Resource;
    import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
    
    import java.io.IOException;
    
    public class MyTest {
        public static void main(String[] args) throws IOException {
            // 创建一个资源加载器
            PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
            // 使用ClassPathResource加载配置文件
            Resource resource = resolver.getResource("classpath:my.xml");
    
            // 创建一个BeanFactory的对象
            DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
            XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);
            reader.loadBeanDefinitions(resource);
    
            // 单例的Bean已经缓存到容器中
            Tank tank = (Tank)factory.getBean(Tank.class);
            tank.run();
        }
    }
    class Tank {
        public void run() {
            System.out.println("run...");
        }
    }
    View Code

    2、ApplicatContext接口 

    public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory,
            MessageSource, ApplicationEventPublisher, ResourcePatternResolver {}

    ApplicationContext继承了ListableBeanFactory、HierarchicalBeanFactory,另外还通过其它几个接口扩展了BeanFactory的功能。

    ApplicationEventPublisher让spring容器拥有发布事件的功能,包括spring容器启动、关闭。ApplicationContext基于Observer模式(java.util包中有对应实现),提供了针对Bean的事件传播功能。事件传播的一个典型应用是,当Bean中的操作发生异常(如数据库连接失败),则通过事件传播机制通知异常监听器进行处理。

    ResourcePatternResolver,所有的ApplicationContext实现类都实现了类似于PathMatchingResourcePatternResolver的功能,可以通过文件路径装载spring配置文件。

    import org.springframework.beans.factory.support.DefaultListableBeanFactory;
    import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.annotation.AnnotationConfigApplicationContext;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    import org.springframework.core.io.Resource;
    import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
    
    import java.io.IOException;
    
    public class MyTest {
        public static void main(String[] args) throws IOException {
            // 使用ClassPathXmlApplicationContext可以省略路径字符串的classpath前缀
            ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath:my.xml");
            //AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class);
            Tank tank = context.getBean(Tank.class);
    
            tank.run();
        }
    }
    class Tank {
        public void run() {
            System.out.println("run...");
        }
    }
    @Configuration
    class MyConfig{
        @Bean
        public Tank tank() {
            return new Tank();
        }
    }
    View Code
    <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="tank" class="my.Tank"></bean>
    
    </beans>
    View Code

    3、WebApplicationContext 

    WebApplicationContext是专门为web应用准备的。

    WebApplicationContext源码:

    package org.springframework.web.context;
    
    import javax.servlet.ServletContext;
    import org.springframework.context.ApplicationContext;
    
    public interface WebApplicationContext extends ApplicationContext {
        /**
         *  WebApplicationContext作为属性保存到了ServletContext中,Spring为此专门提供了一个工具类WebApplicationContextUtils,
         *  通过该类的getWebApplicationContext(ServletContext sc)方法,可以从ServletContext中获取WebApplicationContext的实例。
         *
         *  常量ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE是在ServletContext中保存WebApplicationContext的key
         *  可以通过以下方法获得WebApplicationContext的实例
         *  WebApplicationContext context = 
         *  (WebApplicationContext)servletContext.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
         *
         *  这也正是WebApplicationContextUtils的getWebApplicationContext(ServletContext sc)方法的内部实现方式。
         */
        String ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE = WebApplicationContext.class.getName() + ".ROOT";
        /**
         * 在非web应用的环境下,Bean只有singleton和prototype两种作用域。
         * WebApplicationContext为Bean添加了三个新的作用域:
         * 分别是request、sesseion和global sesseion。
         */
        String SCOPE_REQUEST = "request";
        String SCOPE_SESSION = "session";
        String SCOPE_GLOBAL_SESSION = "globalSession";
        String SCOPE_APPLICATION = "application";
        String SERVLET_CONTEXT_BEAN_NAME = "servletContext";
        String CONTEXT_PARAMETERS_BEAN_NAME = "contextParameters";
        String CONTEXT_ATTRIBUTES_BEAN_NAME = "contextAttributes";
        // 也可以WebApplicationContext中获取ServletContext
        ServletContext getServletContext();
    }

     ConfigurableWebApplicationContext源码:

    package org.springframework.web.context;
    
    import javax.servlet.ServletConfig;
    import javax.servlet.ServletContext;
    import org.springframework.context.ConfigurableApplicationContext;
    
    public interface ConfigurableWebApplicationContext extends WebApplicationContext, ConfigurableApplicationContext {
        String APPLICATION_CONTEXT_ID_PREFIX = WebApplicationContext.class.getName() + ":";
    
        String SERVLET_CONFIG_BEAN_NAME = "servletConfig";
    
        void setServletContext(ServletContext var1);
    
        void setServletConfig(ServletConfig var1);
    
        ServletConfig getServletConfig();
    
        void setNamespace(String var1);
    
        String getNamespace();
        // 设置配置文件地址,允许通过配置文件实例化WebApplicationContext
        void setConfigLocation(String var1);
    
        void setConfigLocations(String... var1);
    
        String[] getConfigLocations();
    }

    XmlWebApplicationContext、AnnotationConfigWebApplicationContext这两个类都实现了上面的接口

    但WebApplicationContext的初始化方式和BeanFactory、ApplicationContext不一样,因为它们必须在拥有Web容器的前提下才能启动。使用XmlWebApplicationContext或AnnotationConfigWebApplicationContext实例化WebApplicationContext需要在web.xml中定义监听器ContextLoaderListener。ContextLoaderListener通过ServletContext参数contextConfigLocation获取Spring配置文件的位置,用户可以指定多个配置文件,用逗号、空格或冒号分隔均可。 

    package com.test;
    
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.web.context.WebApplicationContext;
    
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    
    @WebServlet("/run")
    public class MyTest extends HttpServlet {
        private Tank tank;
    
        public void setTank(Tank tank) {
            this.tank = tank;
        }
    
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            WebApplicationContext context = (WebApplicationContext) req.getServletContext().getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
            MyTest myTest = context.getBean(MyTest.class);
            myTest.tank.run();
        }
    }
    class Tank {
        public void run() {
            System.out.println("run ...");
        }
    }
    @Configuration
    class MyConfig {
        // 这个方法随便声明、方法参数随便写,因为这是一个新的方法,在这个方法的内部调用其它方法
        @Bean
        public MyTest myTest(Tank tank) {
            MyTest myTest = new MyTest();
            myTest.setTank(tank);
            return myTest;
        }
        @Bean
        public Tank tank() {
            return new Tank();
        }
    }
    View Code
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:p="http://www.springframework.org/schema/p"
           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="tank" class="com.test.Tank"/>
    
        <bean id="myTest" class="com.test.MyTest" p:tank-ref="tank"/>
    
    </beans>
    View Code
    <!DOCTYPE web-app PUBLIC
     "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
     "http://java.sun.com/dtd/web-app_2_3.dtd" >
    <web-app>
      <display-name>spring-demo</display-name>
      <!--让spring使用AnnotationConfigWebApplicationContext而非XmlWebApplicationContext启动容器
          如果想使用XmlWebApplicationContext,不需要下面这个<context-param>的配置
      -->
      <!--<context-param>-->
        <!--<param-name>contextClass</param-name>-->
        <!--<param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>-->
      <!--</context-param>-->
      <context-param>
        <param-name>contextConfigLocation</param-name>
        <!--<param-value>com.test.MyConfig</param-value>-->
        <param-value>classpath:/my.xml</param-value>
      </context-param>
      <listener>
      <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
      </listener>
    </web-app>
    View Code
    <?xml version="1.0" encoding="UTF-8"?>
    
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
      <modelVersion>4.0.0</modelVersion>
    
      <groupId>com.test.spring</groupId>
      <artifactId>spring-demo</artifactId>
      <version>1.0-SNAPSHOT</version>
      <packaging>war</packaging>
    
      <name>spring-demo</name>
    
      <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.7</maven.compiler.source>
        <maven.compiler.target>1.7</maven.compiler.target>
      </properties>
    
      <dependencies>
        <dependency>
          <groupId>junit</groupId>
          <artifactId>junit</artifactId>
          <version>4.11</version>
          <scope>test</scope>
        </dependency>
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-core</artifactId>
          <version>4.3.16.RELEASE</version>
        </dependency>
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-context</artifactId>
          <version>4.3.16.RELEASE</version>
        </dependency>
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-beans</artifactId>
          <version>4.3.16.RELEASE</version>
        </dependency>
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-web</artifactId>
          <version>4.3.16.RELEASE</version>
        </dependency>
        <dependency>
          <groupId>javax.servlet</groupId>
          <artifactId>jstl</artifactId>
          <version>1.2</version>
        </dependency>
        <dependency>
          <groupId>javax.servlet</groupId>
          <artifactId>javax.servlet-api</artifactId>
          <version>3.1.0</version>
          <scope>provided</scope>
        </dependency>
        <dependency>
          <groupId>javax.servlet.jsp</groupId>
          <artifactId>javax.servlet.jsp-api</artifactId>
          <version>2.2.1</version>
          <scope>provided</scope>
        </dependency>
      </dependencies>
    
      <build>
        <finalName>spring-demo</finalName>
        <plugins>
          <plugin>
            <groupId>org.apache.tomcat.maven</groupId>
            <artifactId>tomcat7-maven-plugin</artifactId>
            <version>2.2</version>
            <configuration>
              <path>/</path>
              <port>80</port>
              <uriEncoding>UTF-8</uriEncoding>
              <server>tomcat7</server>
            </configuration>
          </plugin>
        </plugins>
        <pluginManagement>
          <plugins>
            <plugin>
              <artifactId>maven-clean-plugin</artifactId>
              <version>3.1.0</version>
            </plugin>
            <plugin>
              <artifactId>maven-resources-plugin</artifactId>
              <version>3.0.2</version>
            </plugin>
            <plugin>
              <artifactId>maven-compiler-plugin</artifactId>
              <version>3.8.0</version>
            </plugin>
            <plugin>
              <artifactId>maven-surefire-plugin</artifactId>
              <version>2.22.1</version>
            </plugin>
            <plugin>
              <artifactId>maven-war-plugin</artifactId>
              <version>3.2.2</version>
            </plugin>
            <plugin>
              <artifactId>maven-install-plugin</artifactId>
              <version>2.5.2</version>
            </plugin>
            <plugin>
              <artifactId>maven-deploy-plugin</artifactId>
              <version>2.8.2</version>
            </plugin>
          </plugins>
        </pluginManagement>
      </build>
    </project>
    View Code
  • 相关阅读:
    Linux启动或禁止SSH用户及IP的登录,只允许密钥验证登录模式
    emacs 入门教程,菜单汉化,配置文件等杂乱文章
    bzoj3376/poj1988[Usaco2004 Open]Cube Stacking 方块游戏 — 带权并查集
    NOIP复习篇
    HiHocoder 1036 : Trie图 AC自动机
    (皇后移动类)八数码难题引发的搜索思考及总结
    POJ 水题(刷题)进阶
    [TJOI2010] 中位数
    小球和盒子的问题
    [洛谷P2785] 物理1(phsic1)-磁通量
  • 原文地址:https://www.cnblogs.com/Mike_Chang/p/10261122.html
Copyright © 2011-2022 走看看