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;