Spring源码分析第五弹 - 神级的spring还有其他什么功效?

从最开始的简单手写篇到现在的源码分析篇,整个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源码后的手写高仿版

读书之法,在循序而渐进,熟读而精思

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值