04-动态代理实现mybatis简易版

首先我们在调用Mapper的相关方法时实现动态代理,将相关参数封装好,这样我们调用的方法时实际上我们将所有的方法调用都封装了起来。外部只需要调用一个接口即可。下面的代码有很多缺点,仅作参考

@Data
public class Blog {

	private String id;
	private String name;

}
public interface BlogMapper {
	Blog queryBlog(int id);
}
public class TestMain {

    public static void main(String[] args) {
        MySqlSession mySqlSession = new MySqlSession();
        BlogMapper blogMapper =  mySqlSession.getMapper(BlogMapper.class);
        Blog blog = blogMapper.queryBlog(1);
        System.out.println(blog);
    }
}
public class MySqlSession {
    private MyConfiguration myConfiguration = new MyConfiguration();

    public <T> T select(String sql, String param){
        ConfigXmlMsg configXmlMsg = ConfigXmlMsg.getConfigXmlMsg();
        try {
            Class.forName(configXmlMsg.getDriverClassName());
            Connection con = DriverManager.getConnection(configXmlMsg.getUrl()
            ,configXmlMsg.getUsername()
            ,configXmlMsg.getPassword());
            Statement st = con.createStatement();
            ResultSet rs = st.executeQuery(new MyConfiguration().getMapperMsg().getSql()+param);
            System.out.println("执行的语句是:"+new MyConfiguration().getMapperMsg().getSql()+param);
            Blog blog = new Blog();
            while (rs.next()){
                blog.setId(rs.getString(1));
                System.out.println("id结果:"+blog.getId());
                blog.setName(rs.getString(2));
                System.out.println("name结果:"+blog.getName());
            }
            return (T)blog;
        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }

    //<T> T表示返回的类型由调用者决定
    //这里实际上交给MyMapperProxy先处理
    @SuppressWarnings("unchecked")
    public <T> T getMapper(Class<T> clas){
        //动态代理调用
        return (T) Proxy.newProxyInstance(clas.getClassLoader(),new Class[]{clas},
                new MyMapperProxy(myConfiguration,this));
    }
}
public class MyMapperProxy implements InvocationHandler{
	//这里没有使用xml而是使用两个实体类代替
	private  MySqlSession mySqlsession;
	
	private MyConfiguration myConfiguration;
     
    public MyMapperProxy(MyConfiguration myConfiguration, MySqlSession mySqlsession) {
        this.myConfiguration=myConfiguration;  
        this.mySqlsession=mySqlsession;  
    }  

	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		MapperXmlMsg mapperXmlMsg = myConfiguration.getMapperMsg();
		//先验证我们的mapper.xml文件中有没有调用的接口类,这里只用了一个mapper举例
		if(!method.getDeclaringClass().getName().equals(mapperXmlMsg.getInterFaceName())){
			return  null;
		}
		Object object = null;
		//xml中是否有对应的方法
		if(method.getName().equals(mapperXmlMsg.getFunctionName())){
			object = mySqlsession.select(mapperXmlMsg.getSql(),String.valueOf(args[0]));
		}

	     return object;
	}
	

}
public class MyConfiguration {
	
    @SuppressWarnings("rawtypes")
    public MapperXmlMsg getMapperMsg(){
        //实际应该读取xml并封装为一个对象,这里为了理解直接用写好的类代替
		MapperXmlMsg mapperXmlMsg = new MapperXmlMsg();
		//对应namespace
		mapperXmlMsg.setInterFaceName("com.mapper.BlogMapper");
		//对应id
		mapperXmlMsg.setFunctionName("queryBlog");
		mapperXmlMsg.setSql("select * from blog where id = ");
        return mapperXmlMsg;
    }
}
@Data
public class MapperXmlMsg {
    //真实情况应该使用DOM4j解析后封装
    private String InterFaceName;

    private String FunctionName;

    private String Sql;
}
@Data
public class ConfigXmlMsg {

    private String driverClassName;
    private String url;
    private String username;
    private String password;

    public static ConfigXmlMsg getConfigXmlMsg(){
        ConfigXmlMsg configXmlMsg = new ConfigXmlMsg();
        configXmlMsg.setDriverClassName("com.mysql.jdbc.Driver");
        configXmlMsg.setUrl("jdbc:mysql://localhost:3306/ssm?useUnicode=true&amp;characterEncoding=utf8");
        configXmlMsg.setPassword("root");
        configXmlMsg.setUsername("root");

        return configXmlMsg;
    }
}

运行测试类结果如下:

执行的语句是:select * from blog where id = 1
id结果:1
name结果:dfgdfg
Blog(id=1, name=dfgdfg)

这仅仅是一个参考,具体详情还要根据mybatis源码分析。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值