从最开始的简单手写篇到现在的源码分析篇,整个springMVC已经完结了。
从中我们可以看到各种回调,例如AOP、MVC都是通过回调处理的。本篇文章就来了解一下spring除了拿来当做框架还有其他的什么实际用途。
首先,再次了解一下spring bean创建过程的回调
createBeanInstance -> Constructor -> setter methods ->
BeanNameAware.setBeanName ->BeanClassLoaderAware.setBeanClassLoader -> BeanFactoryAware.setBeanFactory -> BeanPostProcessor.postProcessBeforeInitialization ->
InitializingBean.afterPropertiesSet -> BeanPostProcessor.postProcessAfterInitialization
1. Constructor:通过构造方法初始化对象,Class.newInstance()
2. setter methods,属性方法赋值,依赖注入,前面有依赖注入详解,不再多说
3. BeanNameAware.setBeanName
- 获取当前实现类的beanName,准备如下代码,在初始化当前类时,会将beanName回调到该方法来
@Component
public class TestBeanNameAware implements BeanNameAware {
@Override
public void setBeanName(String name) {
System.out.println("#获得TestBeanNameAware实现类的beanName:"+name);
}
}
4. BeanClassLoaderAware.setBeanClassLoader
- 获取当前加载类的ClassLoader
@Component
public class TestBeanClassLoaderAware implements BeanClassLoaderAware {
@Override
public void setBeanClassLoader(ClassLoader classLoader) {
System.out.println("#获得当前加载类的classLoader:"+classLoader);
}
}
5. BeanFactoryAware.setBeanFactory
- 获取容器里面所有的bean , 比较常见的ApplicationContextAware也是同样的功能
@Component
public class TestBeanFactoryAware implements BeanFactoryAware {
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
System.out.println("#获得管理bean的容器:"+beanFactory.getClass().getName());
//
Object nameAware = beanFactory.getBean("testBeanNameAware");
System.out.println(nameAware);
}
}
6. BeanPostProcessor.postProcessBeforeInitialization 、postProcessAfterInitialization
- 初始化bean前后的回调,可以在bean初始化之前后返回继承类或者代理类,aop就是典型的例子
@Component
public class TestInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
// System.out.println("初始化之前:"+bean.getClass().getName()+","+beanName);
if(beanName.equals("com.example.demo.action.TestAction")){
System.out.println("初始化之后:"+bean.getClass().getName()+","+beanName);
return new Test1Action(); //设置成实现类或者继承类 动态修改bean的初始化
}
return null;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
// System.out.println("初始化之后:"+bean.getClass().getName()+","+beanName);
if(beanName.equals("com.example.demo.action.TestAction")){
System.out.println("初始化之后:"+bean.getClass().getName()+","+beanName);
}
return null;
}
}
7. InitializingBean.afterPropertiesSet
- 初始完当前类的回调,案例:MVC的实现
@Component
public class TestInitializingBean implements InitializingBean {
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("#初始化完毕当前类回调,后置回调之前");
}
}
8. ApplicationContextAware 获得容器上下文,比较常用,不细说了
9. BeanDefinitionRegistryPostProcessor
- 自定义注册bean或者属性
@Component
public class TestBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
/**
* 实现自定义bean并注册到BeanDefinitionRegistry
* @param registry
* @throws BeansException
*/
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
//TestAction 无任何加载的标识 可以用这种方法向容器注册 mybatis里面用到
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(TestAction.class);
registry.registerBeanDefinition(TestAction.class.getName(),builder.getBeanDefinition());
System.out.println("注册自定义bean:"+builder.getBeanDefinition().getBeanClass());
}
/**
* 主要是用来自定义修改持有的bean里面的属性值
* @param beanFactory
* @throws BeansException
*/
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
for (String definitionName : beanFactory.getBeanDefinitionNames()) {
if ("com.example.demo.action.TestAction".equals(definitionName)) {
System.out.println("###beanName:" + definitionName);
BeanDefinition definition = beanFactory.getBeanDefinition(definitionName);
//获取bean的定义的值 动态修改值 需要有setter方法
MutablePropertyValues pv = definition.getPropertyValues();
pv.addPropertyValue("name", "王二麻子");
System.out.println("###TestAction#name重新赋值");
break;
}
}
}
}
10. FactoryBean.getObject(), getObjectType()
- 实现了FactoryBean的类,容器初始化该类的时候会调用当前getObject()方法
//也可自己注册 初始该注册类时也会调用到该方法
BeanDefinitionBuilder builder1 = BeanDefinitionBuilder.genericBeanDefinition(TestFatoryBean.class);
registry.registerBeanDefinition("aaabbbccc",builder1.getBeanDefinition());
@Component
public class TestFatoryBean implements FactoryBean {
/**
* 初始化这个类的时候 TestFatoryBean的定义就已经被替换成了 TestFactoryBean1 这个类
* 在其他类注解TestFactoryBean1 就可以直接用
* @return 返回的对象实例
* @throws Exception
*/
@Override
public Object getObject() throws Exception {
System.out.println("#初始化TestFatoryBean.getObject()");
return new TestFactoryBean1();
}
/**
* @return 返回的对象类型
*/
@Override
public Class<?> getObjectType() {
System.out.println("#初始化TestFatoryBean.getObjectType()");
return TestFactoryBean1.class;
}
}
11. AbstractApplicationContext
- 主要为容器的相关事件
@Component
public class TestAbstractApplicationContext extends AbstractApplicationContext {
@Override
protected void refreshBeanFactory() throws BeansException, IllegalStateException {
System.out.println("#刷新容器事件");
}
@Override
protected void closeBeanFactory() {
System.out.println("#关闭容器事件");
}
/**
* 返回已有容器 || 自定义的容器
* @return
* @throws IllegalStateException
*/
@Override
public ConfigurableListableBeanFactory getBeanFactory() throws IllegalStateException {
return null;
}
}
12. DeferredImportSelector extends ImportSelector
- 自定义需要导入的类,传入类名list,自动装配用
- 需要用到其他的类,注解@Import(TestDeferredImportSelector.class) 使用
第一种用法:
public class TestDeferredImportSelector implements ImportSelector {
//直接实现 传入类的包名路径
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
System.out.println("#延时引入需要加载的importingClassMetadata");
return new String[]{TestImportAction.class.getName()};
}
}
第二种用法,可按分组实现:
public class TestDeferredImportSelector implements DeferredImportSelector {
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
return null;
}
/**
* 如果实现了分组 优先按分组来 就是去分组的实现类
* @return 返回实现分组的类 (实现DeferredImportSelector.Group)
*/
@Override
public Class<? extends Group> getImportGroup() {
return Test123.class;
}
private static class Test123 implements DeferredImportSelector.Group{
AnnotationMetadata annotationMetadata;
@Override
public void process(AnnotationMetadata metadata, DeferredImportSelector selector) {
System.out.println("#延时引入需要加载的process");
this.annotationMetadata = metadata;
//这里可以根据原数据做分组 让每个分组加载不同的类
}
@Override
public Iterable<Entry> selectImports() {
System.out.println("#延时引入需要加载的selectImports");
String[] strings = {TestImportAction.class.getName()};
return Arrays.asList(strings).stream().
map((className) -> new Entry(this.annotationMetadata,className)).collect(Collectors.toList());
}
}
}
目前能整理出来的就这么多了,肯定还有没顾全的。这里就不多深入研究了
以上就是本章的全部内容了。
上一篇:Spring源码分析第四弹 - MVC分析
下一篇:SpringMvc源码分析第六弹 - 基于SpringMvc源码后的手写高仿版
读书之法,在循序而渐进,熟读而精思