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返回出去。