Spring提供的扩展点以及案例

Spring提供的扩展点以及案例

1 BeanFactoryPostProcessor
/**
 * spring的扩展点之一
 * 实现该接口,可以在spring的bean创建之前修改bean的定义属性。
 * spring允许BeanFactoryPostProcessor在容器实例化任何其它bean之前读取配置元数据,
 * 并可以根据需要进行修改,例如可以把bean的scope从singleton改为prototype,也可以把property的值给修改掉。
 * 可以同时配置多个BeanFactoryPostProcessor,并通过设置'order'属性来控制各个BeanFactoryPostProcessor的执行次序。
 * BeanFactoryPostProcessor是在spring容器加载了bean的定义文件之后,在bean实例化之前执行的
 **/
public interface BeanFactoryPostProcessor {
	void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;

}

案例:ConfigurationClassPostProcessor

ConfigurationClassPostProcessor实现了BeanFactoryPostProcess,利用这个扩展点,ConfigurationClassPostProcessor完成了对Configuration Component ComponentScan Import ImportResource这几种注解的解析,并进行包扫描或者resource的import。

2 BeanPostProcessor
/**
 * BeanPostProcessor是Spring框架的提供的一个扩展类点(不止一个)
 * 通过实现BeanPostProcessor接口,程序员就可插手bean实例化的过程,从而减轻了beanFactory的负担
 * 值得说明的是这个接口可以设置多个,会形成一个列表,然后依次执行
 * (但是spring默认的怎么办?set)
 * 比如AOP就是在bean实例后期间将切面逻辑织入bean实例中的
 * AOP也正是通过BeanPostProcessor和IOC容器建立起了联系
 * (由spring提供的默认的PostPorcessor,spring提供了很多默认的PostProcesso)
 * 先来熟悉一下这个接口,其实这个接口本身特别简单
 * 但是他的实现类特别复杂,同样复杂到发指!
 * 可以看看spring提供哪些默认的实现(前方高能)
 * 1、ApplicationContextAwareProcessor (acap)
 *    acap后置处理器的作用是,当应用程序定义的Bean实现ApplicationContextAware接口时注入ApplicationContext对象
 *    当然这是他的第一个作业,他还有其他作用,这里不一一列举了,可以参考源码
 *    我们可以针对ApplicationContextAwareProcessor写一个栗子
 *  2、InitDestroyAnnotationBeanPostProcessor
 *     用来处理自定义的初始化方法和销毁方法
 *    上次说过Spring中提供了3种自定义初始化和销毁方法分别是
 *    一、通过@Bean指定init-method和destroy-method属性
 *    二、Bean实现InitializingBean接口和实现DisposableBean
 *    三、@PostConstruct:@PreDestroy
 *    为什么spring通这三种方法都能完成对bean生命周期的回调呢?
 *    可以通过InitDestroyAnnotationBeanPostProcessor的源码来解释
 *  3、InstantiationAwareBeanPostProcessor
 *  4、CommonAnnotationBeanPostProcessor
 *  5、AutowiredAnnotationBeanPostProcessor
 *  6 、RequiredAnnotationBeanPostProcessor
 *  7、BeanValidationPostProcessor
 *  8、AbstractAutoProxyCreator
 *  ......
 **/
 public interface BeanPostProcessor {
	 */
	@Nullable
	default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		return bean;
	}

	@Nullable
	default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		return bean;
	}

}

案例:
@PostConstruct

@Override
	public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		//找出被@PostConstruct和@PreDestroy注解修饰的方法
		LifecycleMetadata metadata = findLifecycleMetadata(bean.getClass());
		try {
		//执行对应的方法
			metadata.invokeInitMethods(bean, beanName);
		}
		catch (InvocationTargetException ex) {
			throw new BeanCreationException(beanName, "Invocation of init method failed", ex.getTargetException());
		}
		catch (Throwable ex) {
			throw new BeanCreationException(beanName, "Failed to invoke init method", ex);
		}
		return bean;
	}

