7.17周总结

最近在忙项目中有关OData服务的开发,由于知识储备的不足、项目的特殊复杂性,总体来说做的比较头疼。抽时间可以把自己做过的这一块东西回顾、总结一下。在今天这个悠闲的周末傍晚,静下心来总结一下这周了解到的有关Spring的一些扩展接口的其他小玩意,喵喵喵~~~

目录:

  1. Spring扩展接口
  1. 小玩意

1. Spring 扩展接口

Spring整个框架严格遵循“开闭原则”,即“对扩展开放,对修改关闭”。个人理解为,Spring框架核心之一就是IOC,即"Bean Container",整个"Bean Container"的生命周期大致为:加载(XML或者Anotation)、初始化(初始化相应的Bean)、runtime(在runtime提供Bean)、销毁,也就是说,无论在什么情况下,Spring都是按照这一套流程走下来的,没有提供相应的类、接口、方法来改变这个过程,最多提供一些接口来“丰富”一下这个过程,即对“扩展开发”。这些接口包括:

  1. BeanFactoryPostProcessor
  1. InstantiationAwareBeanPostProcessor
  2. BeanNameAware
  3. BeanFactoryAware
  4. BeanPostProcessor
  5. InitializingBean
  6. DiposibleBean
  7. FactoryBean
  8. 在Bean生命周期中相应接口调用

对于整个 Bean Container 的扩展

  • BeanFactoryPostProcessor
public interface BeanFactoryPostProcessor {

    void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;

}

从接口定义上可以得知,其只有一个方法

void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;

参数类型为ConfigurableListableBeanFactory,追根溯源,该接口的定义如下:

public interface ConfigurableListableBeanFactory extends ListableBeanFactory, AutowireCapableBeanFactory, ConfigurableBeanFactory {

    void ignoreDependencyType(Class<?> type);

    void ignoreDependencyInterface(Class<?> ifc);

    void registerResolvableDependency(Class<?> dependencyType, Object autowiredValue);

    boolean isAutowireCandidate(String beanName, DependencyDescriptor descriptor)throws NoSuchBeanDefinitionException;

    BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;

    Iterator<String> getBeanNamesIterator();

    void clearMetadataCache();

    void freezeConfiguration();

    boolean isConfigurationFrozen();

    void preInstantiateSingletons() throws BeansException;

}

其中有一个方法

BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;

通过传入相应的Bean Name,就能拿到对应的BeanDefinition,其对应着一个Bean的元信息描述。
有关BeanDefinition的接口描述:


public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {

    String SCOPE_SINGLETON = ConfigurableBeanFactory.SCOPE_SINGLETON;

    String SCOPE_PROTOTYPE = ConfigurableBeanFactory.SCOPE_PROTOTYPE;

    int ROLE_APPLICATION = 0;

    int ROLE_SUPPORT = 1;

    int ROLE_INFRASTRUCTURE = 2;

    String getParentName();

    void setParentName(String parentName);

    String getBeanClassName();

    void setBeanClassName(String beanClassName);

    String getFactoryBeanName();

    void setFactoryBeanName(String factoryBeanName);

    String getFactoryMethodName();

    void setFactoryMethodName(String factoryMethodName);

    String getScope();

    void setScope(String scope);

    boolean isLazyInit();

    void setLazyInit(boolean lazyInit);

    String[] getDependsOn();

    void setDependsOn(String... dependsOn);

    boolean isAutowireCandidate();

    void setAutowireCandidate(boolean autowireCandidate);

    boolean isPrimary();

    void setPrimary(boolean primary);

    ConstructorArgumentValues getConstructorArgumentValues();

    MutablePropertyValues getPropertyValues();

    boolean isSingleton();

    boolean isPrototype();

    boolean isAbstract();

    int getRole();

    String getDescription();

    String getResourceDescription();

    BeanDefinition getOriginatingBeanDefinition();

}

其中里边有几个比较常用的方法:

void setFactoryBeanName(String factoryBeanName);
void setBeanClassName(String beanClassName);
void setScope(String scope);
void setLazyInit(boolean lazyInit);

以及一些相应的Get方法。
即在runtime时,可以通过以上接口来动态修改Bean的元描述信息:name、isLazyInit,scope

所以让我们回到最初探索的地方,扩展接口BeanFactoryPostProcessor:实现这个接口的postProcessBeanFactory,来根据需要在Spring启动时动态修改相应Bean的元描述信息。

  • BeanFactoryAware

该接口的详细描述如下:

public interface BeanFactoryAware extends Aware {

    void setBeanFactory(BeanFactory beanFactory) throws BeansException;

}

也只有一个方法

void setBeanFactory(BeanFactory beanFactory) throws BeansException;

同样可以实现该接口,在runtime获得该BeanFactory

对于 Bean 的扩展

  • InstantiationAwareBeanPostProcessor

该接口的定义如下:

public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {

    Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException;

    boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException;

    PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException;

}

其中包含了三个方法:

    Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException;

    boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException;

    PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException;

这三个方法的作用时期是在Bean的实例化阶段。之前我也不太清楚“实例化”和“初始化”的区别,后来查了资料,发现大概是这样的:
实例化----实例化的过程是一个创建Bean的过程,即调用Bean的构造函数,单例的Bean放入单例池中。
初始化----初始化的过程是一个赋值的过程,即调用Bean的setter,设置Bean的属性

  • BeanNameAware

