zoukankan      html  css  js  c++  java
  • 《Java Spring框架》模拟Mybatis整合Spring

    前言

    为了更好的了解Spring的扩展,于是便去研究了MyBatis整合Spring的Jar代码。通过代码模拟写一个Mybatis整合Spring作为笔记留念。

    代码

    目录结构:

    MapScan 

    import com.my.postprocessor.MyImportBeanDefinitionRegistrar;
    import org.springframework.context.annotation.Import;
    
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    
    @Retention(RetentionPolicy.RUNTIME)
    @Import(MyImportBeanDefinitionRegistrar.class)
    public @interface MapScan {
        String value() default "";
    }

    MyFactoryBean 

    import com.my.mybatis.MySqlSession;
    import org.springframework.beans.factory.FactoryBean;
    import org.springframework.stereotype.Component;
    
    /**
     * 猜想MyBatis为什么要通过FactoryBean来注入Spring,
     * 而不是直接扫描DAO接口生成Definition的时候直接将代理类也set进Definition中。
     */
    @Component
    public class MyFactoryBean implements FactoryBean {
    
        Class mapperInterface;
    
        @Override
        public Object getObject() throws Exception {
            MySqlSession mySqlSession = new MySqlSession();
            Object mapper = mySqlSession.getMapper(mapperInterface);
            return mapper;
        }
    
        @Override
        public Class<?> getObjectType() {
            return mapperInterface;
        }
    
        public void setMapperInterface(Class mapperInterface) {
            this.mapperInterface = mapperInterface;
        }
    }

    ClassPathMapperScanner

    import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
    import org.springframework.beans.factory.config.BeanDefinitionHolder;
    import org.springframework.beans.factory.support.BeanDefinitionRegistry;
    import org.springframework.context.annotation.ClassPathBeanDefinitionScanner;
    import org.springframework.core.type.filter.TypeFilter;
    
    import java.util.Set;
    
    public class ClassPathMapperScanner extends ClassPathBeanDefinitionScanner {
    
        public ClassPathMapperScanner(BeanDefinitionRegistry registry) {
            super(registry,false);
        }
    
        @Override
        public void addIncludeFilter(TypeFilter includeFilter) {
            super.addIncludeFilter(includeFilter);
        }
    
        @Override
        public Set<BeanDefinitionHolder> doScan(String... basePackages) {
            return super.doScan(basePackages);
        }
    
        protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {
            return beanDefinition.getMetadata().isInterface() && beanDefinition.getMetadata().isIndependent();
        }
    }

    AccountInfoDao

    import org.apache.ibatis.annotations.Select;
    
    public interface AccountInfoDao {
    
        @Select("select * from taccount")
        public String getAccount();
    }

    AccountInfoDao1

    import org.apache.ibatis.annotations.Select;
    
    public interface AccountInfoDao1 {
    
        @Select("select * from taccount1")
        public String getAccount();
    }

    MySqlSession

    import org.apache.ibatis.annotations.Select;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    
    public class MySqlSession {
    
        class MyInvocationHandler implements InvocationHandler {
            @Override
            public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
                        // 获取方法上的注解
                Select annotation = method.getAnnotation(Select.class);
    
                System.out.println("打开数据库连接");
    
                System.out.println("执行SQL:" + annotation.value()[0]);
    
                System.out.println("关闭数据库连接");
    
                if(method.getName().equals("toString")){
                    return "toString";
                }
    
                return "动态代理反馈";
            }
        }
    
        public Object getMapper(Class clazz){
            MyInvocationHandler myInvocationHandler = new MyInvocationHandler();
            Object object = Proxy.newProxyInstance(MySqlSession.class.getClassLoader(),
                    new Class[]{clazz}, myInvocationHandler);
            return object;
        }
    }

    MyImportBeanDefinitionRegistrar

    import com.my.annotation.MapScan;
    import com.my.bean.MyFactoryBean;
    import com.my.config.ClassPathMapperScanner;
    import com.my.dao.AccountInfoDao;
    import com.my.dao.AccountInfoDao1;
    import org.mybatis.spring.annotation.MapperScan;
    import org.springframework.beans.factory.config.BeanDefinitionHolder;
    import org.springframework.beans.factory.support.AbstractBeanDefinition;
    import org.springframework.beans.factory.support.BeanDefinitionBuilder;
    import org.springframework.beans.factory.support.BeanDefinitionRegistry;
    import org.springframework.beans.factory.support.GenericBeanDefinition;
    import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
    import org.springframework.core.annotation.AnnotationAttributes;
    import org.springframework.core.annotation.MergedAnnotations;
    import org.springframework.core.type.AnnotationMetadata;
    import org.springframework.core.type.classreading.MetadataReader;
    import org.springframework.core.type.classreading.MetadataReaderFactory;
    import org.springframework.core.type.filter.TypeFilter;
    
    import java.io.IOException;
    import java.util.ArrayList;
    import java.util.Iterator;
    import java.util.List;
    import java.util.Set;
    
    public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
        @Override
        public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
    
            AnnotationAttributes annotations = AnnotationAttributes.fromMap(importingClassMetadata.getAnnotationAttributes(MapScan.class.getName()));
            ClassPathMapperScanner classPathMapperScanner = new ClassPathMapperScanner(registry);
            classPathMapperScanner.addIncludeFilter((metadataReader,metadataReaderFactory) -> { return true; });
            Set<BeanDefinitionHolder> beanDefinitionHolders = classPathMapperScanner.doScan((String)annotations.get("value"));
    
            Iterator<BeanDefinitionHolder> it = beanDefinitionHolders.iterator();
            while (it.hasNext()) {
                BeanDefinitionHolder beanDefinitionHolder = it.next();
                GenericBeanDefinition definition = (GenericBeanDefinition)beanDefinitionHolder.getBeanDefinition();
                definition.getPropertyValues().addPropertyValue("mapperInterface",definition.getBeanClassName());
                definition.setBeanClass(MyFactoryBean.class);
            }
        }
    }

     IndexService

    import com.my.dao.AccountInfoDao;
    import com.my.dao.AccountInfoDao1;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Component;
    
    @Component
    public class IndexService {
    
        @Autowired
        AccountInfoDao accountInfoDao;
    
        @Autowired
        AccountInfoDao1 accountInfoDao1;
    
        public void test(){
            System.out.println(accountInfoDao.getAccount());
            System.out.println("===============================");
            System.out.println(accountInfoDao1.getAccount());
        }
    }

    MyTest

    import com.my.AppConfig;
    import com.my.service.IndexService;
    import org.springframework.context.annotation.AnnotationConfigApplicationContext;
    
    public class MyTest {
        public static void main(String[] args) {
            AnnotationConfigApplicationContext ac
                    = new AnnotationConfigApplicationContext(AppConfig.class);
    
            IndexService indexService = ac.getBean(IndexService.class);
            indexService.test();
        }
    }

     AppConfig

    import com.my.annotation.MapScan;
    import org.springframework.context.annotation.ComponentScan;
    import org.springframework.context.annotation.Configuration;
    
    @Configuration
    @ComponentScan("com.my")
    @MapScan("com.my.dao")
    public class AppConfig {
    }

    依赖包只需要一个即可:spring-context

    运行结果:

    总结

    从别人的代码里面学习如何写优美的代码。

    This moment will nap, you will have a dream; But this moment study,you will interpret a dream.
  • 相关阅读:
    近来有客户要求用table显示一大串数据,由于滚动后就看不到表头,很不方便,所以想到这个效果。
    js如何取当前日期时间/格式为:yyyymmdd hh:mm:ss
    jdk源码分析 – Thread线程类源码分析
    Swing中的MVC
    编程生涯的一次思想总结
    怎样成为高手
    浅谈测试驱动开发(TDD)
    Java RMI之HelloWorld篇(EJB都是建立在rmi基础之上的)
    Swing框架之Model
    EJB 工作原理
  • 原文地址:https://www.cnblogs.com/jssj/p/14726388.html
Copyright © 2011-2022 走看看