场景:模拟mabatis scanmapper 实现dao。读者可以拷贝我的代码进行跑一波替换一下,注意里面很多包路径需要替换。
写一个model
public class Model {
}
写一个仓储接口
@Repository
public interface ModelMapper {
void insert(Model model);
}
使用工厂模式,这里只是模拟假装实现。
public class MapperFactoryBean implements FactoryBean {
Class<?> proxyInstanceClass;
public MapperFactoryBean(Class<?> proxyInstanceClass) {
this.proxyInstanceClass = proxyInstanceClass;
}
@Override
public Object getObject() throws Exception {
return Proxy.newProxyInstance(proxyInstanceClass.getClassLoader(), new Class[]{proxyInstanceClass}, new ModelMapperInvocationHandler());
}
@Override
public Class<?> getObjectType() {
return proxyInstanceClass;
}
@Override
public boolean isSingleton() {
return true;
}
class ModelMapperInvocationHandler implements InvocationHandler {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("get sql");
System.out.println("get get link");
System.out.println("execute sql");
System.out.println("close link");
return 0;
}
}
}
MapperScanPostProcessor 实现postProcessBeanDefinitionRegistry方法通过包扫描方式扫描Repository注解的接口,然后修改它的bean定义。
public class MapperScanPostProcessor implements BeanDefinitionRegistryPostProcessor {
ApplicationContext applicationContext;
public void setApplicationContext(ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
}
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
MapScanner mapScanner = new MapScanner(registry);
mapScanner.setResourceLoader(applicationContext);
mapScanner.scan("com.jack.ascp.purchase.app.test.spring.beanfactorypostprocessor");
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
}
class MapScanner extends ClassPathBeanDefinitionScanner {
public MapScanner(BeanDefinitionRegistry registry) {
super(registry);
}
@Override
protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {
return beanDefinition.getMetadata().isInterface();
}
@Override
protected void registerDefaultFilters() {
this.addIncludeFilter(new AnnotationTypeFilter(Repository.class));
}
@Override
protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
Set<BeanDefinitionHolder> beanDefinitionHolders = super.doScan(basePackages);
for (BeanDefinitionHolder beanDefinitionHolder : beanDefinitionHolders) {
BeanDefinition beanDefinition = beanDefinitionHolder.getBeanDefinition();
String className = beanDefinition.getBeanClassName();
TypedStringValue typedStringValue = new TypedStringValue(className);
beanDefinition.setBeanClassName("com.jack.ascp.purchase.app.test.spring.beanfactorypostprocessor.MapperFactoryBean");
beanDefinition.getConstructorArgumentValues().addGenericArgumentValue(typedStringValue);
}
return beanDefinitionHolders;
}
}
}
再假装写一个service层
public class ModelService {
private ModelMapper modelMapper;
// public void setModelMapper(ModelMapper modelMapper) {
// this.modelMapper = modelMapper;
// }
public ModelService(ModelMapper modelMapper) {
this.modelMapper = modelMapper;
}
public void insert() {
modelMapper.insert(new Model());
}
}
我们的processor是可以处理多个mapper的 这里随便加一个demo
@Repository
public interface PersonMapper {
int update(Object o);
}
modelmapper.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-3.1.xsd
">
<!--<bean class="com.jack.ascp.purchase.app.test.spring.beanfactorypostprocessorstprocessor.MapperFactoryBean"/>-->
<bean class="com.jack.ascp.purchase.app.test.spring.beanfactorypostprocessor.MapperScanPostProcessor" />
<bean class="com.jack.ascp.purchase.app.test.spring.beanfactorypostprocessor.ModelService" autowire="constructor"/>
</beans>
测试代码:
public class PostProcessorApplication {
public static void main(String[] args) {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("modelmapper.xml");
ModelMapper modelMapper = context.getBean(ModelMapper.class);
modelMapper.insert(new Model());
ModelService modelService = context.getBean(ModelService.class);
modelService.insert();
PersonMapper personMapper = context.getBean(PersonMapper.class);
personMapper.update(new Object());
}
}
结果