@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface Select {
String value() default “”;
}
2、Dao层接口(IUserDao)
public interface IUserDao {
@Select(“select * from user where id = #{id}”)
String selectById(Integer id);
}
3、代理类(MapperFactoryBean)
@Slf4j
public class MapperFactoryBean implements FactoryBean {
private Class mapperInterface;
public MapperFactoryBean(Class mapperInterface) {
this.mapperInterface = mapperInterface;
}
@Override
public T getObject() throws Exception {
InvocationHandler handler = (proxy, method, args) -> {
Select select = method.getAnnotation(Select.class);
log.info(“query sql:{}”, select.value());
log.info(“param:{}”, args[0]);
return “1, 张三(模拟从数据库查询的返回)”;
};
return (T) Proxy.newProxyInstance(this.getClass().getClassLoader(), new Class[]{mapperInterface}, handler);
}
@Override
public Class<?> getObjectType() {
return mapperInterface;
}
@Override
public boolean isSingleton() {
return true;
}
}
MapperFactoryBean 通过继承 FactoryBean ,提供bean对象,也就是方法T getObject() 。在方法 getObject()
《一线大厂Java面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义》
【docs.qq.com/doc/DSmxTbFJ1cmN1R2dB】 完整内容开源分享
中提供类的代理以及模拟对sql语句的处理,这里包含了用户调用dao层方法时候的处理逻辑。
4、Bean定义注册到Spring容器(RegisterBeanFactory)
public class RegisterBeanFactory implements BeanDefinitionRegistryPostProcessor {
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
beanDefinition.setBeanClass(MapperFactoryBean.class);
beanDefinition.setScope(“singleton”);
beanDefinition.getConstructorArgumentValues().addGenericArgumentValue(IUserDao.class);
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(beanDefinition, “userDao”);
BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, registry);
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
}
}
我们将代理的bean交给spring容器管理,以方便我们获取到代理的bean。这里是在spring中关于⼀个bean注册过程的源码。GenericBeanDefinition ,用于定义⼀个bean的基本信息,也包括可以透传给构造函数信息,最后使用BeanDefinitionReaderUtils.registerBeanDefinition,进行bean的注册,也就是注册到DefaultListableBeanFactory 中。
5、spring-mybatis.xml
<?xml version="1.0" encoding="UTF-8"?><beans xmlns=“http://www.springframework.org/schema/beans”
xmlns:xsi=“http://www.w3.org/2001/XMLSchema-instance”
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
6、测试
@SpringBootTest
public class ApplicationTests {
@Test
public void test() {
BeanFactory beanFactory = new ClassPathXmlApplicationContext(“spring-mybatis.xml”);
IUserDao userDao = beanFactory.getBean(“userDao”, IUserDao.class);
String res = userDao.selectById(1);
System.out.println("res = " + res);
}
本文深入解析了Spring MyBatis的动态代理实现,展示了如何通过MapperFactoryBean创建DAO层接口的代理实例,并在其中处理SQL逻辑。同时,详细介绍了Bean定义的注册过程,以及在测试中如何从Spring容器获取并使用这个代理bean。
4444

被折叠的 条评论
为什么被折叠?



