通過自定義注解,簡單模擬Mybatis通過注解查詢SQL。
首先,創(chuàng)建自定義注解@MyDao和@MySelect。
MyDao.java
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyDao {
String[] value() default {};
}
MySelect.java
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface MySelect {
String[] value() default {};
}
創(chuàng)建UserDao,使用上面的自定義注解。
UserDao.java
@MyDao
public interface UserDao {
@MySelect("select * from sys_user where id = #{id}")
String getNameById(String id);
}
MyInterceptor.java
處理@MySelect注解的方法實現(xiàn)。
@Slf4j
@Component
public class MyInterceptor implements InvocationHandler {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
MySelect mySelect = method.getAnnotation(MySelect.class);
if (mySelect != null) {
String sql = mySelect.value()[0];
// 解析sql中的參數(shù)
Map<String, Object> paramMap = new HashMap<>();
Parameter[] parameters = method.getParameters();
for (int i = 0; i < parameters.length; i++) {
paramMap.put(parameters[i].getName(), args[i]);
}
// 執(zhí)行sql
String workSql = format(sql, paramMap);
log.info("work sql: {}", workSql);
}
return null;
}
/**
* 替換sql中的參數(shù)
*/
private String format(String str, Map<String, Object> paramMap) {
if (MapUtil.isEmpty(paramMap)) {
return str;
}
AtomicReference<String> text = new AtomicReference<>(str);
paramMap.forEach((paramName, paramValue) -> {
String value = String.valueOf(paramValue);
if (paramValue instanceof String) {
value = "'" + value + "'";
}
text.set(StringUtils.replace(text.get(), "#{" + paramName + "}", value));
});
return text.get();
}
}
InterfaceDynamicRegister.java
處理@MyDao的注解的Mapper。
@Configuration
public class InterfaceDynamicRegister implements ImportBeanDefinitionRegistrar {
private static final String BASE_PACKAGE = "com.jjh.business.mapper"; // 指定掃描的包路徑
private static final String RESOURCE_PATTERN = "/**/*.class"; // 指定掃描的文件類型
@SneakyThrows
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
// 掃描所有包含MyDao注解的類
List<Class<?>> classes = new ArrayList<>();
PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
ClassUtils.convertClassNameToResourcePath(BASE_PACKAGE) + RESOURCE_PATTERN;
Resource[] resources = resolver.getResources(packageSearchPath);
SimpleMetadataReaderFactory metadataReaderFactory = new SimpleMetadataReaderFactory();
ClassPathScanningCandidateComponentProvider scanner = new ClassPathScanningCandidateComponentProvider(false);
scanner.addIncludeFilter(new AnnotationTypeFilter(MyDao.class));
for (Resource resource : resources) {
if (resource.isReadable()) {
MetadataReader metadataReader = metadataReaderFactory.getMetadataReader(resource);
String className = metadataReader.getClassMetadata().getClassName();
Class<?> clazz = Class.forName(className);
classes.add(clazz);
}
}
// 創(chuàng)建接口的實現(xiàn)類并注冊到spring
for (Class<?> clazz : classes) {
// 將代理類實例注冊到 Spring 容器中
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(clazz);
// 調(diào)用BeanDefinition的setInstanceSupplier方法,傳入一個Lambda表達式,該表達式返回代理對象的實例
builder.getBeanDefinition().setInstanceSupplier(() -> {
// CGlib代理
// Enhancer enhancer = new Enhancer();
// enhancer.setSuperclass(clazz);
// enhancer.setCallback(new MyInterceptor());
// Object proxyInstance = enhancer.create();
// return proxyInstance;
// JDK代理
return Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), new Class[]{clazz},
new MyInterceptor());
});
registry.registerBeanDefinition(clazz.getSimpleName(), builder.getBeanDefinition());
}
}
}
TestController.java
調(diào)用userDao,查詢數(shù)據(jù)。
@Slf4j
@RestController
@RequestMapping("/test")
public class TestController {
@Autowired
private UserDao userDao;
@GetMapping("/do_sql_select")
public Object doSqlSelect() {
log.info("do_sql_select is do. {}", System.currentTimeMillis());
userDao.getNameById("0001");
return "Ok";
}
}
pom 依賴文章來源:http://www.zghlxwxcb.cn/news/detail-601759.html
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
調(diào)用 http://localhost:8080/test/do_sql_select
即可執(zhí)行userDao方法。文章來源地址http://www.zghlxwxcb.cn/news/detail-601759.html
到了這里,關(guān)于簡單模擬Mybatis通過注解查詢SQL的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!