面向接口编程+策略模式+方法回调
日常在写代码的过程中,这些些简单的知识点我们应该都用过,但是真正的核心逻辑有很多人也不明白,这里给大家做一下简单的总结
- jdbc
- servlet规范
- jdk动态代理
- spring
- mybatis中的原生 api 方法,select(),实现原理是策略模式 + 方法回调,select可以返回我们自定义的数据格式,例如json
- mybatis中的mpper的代理对象方式,调用getMapper()方法时
- springJDBC中的 queryForObject()方法使用了
jdbc
Sun公司提供了一个jdbc规范,其实就是一些接口,各大数据库厂商实现了这些接口,程序员只需要会使用这些接口就行,而之前没有jdbc时我们要去学习每个数据库的使用
servlet规范
我们写的java应用程序是遵循servlet规范的,而一些厂商的服务器也实现了servlet规范,所以我们的程序可以运行在这些服务器上
jdk动态代理
在Proxy类调用newProxyInstance方法时,会有三个参数,一个是类加载器,一个是接口数组,一个是实现了InvocationHandler接口类的回调,这个类中重写了invoke方法,我们在调用方法时,会调用重写后的方法
spring
我们的程序基于三层架构,为了使各层之间的耦合度降低,spring以IOC和DI的方式帮我们很好地解决了耦合问题,例如在service层中提供一个userdao接口,而在dao层中可以随意更换任意的数据库,而不影响web层和service层
mybatis中的原生 api 方法,select(),实现原理是策略模式 + 方法回调,select可以返回我们自定义的数据格式,例如json
//将数据库中查询到的数据拼接成json字符串
class JsonHandler implements ResultHandler<User>{
//[{"id":1,"name":"aa","password":"aa","address":"aa"},{},{},{}]
//{"key1":{},"key2":{}...}
StringBuilder sb=new StringBuilder("[");
@Override
public void handleResult(ResultContext<? extends User> resultContext) {
//获取一个用户数据
User user =resultContext.getResultObject();
//把数据封装成json字符串
sb.append("{");
sb.append("\"id\"");
sb.append(":");
sb.append(user.getId());
sb.append(",");
sb.append("\"name\"");
sb.append(":");
sb.append("\""+user.getName()+"\"");
sb.append(",");
sb.append("\"password\"");
sb.append(":");
sb.append("\""+user.getPassword()+"\"");
sb.append(",");
sb.append("\"address\"");
sb.append(":");
sb.append("\""+user.getAddress()+"\"");
sb.append("}");
sb.append(",");
}
public String getJson(){
String temp=sb.toString();
String temp1=temp.substring(0, temp.length()-1)+"]";
return temp1;
}
}
@Override
public String findAllUser5() {
String json=null;
SqlSession sqlSession=null;
try{
sqlSession=MyBatisUtil.getSession();
JsonHandler handler=new JsonHandler();
sqlSession.select("findAllUser_user", handler);
json=handler.getJson();
sqlSession.commit();
}catch(Exception e){
e.printStackTrace();
sqlSession.rollback();
}finally{
sqlSession.close();
}
return json;
}
mybatis中的mpper的代理对象方式,调用getMapper()方法时
UserMapper userMapper=sqlSession.getMapper(UserMapper.class);
userMapper.findUserById(7);
用UserMaper接口利用jdk动态代理生成接口代理类,用代理类生成代理对象
用代理对象调用目标方法,实际上执行的是InvocationHandler中的invoke方法
在invoke方法中调用selectOne等原生api方法,来做增删改查
手动实现getMapper()方法
//测试类
public void testMethod(){
//接口类型 jdk动态代理对象=sqlSession.getMapper(接口类型.class);
UserMapper userMapper=(UserMapper)JDKProxy.getMapper(UserMapper.class);
User user=userMapper.findUserById(1);
System.out.println(user);
}
//代理类
/**
* 根据接口获取代理对象
* @param clazz 接口的Class类型对象 比如UserMapper.class
* @return
*/
public static Object getMapper(Class clazz){
Object proxyObject=null;
/**
* 参数一:类加载器
* 参数二:接口数组
* 参数三:InvocationHandler接口的回调
*/
Object targetObject=null;
proxyObject=Proxy.newProxyInstance(
clazz.getClassLoader(),
new Class[]{clazz},
new MapperHandler());
return proxyObject;
}
//invocationHandler接口的实现类
public class MapperHandler implements InvocationHandler {
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object returnValue=null;
System.out.println("由mybatis根据若干信息选择执行对应的原生api方法");
//mybatis根据method能得到目标方法的返回值,方法名,参数类型
//if判断返回的数据为一个值则调用mybatis的原生selectOne方法
//if判断返回的数据为多个数据,就看返回类型是否为List ,则调用mybatis的原生selectList方法
//if判断返回的数据为多个数据,就看返回类型是否为Map ,则调用mybatis的原生selectMap方法
//if判断是insert,delete,update, ,则调用mybatis的原生对应insert(),delete(),update方法'
//假设给一个User
User user=new User();
user.setName("aaa");
returnValue=user;
return returnValue;
}
}
springJDBC中的 queryForObject()方法使用了
User user=null;
String sql="select id idd,username name,userpassword pwd,address from t_user where id=?";
//手动处理返回结果集中的数据如何映射到实体(domain)中
RowMapper<User> rowMapper=new RowMapper<User>(){
@Override
public User mapRow(ResultSet rs, int rowNum) throws SQLException {
User user=new User();
user.setId(rs.getInt("idd"));
user.setName(rs.getString("name"));
user.setPassword(rs.getString("pwd"));
user.setAddress(rs.getString("address"));
return user;
}
};
user =this.jdbcTemplate.queryForObject(sql, rowMapper, id);
return user;