Spring源码分析

Spring创建对象过程

  • 层次结构
  • AnnotationConfigApplicationContext
    • GenericApplicationContext 继承
      • AbstractApplicationContext 继承
        • DefaultResourceLoader 继承
        • ConfigurableApplicationContext 实现
          • ApplicationContext继承
            • EnvironmentCapable 继承
            • ListableBeanFactory 继承
              • BeanFactory 继承
            • HierarchicalBeanFactory继承
              • BeanFactory 继承
            • MessageSource 继承
            • ApplicationEventPublisher 继承
            • ResourcePatternResolver 继承
              • ResourceLoader 继承
          • Lifecycle 继承
          • Closeable 继承
        • DisposableBean 实现
      • BeanDefinitionRegistry 实现
        • AliasRegistry 继承
    • AnnotationConfigRegistry实现

具体类详解

BeanFactory
  • 这个接口得意思就是说 获取bean信息 根据名称啊 类型啊 别名啊 是否单例的 bean工厂是否包含
String FACTORY_BEAN_PREFIX = "&";
Object getBean(String name) throws BeansException;
<T> T getBean(String name, Class<T> requiredType) throws BeansException;
<T> T getBean(Class<T> requiredType) throws BeansException;
Object getBean(String name, Object... args) throws BeansException;
<T> T getBean(Class<T> requiredType, Object... args) throws BeansException;
boolean containsBean(String name);
boolean isSingleton(String name) throws NoSuchBeanDefinitionException;
boolean isPrototype(String name) throws NoSuchBeanDefinitionException;
boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException;
boolean isTypeMatch(String name, Class<?> typeToMatch) throws NoSuchBeanDefinitionException;
Class<?> getType(String name) throws NoSuchBeanDefinitionException;
String[] getAliases(String name);
ListableBeanFactory
  • 这个类看起来其实意义不大
boolean containsBeanDefinition(String beanName);
int getBeanDefinitionCount();
String[] getBeanDefinitionNames();
String[] getBeanNamesForType(ResolvableType type);
String[] getBeanNamesForType(Class<?> type);
String[] getBeanNamesForType(Class<?> type, boolean includeNonSingletons, boolean allowEagerInit);
<T> Map<String, T> getBeansOfType(Class<T> type) throws BeansException;
<T> Map<String, T> getBeansOfType(Class<T> type, boolean includeNonSingletons, boolean allowEagerInit)
		throws BeansException;
String[] getBeanNamesForAnnotation(Class<? extends Annotation> annotationType);
Map<String, Object> getBeansWithAnnotation(Class<? extends Annotation> annotationType) throws BeansException;
<A extends Annotation> A findAnnotationOnBean(String beanName, Class<A> annotationType)
		throws NoSuchBeanDefinitionException;
HierarchicalBeanFactory
  • Hierarchical 层次的意思
  • 只有设置父容器才会有
  • 子容器可以访问父容器内容,父容器访问不了子容器内容
BeanFactory getParentBeanFactory();
boolean containsLocalBean(String name);
EnvironmentCapable
  • Capable 能力的意思
  • 环境变量属性啊什么的顶级接口
  • Environment getEnvironment(); 意识就是可以获取环境的能力接口
  • Environment也是一个接口 继承PropertyResolver 意思是说不光能获取系统信息 还可以解析property
  • StandardEnvironment 看这个类就够了
MessageSource
  • Strategy interface for resolving messages, with support for the parameterization and internationalization of such messages.
  • 策略接口 国际化的 暂时先不看

ResourceLoader

  • Strategy interface for loading resources
  • 策略模式的核心个人理解是返回值是什么 Resource 那就太多了 xml 注解 file url inputStream 外部资源什么的
  • 再看PropertyResolver 这个 是不是就能对应上了 这个解析属性 这边获取xml
  • ResourceUtils 可以看下这个类 也可以根据前置判断资源类型
// classpath:
String CLASSPATH_URL_PREFIX = ResourceUtils.CLASSPATH_URL_PREFIX;
Resource getResource(String location);
ClassLoader getClassLoader();
ResourcePatternResolver
  • classpath:只会加载第一个匹配的资源,而classpath*:会加载所有匹配的资源并合并成一个集合。
