赞
踩
项目中经常会有数据源切换的需求,而aop编程实现数据源切换也很实用,由于本人是技术渣,一直没有深究,只知道aop底层是代理模式。趁着现在有时间,恶补了一下aop底层原理。
本文演示:基于spring提供的接口实现对业务类的扫描并生成动态代理类,注册到ioc容器中。这里不多讲直接上代码。
DataSourceComponent:
@Documented @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) public @interface DataSourceComponent { /** * 数据源 * @return */ DatasourceEnum DataSource() default DatasourceEnum.DB1; /** * 是否要将标识此注解的类注册为Spring的Bean * * @return */ boolean registerBean() default false; }
该注解声明在类上,表明该类使用哪个数据源。
DataSourceComponentScan:
@Documented @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Import(BeanDefinitionRegistrar.class) public @interface DataSourceComponentScan { /** * @return */ String[] value() default {}; /** * 扫描包 * * @return */ String[] basePackages() default {}; /** * 扫描的基类 * * @return */ Class<?>[] basePackageClasses() default {}; /** * 包含过滤器 * * @return */ Filter[] includeFilters() default {}; /** * 排斥过滤器 * * @return */ Filter[] excludeFilters() default {}; }
该注解在主类上声明,basePackages属性指定扫描哪个包:@DataSourceComponentScan(basePackages=“CglibRegisterToSpring.service”)
@Import(HsfBeanDefinitionRegistrar.class)引入配置类,如果该配置类实现了ImportBeanDefinitionRegistrar接口或者BeanDefinitionRegistryPostProcessor,则会调用该接口方法,而不是该实现类注册为bean.
ImportBeanDefinitionRegistrar用法大体和BeanDefinitionRegistryPostProcessor相同,但是值得注意的是ImportBeanDefinitionRegistrar只能通过由其它类import的方式来加载,通常是主启动类或者注解。
2.1 扫描器
在容器启动时调用,会加载import注解中声明的类,配置类实现ImportBeanDefinitionRegistrar接口,自动执行registerBeanDefinitions方法
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { //拿到主类上的自定义注解的属性 AnnotationAttributes annAttr = AnnotationAttributes.fromMap(importingClassMetadata.getAnnotationAttributes(DataSourceComponentScan.class.getName())); String[] basePackages = annAttr.getStringArray("value"); if (ObjectUtils.isEmpty(basePackages)) { basePackages = annAttr.getStringArray("basePackages"); } if (ObjectUtils.isEmpty(basePackages)) { basePackages = getPackagesFromClasses(annAttr.getClassArray("basePackageClasses")); } if (ObjectUtils.isEmpty(basePackages)) { basePackages = new String[] {ClassUtils.getPackageName(importingClassMetadata.getClassName())}; } List<TypeFilter> includeFilters = extractTypeFilters(annAttr.getAnnotationArray("includeFilters")); //增加一个包含的过滤器,扫描到的类只要不是抽象的,接口,枚举,注解,及匿名类那么就算是符合的 includeFilters.add(new HsfTypeFilter()); List<TypeFilter> excludeFilters = extractTypeFilters(annAttr.getAnnotationArray("excludeFilters")); List<Class<?>> candidates = scanPackages(basePackages, includeFilters, excludeFilters); if (candidates.isEmpty()) { log.info("扫描指定包[{}]时未发现复合条件的类", basePackages.toString()); return; } //注册处理器后,为 对象注入环境配置信息 //通过该类对对象进行进一步操作 //registerHsfBeanPostProcessor(registry); //注册 registerBeanDefinitions(candidates, registry); }
TypeFilter:
用于过滤抽象类,接口,注解,枚举,内部类及匿名类以及应用了spring生成组件注解的类,该类 继承AbstractClassTestingTypeFilter
protected boolean match(ClassMetadata metadata) {
Class<?> clazz = transformToClass(metadata.getClassName());
if (clazz == null || !clazz.isAnnotationPresent(DataSourceComponent.class)) {
return false;
}
DataSourceComponent hsfComponent = clazz.getAnnotation(DataSourceComponent.class);
if (hsfComponent.registerBean() && isAnnotatedBySpring(clazz)) {
throw new IllegalStateException("类{" + clazz.getName() + "}已经标识了Spring组件注解,不能再指定[registerBean = true]");
}
//过滤抽象类,接口,注解,枚举,内部类及匿名类
return !metadata.isAbstract() && !clazz.isInterface() && !clazz.isAnnotation() && !clazz.isEnum()
&& !clazz.isMemberClass() && !clazz.getName().contains("$");
}
2.2 注册器
通过spring的BeanDefinitionBuilder动态生成bean对象,definition.setBeanClass(InterfaceFactoryBean.class) 指定一个实现FactoryBean的类,其返回的对象不是指定类的一个实例,其返回的是该FactoryBean的getObject方法所返回的对象。
private void registerBeanDefinitions(List<Class<?>> internalClasses, BeanDefinitionRegistry registry) { for (Class<?> clazz : internalClasses) { if (HSF_UNDERLYING_MAPPING.values().contains(clazz)) { log.debug("重复扫描{}类,忽略重复注册", clazz.getName()); continue; } BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(clazz); GenericBeanDefinition definition = (GenericBeanDefinition) builder.getRawBeanDefinition(); definition.getPropertyValues().add("interfaceClass", clazz); Enum value = clazz.getAnnotation(DataSourceComponent.class).DataSource(); definition.getPropertyValues().add("value",value); definition.setBeanClass(InterfaceFactoryBean.class); definition.setAutowireMode(GenericBeanDefinition.AUTOWIRE_BY_TYPE); if (registerSpringBean(clazz)) { log.debug("注册[{}]Bean", clazz.getName()); registry.registerBeanDefinition(ClassUtils.getShortNameAsProperty(clazz), definition); } UNDERLYING_MAPPING.put(ClassUtils.getShortNameAsProperty(clazz), clazz); } }
FactoryBean:
//实现了FactoryBean 注册器注册对象时,会调用该方法,得到返回的代理对象
public T getObject() throws Exception {
// 检查 h 不为空,否则抛异常
Objects.requireNonNull(interfaceClass);
return (T) Enhancer.create(interfaceClass,new DymicInvocationHandler());
}
DymicInvocationHandler:
接下来就是实现cglib的动态代理了
@Override
public Object intercept(Object sub, Method method, Object[] objects,MethodProxy proxy) throws Throwable {
Class<?> declaringClass = method.getDeclaringClass();
DataSourceComponent declaredAnnotation = AnnotationUtils.findAnnotation(declaringClass, DataSourceComponent.class);
//dosomthing
//。。。
Object object = proxy.invokeSuper(sub, objects);
//dosomthing
//。。。
return object;
}
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。