Spring之核心类

spring核心容器介绍

两个核心容器

Spring有两个核心接口:BeanFactory和ApplicationContext,其中ApplicationContext是BeanFactory的子接口。他们都可代表Spring容器。使用最多的是ApplicationContext,所以介绍ApplicationContext。

作用

Spring容器是生成Bean实例的工厂,并且管理容器中的Bean。BeanFactory 使用控制反转(IOC) 模式将应用程序的配置和依赖性规范与实际的应用程序代码分开。

使用

使用spring首先要引入jar包依赖

// spring-context 会自动将 spring-core、spring-beans、
//spring-aop、spring-expression 这几个基础 jar 包带进来。
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-context</artifactId>
  <version>5.0.2.RELEASE</version>
</dependency>

在这里插入图片描述
启动spring容器的代码

public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("application.xml");
    }

ApplicationContext的父子级关系

父级
在这里插入图片描述
子级
在这里插入图片描述
  ClassPathXmlApplicationContext 实现了ApplicationContext 接口,同样的,我们也可以使用绿颜色的 FileSystemXmlApplicationContext 和 AnnotationConfigApplicationContext 这两个类。
  FileSystemXmlApplicationContext 的构造函数需要一个 xml 配置文件在系统中的路径,其他和 ClassPathXmlApplicationContext 基本上一样。
  AnnotationConfigApplicationContext 是基于注解来使用的,它不需要配置文件,采用 java 配置类和各种注解来配置,是比较简单的方式,也是大势所趋吧。

代码分析

接口

public interface Message {
    String getMessage();
}

实现类

public class MessageImpl implements Message {
    @Override
    public String getMessage() {
        return "Hello World";
    }
}

核心配置文件

<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns="http://www.springframework.org/schema/beans"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <!--default-autowire="byClass"-->
    <bean id="messageService" class="com.springtest.interfacepackage.impl.MessageImpl"/>
    <!--<bean id="messageImpl" class="com.springtest.interfacepackage.impl.MessageImpl2"/>-->
</beans>

启动类

public static void main(String[] args) {
    ApplicationContext context = new ClassPathXmlApplicationContext("application.xml");
    Message message = context.getBean(Message.class);
    System.out.println(message.getMessage());
}

主要类

ApplicationContext的实现类-启动类

AnnotationConfigApplicationContext、FileSystemXmlApplicationContext 、ClassPathXmlApplicationContext
FileSystemXmlApplicationContext 的构造函数需要一个 xml 配置文件在系统中的路径,其他和 ClassPathXmlApplicationContext 基本上一样

BeanDefinition

BeanDefinition 中保存了我们的 Bean 信息,比如这个 Bean 指向的是哪个类、是否是单例的、是否懒加载、这个 Bean 依赖了哪些 Bean 等等。