该接口的详细描述如下:


public interface BeanNameAware extends Aware {

    void setBeanName(String name);

}

这个接口很简单,只有一个方法

void setBeanName(String name);

在实际开发中,可以实现该接口,动态地获取每一个被加载到"Bean Container"中的Bean Name

  • BeanPostProcessor

该接口的详细描述如下:


public interface BeanPostProcessor {

    Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;

    Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;

}

其中包含了两个方法:

Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;

这两个方法分别是在Bean初始化的前后起作用,我们可以根据beanName来筛选出相应的Bean,并结合具体的业务需求来对某些Bean进行一些有针对性的预处理。

  • InitializingBean

其接口的详细描述如下:


public interface InitializingBean {

    void afterPropertiesSet() throws Exception;

}

该接口只有一个方法

void afterPropertiesSet() throws Exception;

很明显,该接口是在某个Bean的所有Properties初始化完成之后起作用。该方法没有任何参数,可以根据具体业务需求来自定义处理。

扩展: 在Spring对于XML配置Bean的规范中,提供了一个属性init-method,作用于该方法一样。该属性的具体用法大致如下:

<?xml version="1.0" encoding="UTF-8"?>
<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-4.1.xsd">
    
    <bean id="common0" class="org.xrq.bean.common.CommonBean" init-method="initMethod">
        <property name="commonName" value="common0"/>
    </bean>
    
    <bean id="common1" class="org.xrq.bean.common.CommonBean" init-method="initMethod">
        <property name="commonName" value="common1"/>
    </bean>
</beans>
  • DisposableBean

该接口的具体描述如下:


public interface DisposableBean {

    void destroy() throws Exception;

}

其中也只有一个方法

void destroy() throws Exception;

该方法是在某个Bean的结束时(Bean Container被销毁时)起作用。

  • FactoryBean

该接口的详细描述如下:

public interface FactoryBean<T> {

    T getObject() throws Exception;

    Class<?> getObjectType();

    boolean isSingleton();

}

其中有三个方法,实现方法getObject,就可以加载自定义的Bean

在Bean生命周期中相应接口调用:

参考文章:Spring Bean的生命周期(非常详细)

2. 小玩意

之前一直对Spring体系中的BeanFactoryApplicationContext搞不明白,这次查了一点资料,逐渐理清了。

  • BeanFactory:是一个对于IOC容器行为最基本的规范接口,比如getBean()
    有关BeanFactory的具体实现,常见XmlBeanFactory,不过该类已经被弃用了。
  • ApplicationContext: 继承BeanFactory,不仅具有BeanFactory的功能,还支持国际化message处理,比如MessageSource接口,事件监听
    有关ApplicationContext的具体实现,常见XmlWebApplicationContext,ClassPathXmlApplicationContext,FileSystemApplicationContext,AnnotationConfigApplicationContext

有关ApplicationContext的扩展:获取ApplicationContext的几种方式:

  • 直接通过上面列举的几种描述来获得,比如
pplicationContext ac = new FileSystemXmlApplicationContext("applicationContext.xml"); 
  • 通过Spring提供的工具类获取ApplicationContext对象,比如
ApplicationContext ac = WebApplicationContextUtils.getRequiredWebApplicationContext(ServletContext sc); 
  • 继承自抽象类ApplicationObjectSupport
    Spring初始化时,会通过该抽象类的setApplicationContext(ApplicationContext context)方法将ApplicationContext 对象注入

  • 继承自抽象类WebApplicationObjectSupport
    说明:类似上面方法,调用getWebApplicationContext()获取WebApplicationContext

  • 实现接口ApplicationContextAware

  • 通过Spring提供的ContextLoader

WebApplicationContext wac = ContextLoader.getCurrentWebApplicationContext();

最后提供一种不依赖于servlet,不需要注入的方式。但是需要注意一点,在服务器启动时,Spring容器初始化时,不能通过以下方法获取Spring 容器

参考文章

  1. Spring8:一些常用的Spring Bean扩展接口
  2. Spring Bean的生命周期(非常详细)
  3. Spring在代码中获取bean的几种方式
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,386评论 6 479
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,939评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,851评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,953评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,971评论 5 369
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,784评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,126评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,765评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,148评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,744评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,858评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,479评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,080评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,053评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,278评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,245评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,590评论 2 343

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,598评论 18 139
  • Spring Boot 参考指南 介绍 转载自:https://www.gitbook.com/book/qbgb...
    毛宇鹏阅读 46,747评论 6 342
  • Spring容器高层视图 Spring 启动时读取应用程序提供的Bean配置信息,并在Spring容器中生成一份相...
    Theriseof阅读 2,796评论 1 24
  • 拿到小文友赠送的上海书展的门票,还在犹豫是否决定真的践行,问了小墨,他决定要去,那母子俩就冒着闷热的天气去上海冒充...
    一玄子阅读 364评论 0 0
  • 姓名:王成茗 日精进打卡第26天 【打卡始于2017.10.12持续于2017.11.6】 【知~学习】 ...
    王成茗阅读 96评论 0 0