`
raymond.chen
  • 浏览: 1441382 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

基于JDK动态代理实现Mybatis的Mapper功能

    博客分类:
  • Java
 
阅读更多

Mybatis通过定义Mapper接口类,类中的方法与mapper的xml文件对应起来,然后在Service类自动注入Mapper接口类即可调用其方法。

 

我们可以使用JDK的动态代理机制自己实现这样的Mapper功能。

 

先自定义两个注解类:

@Target(ElementType.TYPE) //在接口和类上使用
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface MapperEnable {
	boolean enable() default true;
}


@Target(ElementType.METHOD) //在方法上使用
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface MethodEnable {
	boolean enable() default true;
}

 

定义Mapper接口类:

     接口上和方法上添加自定义注解,用于后续做特殊业务处理

@MapperEnable(enable=true)
public interface UserMapper {
	@MethodEnable(enable=true)
	public User getUserById(Long id);
	
	@MethodEnable(enable=false)
	public void print();
}

 

定义Mapper接口的代理类,代理类需要实现InvocationHandler接口

/**
 * 代理类
 */
public class MapperProxy implements InvocationHandler {
	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		System.out.println("接口类名:" + method.getDeclaringClass().getName());
		
		System.out.println("接口上的注解类: " + Arrays.toString(method.getDeclaringClass().getAnnotations()));
		
		System.out.println("接口方法名:" + method.getName());
		System.out.println("输入参数:" + Arrays.toString(args));

		System.out.println("方法上的注解类: " + Arrays.toString(method.getAnnotations()));
		
		if(method.isAnnotationPresent(MethodEnable.class)){ //方法上有指定注解
			MethodEnable methodEnable = method.getAnnotation(MethodEnable.class); //获取该注解类
			boolean b = methodEnable.enable();
			if(b){
				//此处根据接口类名、方法名和参数值等信息构造对应的sql语句并获取数据
				return new User(100L, "cjm", "123", null);
			}else{
				System.out.println("no permission");
				return null;
			}
		}
		
		return null;
	}
}

 

通过动态代理获取接口类的代理对象,并调用其方法

public class ProxyTest {
	public static void main(String[] args) {
		//通过动态代理获取接口的代理对象
		UserMapper mapper = getMapper(UserMapper.class);
		System.out.println(mapper.getClass().getName());
		
		//调用接口方法
		User user = mapper.getUserById(1L);
		String username = Optional.ofNullable(user).map(u -> u.getUsername()).orElse("");
		System.out.println(username);
		
		mapper.print();
	}
	
	/**
	 * 利用Proxy类的newProxyInstance方法创建一个动态代理对象
	 * @param clazz 接口类
	 */
	@SuppressWarnings("unchecked")
	private static <T> T getMapper(Class<T> clazz){
		return (T)Proxy
				.newProxyInstance(clazz.getClassLoader(), new Class[]{clazz}, new MapperProxy());
	}
}

 

执行后的结果如下:

接口的代理对象:com.sun.proxy.$Proxy0

接口类名:com.seasy.jdk8.proxy.UserMapper
接口上的注解类: [@com.seasy.jdk8.proxy.MapperEnable(enable=true)]
接口方法名:getUserById
输入参数:[1]
方法上的注解类: [@com.seasy.jdk8.proxy.MethodEnable(enable=true)]
cjm

接口类名:com.seasy.jdk8.proxy.UserMapper
接口上的注解类: [@com.seasy.jdk8.proxy.MapperEnable(enable=true)]
接口方法名:print
输入参数:null
方法上的注解类: [@com.seasy.jdk8.proxy.MethodEnable(enable=false)]
no permission

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics