Mybatis源码---重写一个最简单的Mybatis架构实现(二)

     前言:经过不蟹的努力,终于把Mybatis和Spring结合的代码也给整合进来啦!此处应有掌声,真的,感觉自己一下子进入了另一种天地。话不多说,代码奉上  。这三段代码,就是mybatis和spring整合的核心代码了。

1.  第一步,编写一个类似与MapperFactoryBean的类用来提供Fisher接口的代理类,代码如下:

public class FisherFactoryBean implements FactoryBean {

	private Class fishInterface;

	private boolean addToConfig = true;

	private FishingRod rod;

	public FisherFactoryBean() {

	}

	public FisherFactoryBean(Class fishInterface) {
		this.fishInterface = fishInterface;
	}

	public T getObject() throws Exception {
		return getFishingRod().getFishinger(this.fishInterface);
	}
    
       //注入FishingFactory,并设置FishingRod
	private FishingRod getFishingRod() {
		if (this.rod == null) {
			FishingFactory factory = new DefaultFishingerFactory();
			this.rod = factory.getFishingRod();
		}
		return this.rod;
	}

	public Class getObjectType() {
		return this.fishInterface;
	}

	public boolean isSingleton() {
		return true;
	}

	public void setMapperInterface(Class fishInterface) {
		this.fishInterface = fishInterface;
	}

	public Class getMapperInterface() {
		return fishInterface;
	}

	public void setAddToConfig(boolean addToConfig) {
		this.addToConfig = addToConfig;
	}

	public boolean isAddToConfig() {
		return addToConfig;
	}
}

 2. 一个类似MapperScannerConfigurer的类,用来在Bean定义完,初始化前替换Spring容器中的Fisher接口的BeanDefinitions:

@Component
public class FishingConfigurer implements BeanDefinitionRegistryPostProcessor, InitializingBean, ApplicationContextAware, BeanNameAware{
   
	private String basePackage = "com.demo.fisher";
	private Class annotationClass = Fisher.class;
	private ResourceLoader applicationContext;
	private BeanNameGenerator nameGenerator;
	private Class markerInterface;

	public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
		
	}

	public void setBeanName(String name) {
		
	}

	public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
		this.applicationContext = applicationContext;
	}

	public void afterPropertiesSet() throws Exception {
		System.out.println("");
	}

	public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
		ClassPathFisherScanner scanner = new ClassPathFisherScanner(registry);
		scanner.setMarkerInterface(this.markerInterface);
		scanner.setAnnotationClass(this.annotationClass );
		scanner.setResourceLoader(this.applicationContext);
	    scanner.setBeanNameGenerator(this.nameGenerator);
	    scanner.registerFilters();
	    scanner.scan(new String[]{this.basePackage}); 
	}

}

注意此处用@Component来声明了,不然Spring不会扫描到这个类。

3.一个仿ClassPathMapperScanner的类,用来扫描和将Fisher接口的BeanDefinition替换为代理类

public class ClassPathFisherScanner extends ClassPathBeanDefinitionScanner {

	private boolean addToConfig = true;

	private Class annotationClass;

	private Class markerInterface;

	private FisherFactoryBean fisherFactoryBean = new FisherFactoryBean();

	public ClassPathFisherScanner(BeanDefinitionRegistry registry) {
		super(registry, false);
	}

	public void setAddToConfig(boolean addToConfig) {
		this.addToConfig = addToConfig;
	}

	public void setAnnotationClass(Class annotationClass) {
		this.annotationClass = annotationClass;
	}

	public void setMarkerInterface(Class markerInterface) {
		this.markerInterface = markerInterface;
	}

	public void setfisherFactoryBean(FisherFactoryBean fisherFactoryBean) {
		this.fisherFactoryBean = fisherFactoryBean != null ? fisherFactoryBean : new FisherFactoryBean();
	}

	public void registerFilters() {
		boolean acceptAllInterfaces = true;

		if (this.annotationClass != null) {
			addIncludeFilter(new AnnotationTypeFilter(this.annotationClass));
			acceptAllInterfaces = false;
		}

		if (this.markerInterface != null) {
			addIncludeFilter(new AssignableTypeFilter(this.markerInterface) {
				@Override
				protected boolean matchClassName(String className) {
					return false;
				}
			});
			acceptAllInterfaces = false;
		}

		if (acceptAllInterfaces) {
			// default include filter that accepts all classes
			addIncludeFilter(new TypeFilter() {
				public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory)
						throws IOException {
					return true;
				}
			});
		}

		addExcludeFilter(new TypeFilter() {
			public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory)
					throws IOException {
				String className = metadataReader.getClassMetadata().getClassName();
				return className.endsWith("package-info");
			}
		});
	}

	@Override
	public Set doScan(String... basePackages) {
		Set beanDefinitions = super.doScan(basePackages);

		if (beanDefinitions.isEmpty()) {
			logger.warn("No MyBatis fisher was found in '" + Arrays.toString(basePackages)
					+ "' package. Please check your configuration.");
		} else {
			processBeanDefinitions(beanDefinitions);
		}

		return beanDefinitions;
	}

	private void processBeanDefinitions(Set beanDefinitions) {
		GenericBeanDefinition definition;
		for (BeanDefinitionHolder holder : beanDefinitions) {
			definition = (GenericBeanDefinition) holder.getBeanDefinition();

			if (logger.isDebugEnabled()) {
				logger.debug("Creating fisherFactoryBean with name '" + holder.getBeanName() + "' and '"
						+ definition.getBeanClassName() + "' fisherInterface");
			}

			definition.getConstructorArgumentValues().addGenericArgumentValue(definition.getBeanClassName()); // issue
																												// #59
			definition.setBeanClass(this.fisherFactoryBean.getClass());

			definition.getPropertyValues().add("addToConfig", this.addToConfig);

		}
	}

	@Override
	protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {
		return beanDefinition.getMetadata().isInterface() && beanDefinition.getMetadata().isIndependent();
	}

	@Override
	protected boolean checkCandidate(String beanName, BeanDefinition beanDefinition) {
		if (super.checkCandidate(beanName, beanDefinition)) {
			return true;
		} else {
			logger.warn(
					"Skipping fisherFactoryBean with name '" + beanName + "' and '" + beanDefinition.getBeanClassName()
							+ "' fisherInterface" + ". Bean already defined with the same name!");
			return false;
		}
	}

}

此刻,老泪纵横啊!终于成功了!开始读Mybatis源码到现在也小半年了,一直想做这样一件事,写一套自己的Mybatis,可是技术水平不够,或者说差点什么。但今天,算是完成了第一步了啊!以后,会慢慢把我编写的Mybatis增强模块写进去。相信终有一天,我会写出和Mybatis一样牛逼的架构!

你可能感兴趣的:(mybatis源码分析)