MapperScan实现原理分析
public class ClassPathMapperScanner extends ClassPathBeanDefinitionScanner {}
@Mapper public interface UserMapper { @Select("SELECT * FROM user WHERE id = #{userId}") User getUser(@Param("userId") String userId); @Select("SELECT * FROM user") List<User> getAll(); }
@Service public class UserService { @Autowired UserMapper userMapper; public User getUser(String userId) { return userMapper.getUser(userId); } public List<User> getAll() { return userMapper.getAll(); }
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) @Documented @Import(MapperScannerRegistrar.class) @Repeatable(MapperScans.class) public @interface MapperScan {}
public class MapperScannerRegistrar implements ImportBeanDefinitionRegistrar, ResourceLoaderAware {}
registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry)
@Import(MyImportBeanDefinitionRegistrar.class) @Retention(RetentionPolicy.RUNTIME) public @interface MyScan { }
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar { @Override public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { //得到bd //根据包名扫描所有的class,这里就直接写死了 BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(UserMapper.class); GenericBeanDefinition beanDefinition = (GenericBeanDefinition) builder.getBeanDefinition(); //System.out.println(beanDefinition.getBeanClassName()); //通过构造函数注入,spring内部调用下面指定的 MyFactoryBean的构造 beanDefinition.getConstructorArgumentValues().addGenericArgumentValue(beanDefinition.getBeanClassName()); //指定bd类型,因为它是一个代理对象,我们只能通过FactoryBean去动态获取其类型 beanDefinition.setBeanClass(MyFactoryBean.class); registry.registerBeanDefinition("userMapper", beanDefinition); }
public class MyFactoryBean implements FactoryBean, InvocationHandler { Class clazz; //通过构造函数注入 public MyFactoryBean(Class clazz) { this.clazz = clazz; } @Override public Object getObject() throws Exception { Class[] clazzs = new Class[]{clazz}; Object instance = Proxy.newProxyInstance(this.getClass().getClassLoader(), clazzs, this); return instance; } @Override public Class<?> getObjectType() { return clazz; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("proxy"); //可以动态拿到每个方法注解的sql语句 Method method1 = proxy.getClass().getInterfaces()[0].getMethod(method.getName(), String.class); Select annotations = method1.getDeclaredAnnotation(Select.class); System.out.println(annotations.value()[0]); return null;