1、使用动态代理实现扫描的接口
public class MapperFactoryBean implements FactoryBean {
private Class mapper;
public MapperFactoryBean(Class mapper){
this.mapper = mapper;
}
@Override
public Object getObject() throws Exception {
return Proxy.newProxyInstance(MapperFactoryBean.class.getClassLoader(), new Class[]{mapper}, new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if(Object.class.equals(method.getDeclaringClass())){
return method.invoke(this,args);
}else {
System.out.println("执行SQL");
}
return null;
}
});
}
@Override
public Class<?> getObjectType() {
return mapper;
}
}
2、创建Mybatis的Mapper扫描注解
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Documented
@Import(MapperImportBeanDefinitionRegistrar.class)
public @interface EnableMapperScan {
String value();
String[] packages() default {};
}
3、核心注册代理类
public class MapperImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar, ResourceLoaderAware, EnvironmentAware, Ordered {
private Environment environment;
private ResourceLoader resourceLoader;
private String[] packages;
private String resourcePattern = DEFAULT_RESOURCE_PATTERN;
static final String DEFAULT_RESOURCE_PATTERN = "**/*.class";
private ResourcePatternResolver resourcePatternResolver;
private MetadataReaderFactory metadataReaderFactory;
@Override
public void setEnvironment(Environment environment) {
this.environment = environment;
}
@Override
public void setResourceLoader(ResourceLoader resourceLoader) {
this.resourceLoader = resourceLoader;
}
@Override
public int getOrder() {
return 0;
}
@Override
public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry beanDefinitionRegistry) {
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition();
AbstractBeanDefinition beanDefinition = builder.getBeanDefinition();
beanDefinition.setBeanClass(MapperFactoryBean.class);
Map<String, Object> defaultAttrs = annotationMetadata.getAnnotationAttributes(EnableMapperScan.class.getName(), true);
String[] value = (String[]) defaultAttrs.get("value");
if(ArrayUtils.isNotEmpty(value)){
this.packages = value;
}else {
String[] basePackages = (String[]) defaultAttrs.get("packages");
if(ArrayUtils.isNotEmpty(basePackages)){
this.packages = basePackages;
}
}
//创建类路径包扫描
for (String aPackage : packages) {
String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
resolveBasePackage(aPackage) + '/' + this.resourcePattern;
try {
Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath);
for (Resource resource : resources) {
if(resource.isReadable()){
MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource);
String className = metadataReader.getClassMetadata().getClassName();
Class<?> aClass = Class.forName(className);
beanDefinition.getConstructorArgumentValues().addGenericArgumentValue(aClass);
beanDefinitionRegistry.registerBeanDefinition(className,beanDefinition);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
public final MetadataReaderFactory getMetadataReaderFactory() {
if (this.metadataReaderFactory == null) {
this.metadataReaderFactory = new CachingMetadataReaderFactory();
}
return this.metadataReaderFactory;
}
protected String resolveBasePackage(String basePackage) {
return ClassUtils.convertClassNameToResourcePath(this.environment.resolveRequiredPlaceholders(basePackage));
}
private ResourcePatternResolver getResourcePatternResolver() {
return this.resourcePatternResolver = ResourcePatternUtils.getResourcePatternResolver(resourceLoader);
}
}
4、启动类加上启用注解
@SpringBootApplication
@EnableMapperScan("com.liangjiachu.liangjiachuframework.mybatis.mapper")
public class LiangjiachuFrameworkApplication {
public static void main(String[] args) {
ConfigurableApplicationContext applicationContext = SpringApplication.run(LiangjiachuFrameworkApplication.class, args);
UserMapper userMapper = applicationContext.getBean(UserMapper.class);
userMapper.getUserInfo();
}
}