天天看点

JDK动态代理示例(一个注解就能帮你完成查询)

代理就是为了将被代理对象增强、扩展被代理对象的功能。说到代理,分为静态和动态。静态代理就是硬编码。而一般需要的都是无侵入的代理,就是动态代理。下面讲的就是最简单的JDK原生的动态代理。

JDK动态代理常用的类和接口有Proxy、InvocationHandler,下面用伪代码来演示一下。

这是一个MyBatis的mapper,他的对象是怎么实例化的呐?他是怎么执行sql并组装返回值的?

public interface UserMapper {

    @Select("select * from tb_user")
    public List<User> getUsers();
}      

这里来解决第二个问题,一个接口是如何执行sql并组装返回值?

public class MapperHandler implements InvocationHandler {

    private JdbcTemplate jdbcTemplate;

    public MapperHandler(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // 仅保留必要的步骤,如传参等细节不做演示
        Select select = method.getAnnotation(Select.class);
        String[] sqls = select.value();
        String sql = sqls[0];
        Class resultType = method.getReturnType();
        // 这里就不写jdbc了,借用JdbcTemplate来执行sql
        List list = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(resultType));
        return list;
    }
}      

有了InvocationHandler,那么就可以用动态代理来创建代理对象,这样就产生了mapper实例。在spring环境中就可以扔到spring里。

UserMapper mapper = (UserMapper) Proxy.newProxyInstance(
                UserMapper.class.getClassLoader(), 
                UserMapper.class.getInterfaces(), 
                new MapperInvocationHandler(jdbcTemplate));
        mapper.getUsers();      

注:上述代码为伪代码,未经过实际测试,只是讲述了一下思路。