当然还有AOP还有事务

3 BeanDefinitionRegistryPostProcessor
public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {
	void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;

}

拿到了registry,就可以去注册自己想注册的bean

4 ImportBeanDefinitionRegistrar
public interface ImportBeanDefinitionRegistrar {
	public void registerBeanDefinitions(
			AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry);
}

案例,mybatis的@MapperScan(“com.xxx”)

public class MapperScannerRegistrar implements ImportBeanDefinitionRegistrar, ResourceLoaderAware {
    private ResourceLoader resourceLoader;

    public MapperScannerRegistrar() {
    }

    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        AnnotationAttributes annoAttrs = AnnotationAttributes.fromMap(importingClassMetadata.getAnnotationAttributes(MapperScan.class.getName()));
        ClassPathMapperScanner scanner = new ClassPathMapperScanner(registry);
        if (this.resourceLoader != null) {
            scanner.setResourceLoader(this.resourceLoader);
        }

        Class<? extends Annotation> annotationClass = annoAttrs.getClass("annotationClass");
        if (!Annotation.class.equals(annotationClass)) {
            scanner.setAnnotationClass(annotationClass);
        }

        Class<?> markerInterface = annoAttrs.getClass("markerInterface");
        if (!Class.class.equals(markerInterface)) {
            scanner.setMarkerInterface(markerInterface);
        }

        Class<? extends BeanNameGenerator> generatorClass = annoAttrs.getClass("nameGenerator");
        if (!BeanNameGenerator.class.equals(generatorClass)) {
            scanner.setBeanNameGenerator((BeanNameGenerator)BeanUtils.instantiateClass(generatorClass));
        }

        scanner.setSqlSessionTemplateBeanName(annoAttrs.getString("sqlSessionTemplateRef"));
        scanner.setSqlSessionFactoryBeanName(annoAttrs.getString("sqlSessionFactoryRef"));
        List<String> basePackages = new ArrayList();
        String[] arr$ = annoAttrs.getStringArray("value");
        int len$ = arr$.length;

        int i$;
        String pkg;
        for(i$ = 0; i$ < len$; ++i$) {
            pkg = arr$[i$];
            if (StringUtils.hasText(pkg)) {
                basePackages.add(pkg);
            }
        }

        arr$ = annoAttrs.getStringArray("basePackages");
        len$ = arr$.length;

        for(i$ = 0; i$ < len$; ++i$) {
            pkg = arr$[i$];
            if (StringUtils.hasText(pkg)) {
                basePackages.add(pkg);
            }
        }

        Class[] arr$ = annoAttrs.getClassArray("basePackageClasses");
        len$ = arr$.length;

        for(i$ = 0; i$ < len$; ++i$) {
            Class<?> clazz = arr$[i$];
            basePackages.add(ClassUtils.getPackageName(clazz));
        }

        scanner.registerFilters();
        scanner.doScan(StringUtils.toStringArray(basePackages));
    }

拿到了registry和注解,然后就可以根据注解所配置的包,扫描我们的mapper文件,形成BeanDefinitions。

5 FactoryBean
public interface FactoryBean<T> {
	@Nullable
	T getObject() throws Exception;
	}

mybatis中的SqlSessionFactoryBean实现了InitializingBean和FactoryBean接口
其中InitializingBean接口,提供了afterPropertiesSet,new出来了DefaultSqlSessionFactory,并且往里面environment设置好了数据库账号密码等信息。

    public void afterPropertiesSet() throws Exception {
        Assert.notNull(this.dataSource, "Property 'dataSource' is required");
        Assert.notNull(this.sqlSessionFactoryBuilder, "Property 'sqlSessionFactoryBuilder' is required");
        this.sqlSessionFactory = this.buildSqlSessionFactory();
    }

通过的getObject方法,把完成数据库配置的DefaultSqlSessionFactory返回出去。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值