String CLASSPATH_ALL_URL_PREFIX = "classpath*:";
Resource[] getResources(String locationPattern) throws IOException;
ApplicationEventPublisher
  • 事件发布 典型的监听器模式 可以发布给所有监听对象
  • 这块设计就牛逼了 本来只有 ApplicationEvent 实现这个对象的才可以收到事件 第二个方法把Object 放在PayloadApplicationEvent里面 所以就变成了ApplicationEvent
void publishEvent(ApplicationEvent event);
void publishEvent(Object event);
Lifecycle
  • 生命周期
  • The typical use case for this is to control asynchronous processing. 异步调用执行
  • This interface does not imply specific auto-startup semantics. Consider implementing {@link SmartLifecycle} for that purpose.
  • 这都属于顶级接口了 意思就是所有的bean都是有生命周期的
	void start();
	void stop();
	boolean isRunning();
Closeable
  • public void close() throws IOException;
  • 关闭看这个类就够了AbstractApplicationContext#doClose
  • 发布关闭事件 getLifecycleProcessor().onClose(); destroyBeans(); closeBeanFactory(); onClose();
ConfigurableApplicationContext
  • 这个接口就开始介入beanFactory ,后置处理器,刷新工作了
  • refresh() 这个注释告诉我们 实例化所有或根本不实例化singletons
  • getBeanFactory() Spring中大量get方法 get不到就doGet doGet不到就doCreate 典型的缓存模式
  • SPI接口
  • ApplicationListener 可以监听事件了
String CONFIG_LOCATION_DELIMITERS = ",; \t\n";
String CONVERSION_SERVICE_BEAN_NAME = "conversionService";
String LOAD_TIME_WEAVER_BEAN_NAME = "loadTimeWeaver";
String ENVIRONMENT_BEAN_NAME = "environment";
String SYSTEM_PROPERTIES_BEAN_NAME = "systemProperties";
String SYSTEM_ENVIRONMENT_BEAN_NAME = "systemEnvironment";
void setId(String id);
void setParent(ApplicationContext parent);
void setEnvironment(ConfigurableEnvironment environment);
@Override
ConfigurableEnvironment getEnvironment();
void addBeanFactoryPostProcessor(BeanFactoryPostProcessor postProcessor);
void addApplicationListener(ApplicationListener<?> listener);
void addProtocolResolver(ProtocolResolver resolver);
void refresh() throws BeansException, IllegalStateException;
void registerShutdownHook();
@Override
void close();
boolean isActive();
ConfigurableListableBeanFactory getBeanFactory() throws IllegalStateException;
  • 理解一下registerShutdownHook()方法的操作(Connection conn相关信息删除效果也一样)
  • 现象:The main thread ends execution. 这行打印完了 Database connection closed!继续打印出来了
  • 这个是向jvm申请了一个钩子 在程序退出 异常什么情况导致的 调用了注册方法 这个就是释放资源时候最核心的东西了

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

public class DataBaseConnectMain {
    private static Connection conn;

    public static void main(String[] args) {

        System.out.println("The main thread starts executing");

        // 初始化数据库连接
        initConnection();

        System.out.println("Do some data querying and processing");

        // 注册关闭钩子
        Runtime.getRuntime().addShutdownHook(new Thread() {
            public void run() {
                closeConnection();
            }
        });

        System.out.println("The main thread ends execution.");
    }