public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {
 
   // 我们可以看到,默认只提供 sington 和 prototype 两种,
   // 很多读者都知道还有 request, session, globalSession, application, websocket 这几种,
   // 不过,它们属于基于 web 的扩展。
   String SCOPE_SINGLETON = ConfigurableBeanFactory.SCOPE_SINGLETON;
   String SCOPE_PROTOTYPE = ConfigurableBeanFactory.SCOPE_PROTOTYPE;
 
   // 比较不重要,直接跳过吧
   int ROLE_APPLICATION = 0;
   int ROLE_SUPPORT = 1;
   int ROLE_INFRASTRUCTURE = 2;
 
   // 设置父 Bean,这里涉及到 bean 继承,不是 java 继承。请参见附录介绍
   void setParentName(String parentName);
 
   // 获取父 Bean
   String getParentName();
 
   // 设置 Bean 的类名称
   void setBeanClassName(String beanClassName);
 
   // 获取 Bean 的类名称
   String getBeanClassName();
 
 
   // 设置 bean 的 scope
   void setScope(String scope);
 
   String getScope();
 
   // 设置是否懒加载
   void setLazyInit(boolean lazyInit);
 
   boolean isLazyInit();
 
   // 设置该 Bean 依赖的所有的 Bean,注意,这里的依赖不是指属性依赖(如 @Autowire 标记的),
   // 是 depends-on="" 属性设置的值。
   void setDependsOn(String... dependsOn);
 
   // 返回该 Bean 的所有依赖
   String[] getDependsOn();
 
   // 设置该 Bean 是否可以注入到其他 Bean 中,只对根据类型注入有效,
   // 如果根据名称注入,即使这边设置了 false,也是可以的
   void setAutowireCandidate(boolean autowireCandidate);
 
   // 该 Bean 是否可以注入到其他 Bean 中
   boolean isAutowireCandidate();
 
   // 主要的。同一接口的多个实现,如果不指定名字的话,Spring 会优先选择设置 primary 为 true 的 bean
   void setPrimary(boolean primary);
 
   // 是否是 primary 的
   boolean isPrimary();
 
   // 如果该 Bean 采用工厂方法生成,指定工厂名称。对工厂不熟悉的读者,请参加附录
   void setFactoryBeanName(String factoryBeanName);
   // 获取工厂名称
   String getFactoryBeanName();
   // 指定工厂类中的 工厂方法名称
   void setFactoryMethodName(String factoryMethodName);
   // 获取工厂类中的 工厂方法名称
   String getFactoryMethodName();
 
   // 构造器参数
   ConstructorArgumentValues getConstructorArgumentValues();
 
   // Bean 中的属性值,后面给 bean 注入属性值的时候会说到
   MutablePropertyValues getPropertyValues();
 
   // 是否 singleton
   boolean isSingleton();
 
   // 是否 prototype
   boolean isPrototype();
 
   // 如果这个 Bean 原生是抽象类,那么不能实例化
   boolean isAbstract();
 
   int getRole();
   String getDescription();
   String getResourceDescription();
   BeanDefinition getOriginatingBeanDefinition();
}

XmlBeanDefinitionReader

其负责加载配置、解析

ContextNamespaceHandler

想分析 <context:property-placeholder location=“classpath:xx.properties” /> 的实现原理

ConversionService

最有用的场景就是,它用来将前端传过来的参数和后端的 controller 方法上的参数进行绑定的时候用。像前端传过来的字符串、整数要转换为后端的 String、Integer 很容易,但是如果 controller 方法需要的是一个枚举值,或者是 Date 这些非基础类型(含基础类型包装类)值的时候,我们就可以考虑采用 ConversionService 来进行转换。
ConversionService 接口很简单,所以要自定义一个 convert 的话也很简单。
下面再说一个实现这种转换很简单的方式,那就是实现 Converter 接口。
来看一个很简单的例子,这样比什么都管用。

public class StringToDateConverter implements Converter<String, Date> {
 
    @Override
    public Date convert(String source) {
        try {
            return DateUtils.parseDate(source, "yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "HH:mm:ss", "HH:mm");
        } catch (ParseException e) {
            return null;
        }
    }
}

BeanPostProcessor

接口定义

public interface BeanPostProcessor {
 
   Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
 
   Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
 
}

看这个接口中的两个方法名字我们大体上可以猜测 bean 在初始化之前会执行 postProcessBeforeInitialization 这个方法,初始化完成之后会执行 postProcessAfterInitialization 这个方法。但是,这么理解是非常片面的。

首先,我们要明白,除了我们自己定义的 BeanPostProcessor 实现外,Spring 容器在启动时自动给我们也加了几个。如在获取 BeanFactory 的 obtainFactory() 方法结束后的 prepareBeanFactory(factory),大家仔细看会发现,Spring 往容器中添加了这两个 BeanPostProcessor:ApplicationContextAwareProcessor、ApplicationListenerDetector。

如果仔细看了代码分析的话,其实很容易知道了,在 bean 实例化完成、属性注入完成之后,会执行回调方法,具体请参见类 AbstractAutowireCapableBeanFactory#initBean 方法。

首先会回调几个实现了 Aware 接口的 bean,然后就开始回调 BeanPostProcessor 的 postProcessBeforeInitialization 方法,之后是回调 init-method,然后再回调 BeanPostProcessor 的 postProcessAfterInitialization 方法。

转载: https://javadoop.com/post/spring-ioc

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值