手写Mybatis和Spring整合(二)

如果看过我上一篇的人都知道我虽然实现了自己手写Mybatis底层源码,并且注入到了Spring的ioc容器中也是可以用的,Spring底层默认调用的是我们自己手写的Mybatis底层代码,但是这里是由一个问题的就是我们只能一个一个dao层接口注入,如果一旦多了就比较麻烦了,下面我将手写一种批量导入dao层接口的方法

具体代码如下

dao层接口

在这里插入图片描述

在这里插入图片描述

主入口

public class SpringDome {


    public static void main(String[] args) {
        AnnotationConfigApplicationContext  applicationContext=new AnnotationConfigApplicationContext(SZConfiguration.class);
        ServiceImpl bean = applicationContext.getBean(ServiceImpl.class);
        bean.query();
    }
}

service

@Service
public class ServiceImpl {

    @Autowired
    UserMapper mapper;

    @Autowired
    Adminmapper adminmapper;

    public void query(){

        mapper.selectAllUser();


        adminmapper.selectAllUser();
    }
}

spring主配置类


@Configuration
@ComponentScan("com.ssm.proxy")
@SZScan(value = "com.ssm.dao")
public class SZConfiguration {

}

在这里我自己写了一个注解,就相当一@MapperScan注解作用是一样的


@Retention(RetentionPolicy.RUNTIME)
@Import(SZBeanDefinitionRegistry.class)
public @interface SZScan {
    String[] value() default {};
}

FactoryBean 需要注意的是在这里SZFactoryBean就相当于MapperFactoryBean。作用就是生成一个dao层接口的代理类并注入到Sprig容器中,在这里如果想要生成的代理类生效就必须让SZFactoryBean生效,你或许会问我为什么不加spring的注解让他生效,如果加上注解的话那么这时候mapperinterface这个属性的参数你怎么传呢?

public class SZFactoryBean implements FactoryBean {
    private  Class mapperinterface;

    public void setMapperinterface(Class mapperinterface) {
        this.mapperinterface = mapperinterface;
    }

    @Override
    public Object getObject() throws Exception {
        Object mapper = SZSession.getMapper(mapperinterface);
        return mapper;
    }

    @Override
    public Class<?> getObjectType() {
        return mapperinterface;
    }
}

解决办法

public class SZBeanDefinitionRegistry implements ImportBeanDefinitionRegistrar {

    private ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
    private MetadataReaderFactory metadataReaderFactory = new CachingMetadataReaderFactory(this.resourcePatternResolver);

    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry, BeanNameGenerator importBeanNameGenerator) {
       try {
           AnnotationAttributes metadata=AnnotationAttributes.fromMap(importingClassMetadata.getAnnotationAttributes(SZScan.class.getName()));
           List<String> list=new ArrayList<>();
           for (String value : metadata.getStringArray("value")) {
               if(StringUtils.hasText(value)){
                   list.add(value);
               }
           }
         //我上面获取list中的数据是  com.ssm.dao 也就是我在Spring主配置类中加的@SZScan中
         //的value值

          //下面通过反射获取包中所有的接口也就是com.ssm.dao中的所有接口
           Set<Class> set=null;
           for (String em : list) {
               set=this.doScan(em);
           }
           for (Class aClass : set) {
              //循环获取到的包中所有的接口,使用spring的扩展对bean进行初始化
              //在这里需要注意的是spring在初始化的时候不是根据你的类初始化的
              //而是根据你的每个类对应的每一个BeanDefinition来进行初始化的
               BeanDefinitionBuilder beanDefinitionBuilder=BeanDefinitionBuilder.genericBeanDefinition(SZFactoryBean.class);
               AbstractBeanDefinition beanDefinition = beanDefinitionBuilder.getBeanDefinition();
               MutablePropertyValues propertyValues = beanDefinition.getPropertyValues();
               propertyValues.add("mapperinterface",aClass.getName());

               registry.registerBeanDefinition(aClass.getSimpleName(),beanDefinition);
           }

       }
       catch (Exception e){

       }
    }

    public Set<Class> doScan(String basePackage) {
        Set<Class> classes = new HashSet<Class>();
        try {
            String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX
                    + org.springframework.util.ClassUtils
                    .convertClassNameToResourcePath(SystemPropertyUtils
                            .resolvePlaceholders(basePackage))
                    + "/**/*.class";
            Resource[] resources = this.resourcePatternResolver
                    .getResources(packageSearchPath);
            for (int i = 0; i < resources.length; i++) {
                Resource resource = resources[i];
                if (resource.isReadable()) {
                    MetadataReader metadataReader = this.metadataReaderFactory.getMetadataReader(resource);
                    try {
                        classes.add(Class.forName(metadataReader
                                .getClassMetadata().getClassName()));
                    } catch (ClassNotFoundException e) {
                        e.printStackTrace();
                    }
                }
            }
        } catch (IOException ex) {
            throw new BeanDefinitionStoreException(
                    "I/O failure during classpath scanning", ex);
        }
        return classes;
    }


}

JDk动态代理生成dao层接口代理类

public class SZSession {
    public static Object getMapper(Class clazz){
        Class[] classz=new Class[]{clazz};
        Object object=Proxy.newProxyInstance(clazz.getClassLoader(),classz,new SZInvocationHandler());
        return object;
    }
}


public class SZInvocationHandler implements InvocationHandler
{


    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("proxy============="+proxy.getClass().getName());
        Select annotation = method.getAnnotation(Select.class);
        String sql = annotation.value()[0];
        System.out.println(sql);
       /* Class.forName("com.mysql.jdbc.Driver");
        Connection root = DriverManager.getConnection("jdbc:mysql://localhost:3306/stu", "root", "123");
        PreparedStatement preparedStatement = root.prepareStatement(sql);
        ResultSet resultSet = preparedStatement.executeQuery();
        List<User> list=new ArrayList<>();
        while (resultSet.next()){
            User user=new User();
            user.setId(resultSet.getString("id"));
            user.setUsername(resultSet.getString("username"));
            user.setPassword(resultSet.getString("password"));
            list.add(user);
        }
        System.out.println(list);*/
        return null;
    }
}

执行结果 可以看到我全部获取到了dao层接口的sql语句,实现的

proxy=============com.sun.proxy.$Proxy14
select * from user
proxy=============com.sun.proxy.$Proxy15
select * from tem

总结 : 上述代码给大家展示了spring和mybatis底层是如何进行整合的还有就是@MapperScan大概的工作流程以及mybatis底层是如何生成接口的代理类的,希望对大家理解mybatis和Spring整合有一定帮助

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值