    private static void initConnection() {
        try {
            Class.forName("com.mysql.jdbc.Driver");
            conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/mysql?useSSL=true&", "root", "root");
            System.out.println("Database connection successful!");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    private static void closeConnection() {
        try {
            conn.close();
            System.out.println("Database connection closed!");
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}
DisposableBean
  • void destroy() throws Exception;
  • 这个还是挺常见的自定义实现组件 配合InitializingBean在bean初始化完了做一些工作 然后销毁的时候做一些工作 主要是针对连接资源什么的

类信息开始

AbstractApplicationContext
  • 这个类目前看 需要实现上面所有接口的通用功能了

BeanDefinition注入过程

  • ApplicationContext ac = new AnnotationConfigApplicationContext(Dog.class);
  • 如果没有先创建一个RootBeanDefinition 构造器+属性 然后把beanClass设置进去
  • 再看下DefaultListableBeanFactory#registerBeanDefinition
    • this.beanDefinitionMap.put(beanName, beanDefinition); this.beanDefinitionNames.add(beanName); this.manualSingletonNames.remove(beanName);
    • 把bean信息放到beanDefinitionMap中
  • AnnotatedBeanDefinitionReader#registerBean 看下这个方法 这个是根据注解把Dog信息放进去
    • 先创建一个 AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass);
    • BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
    • definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
    • BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
  • 结束

Spring内部初始化的后置处理器内容

  • ApplicationContext ac = new AnnotationConfigApplicationContext(Dog.class);
    • 构造器AnnotationConfigApplicationContext
      • this.reader = new AnnotatedBeanDefinitionReader(this);
      • this.scanner = new ClassPathBeanDefinitionScanner(this);
    • 初始化4个BeanDefinitionHolder 初始化内部后置处理器 内部三个属性beanDefinition beanName aliases
      • 下面是需要的内部后置处理器 如果具体想看累都干了哪些事情 看每个类的 postProcessBeanFactory , postProcessBeanDefinitionRegistry,postProcessBeforeInitialization
      • ConfigurationClassPostProcessor -> org.springframework.context.annotation.internalConfigurationAnnotationProcessor
        • postProcessBeanFactory 这个类主要是处理 @Configuration 这个类的
        • 两大核心 enhanceConfigurationClasses(beanFactory); // 本次没走 是因为 没有注解
        • beanFactory.addBeanPostProcessor(new ImportAwareBeanPostProcessor(beanFactory));
      • AutowiredAnnotationBeanPostProcessor -> org.springframework.context.annotation.internalAutowiredAnnotationProcessor
        • 继承抽象类InstantiationAwareBeanPostProcessorAdapter
        • 这个类主要是处理 @Autowired 和 @Value 然后收集数据 Set lookupMethodsChecked , Map<Class<?>, Constructor<?>[]> candidateConstructorsCache,Map<String, InjectionMetadata> injectionMetadataCache
      • RequiredAnnotationBeanPostProcessor-> org.springframework.context.annotation.internalRequiredAnnotationProcessor
        +
      • CommonAnnotationBeanPostProcessor -> org.springframework.context.annotation.internalCommonAnnotationProcessor
      • 持久化的 不配置不注入进来 PersistenceAnnotationBeanPostProcessor -> org.springframework.context.annotation.internalPersistenceAnnotationProcessor
      • EventListenerMethodProcessor -> org.springframework.context.event.internalEventListenerProcessor
      • DefaultEventListenerFactory -> org.springframework.context.event.internalEventListenerFactory

未完待续

代码解析2,部分摘抄 简单的说,在web容器中,通过ServletContext为Spring的IOC容器提供宿主环境,对应的建立起一个IOC容器的体系。其中,首先需要建立的是根上下文,这个上下文持有的对象可以有业务对象,数据存取对象,资源,事物管理器等各种中间层对象。在这个上下文的基础上,和web MVC相关还会有一个上下文来保存控制器之类的MVC对象,这样就构成了一个层次化的上下文结构。在web容器中启动Spring应用程序就是一个建立这个上下文体系的过程。Spring为web应用提供了上下文的扩展接口 WebApplicationContext: 如转载请注明,转载自:关注Java[http://www.gbsou.com] 本文链接: http://www.gbsou.com/2009/08/11/214.html - - Java代码 public interface WebApplicationContext extends ApplicationContext { //这里定义的常量用于在ServletContext中存取根上下文 String ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE = WebApplicationContext.class.getName() + ".ROOT"; …… //对WebApplicationContext来说,需要得到Web容器的ServletContext ServletContext getServletContext(); } public interface WebApplicationContext extends ApplicationContext { //这里定义的常量用于在ServletContext中存取根上下文 String ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE = WebApplicationContext.class.getName() + ".ROOT"; ...... //对WebApplicationContext来说,需要得到Web容器的ServletContext ServletContext getServletContext(); } 而一般的启动过程,Spring会使用一个默认的实现,XmlWebApplicationContext – 这个上下文实现作为在web容器中的根上下文容器被建立起来,具体的建立过程在下面我们会详细分析。 Java代码 public class XmlWebApplicationContext extends AbstractRefreshableWebApplicationContext { /** 这是和web部署相关的位置信息,用来作为默认的根上下文bean定义信息的存放位置*/ public static final String DEFAULT_CONFIG_LOCATION = "/WEB-INF/applicationContext.xml"; public static final String DEFAULT_CONFIG_LOCATION_PREFIX = "/WEB-INF/"; public static final String DEFAULT_CONFIG_LOCATION_SUFFIX = ".xml"; //我们又看到了熟悉的loadBeanDefinition,就像我们前面对IOC容器的分析中一样,这个加载工程在容器的refresh()的时候启动。 protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws IOException { //对于XmlWebApplicationContext,当然使用的是XmlBeanDefinitionReader来对bean定义信息来进行解析 XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory); beanDefinitionReader.setResourceLoader(this); beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this)); initBeanDefinitionReader(beanDefinitionReader); loadBeanDefinitions(beanDefinitionReader); } protected void initBeanDefinitionReader(XmlBeanDefinitionReader beanDefinitionReader) { } //使用XmlBeanDefinitionReader来读入bean定义信息 protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException { String[] configLocations = getConfigLocations(); if (configLocations != null) { for (int i = 0; i < configLocations.length; i++) { reader.loadBeanDefinitions(configLocations[i]); } } } //这里取得bean定义信息位置,默认的地方是/WEB-INF/applicationContext.xml protected String[] getDefaultConfigLocations() { if (getNamespace() != null) { return new String[] {DEFAULT_CONFIG_LOCATION_PREFIX + getNamespace() + DEFAULT_CONFIG_LOCATION_SUFFIX}; } else { return new String[] {DEFAULT_CONFIG_LOCATION}; } } } public class XmlWebApplicationContext extends AbstractRefreshableWebApplicationContext { /** 这是和web部署相关的位置信息,用来作为默认的根上下文bean定义信息的存放位置*/ public static final String DEFAULT_CONFIG_LOCATION = "/WEB-INF/applicationContext.xml"; public static final String DEFAULT_CONFIG_LOCATION_PREFIX = "/WEB-INF/"; public static final String DEFAULT_CONFIG_LOCATION_SUFFIX = ".xml"; //我们又看到了熟悉的loadBeanDefinition,就像我们前面对IOC容器的分析中一样,这个加载工程在容器的refresh()的时候启动。 protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws IOException { //对于XmlWebApplicationContext,当然使用的是XmlBeanDefinitionReader来对bean定义信息来进行解析 XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory); beanDefinitionReader.setResourceLoader(this); beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this)); initBeanDefinitionReader(beanDefinitionReader); loadBeanDefinitions(beanDefinitionReader); } protected void initBeanDefinitionReader(XmlBeanDefinitionReader beanDefinitionReader) { } //使用XmlBeanDefinitionReader来读入bean定义信息 protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException { String[] configLocations = getConfigLocations(); if (configLocations != null) { for (int i = 0; i < configLocations.length; i++) { reader.loadBeanDefinitions(configLocations[i]); } } } //这里取得bean定义信息位置,默认的地方是/WEB-INF/applicationContext.xml protected String[] getDefaultConfigLocations() { if (getNamespace() != null) { return new String[] {DEFAULT_CONFIG_LOCATION_PREFIX + getNamespace() + DEFAULT_CONFIG_LOCATION_SUFFIX}; } else { return new String[] {DEFAULT_CONFIG_LOCATION}; } } } 对于一个Spring激活的web应用程序,可以通过使用Spring代码声明式的指定在web应用程序启动时载入应用程序上下文(WebApplicationContext),Spring的ContextLoader是提供这样性能的类,我们可以使用 ContextLoaderServlet或者ContextLoaderListener的启动时载入的Servlet来实例化Spring IOC容器 – 为什么会有两个不同的类来装载它呢,这是因为它们的使用需要区别不同的Servlet容器支持的Serlvet版本。但不管是 ContextLoaderSevlet还是 ContextLoaderListener都使用ContextLoader来完成实际的WebApplicationContext的初始化工作。这个ContextLoder就像是Spring Web应用程序在Web容器中的加载器booter。当然这些Servlet的具体使用我们都要借助web容器中的部署描述符来进行相关的定义。 下面我们使用ContextLoaderListener作为载入器作一个详细的分析,这个Servlet的监听器是根上下文被载入的地方,也是整个 Spring web应用加载上下文的第一个地方;从加载过程我们可以看到,首先从Servlet事件中得到ServletContext,然后可以读到配置好的在web.xml的中的各个属性值,然后ContextLoder实例化WebApplicationContext并完成其载入和初始化作为根上下文。当这个根上下文被载入后,它被绑定到web应用程序的ServletContext上。任何需要访问该ApplicationContext的应用程序代码都可以从WebApplicationContextUtils类的静态方法来得到:
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值