美文网首页
mybatis中的动态代理解析

mybatis中的动态代理解析

作者: _FireFly_ | 来源:发表于2020-11-23 09:25 被阅读0次

    动态代理的目的: 一个接口需要通过动态代理对象为自己产生一个匿名的实现类,平时我们都是自己实现这个接口,然后通过new这个接口的实现类来创建这个接口的对象,然后执行这个接口中的方法;这里不需要我们自己来实现这个接口,通过动态代理的方法,系统会为我们new一个实现这个接口的匿名对象,然后通过这个系统产生的匿名对象来执行原来接口中的方法

    Student

    package domain;
    public class Student {
    
        private Integer sid;
        private String sname;
        private String ssex;
        private Integer sage;
    
        public Student() {
        }
    
        public Student(Integer sid, String sname, String ssex, Integer sage) {
            this.sid = sid;
            this.sname = sname;
            this.ssex = ssex;
            this.sage = sage;
        }
    
        public Integer getSid() {
            return sid;
        }
    
        public void setSid(Integer sid) {
            this.sid = sid;
        }
    
        public String getSname() {
            return sname;
        }
    
        public void setSname(String sname) {
            this.sname = sname;
        }
    
        public String getSsex() {
            return ssex;
        }
    
        public void setSsex(String ssex) {
            this.ssex = ssex;
        }
    
        public Integer getSage() {
            return sage;
        }
    
        public void setSage(Integer sage) {
            this.sage = sage;
        }
    }
    

    StudentDao

    public interface StudentDao {
    
    //    //属性
    //    private SqlSession sqlSession = new SqlSessionFactory().openSession();
    //
    //    //dao中有一个具体的方法
    //    //负责执行数据库的写操作
    //    public void insert(Student student){
    //        sqlSession.insert("sqlid",student);
    //    }
    
        public void insert(Student student);//dao变成接口的时候 方法名字 必须与sqlid
    }
    

    StudentMapper.xml

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <mapper namespace="dao.StudentDao">
        <insert id="insert">
          insert into student values(#{sid},#{sname},#{ssex},#{sage})
        </insert>
    </mapper>
    

    StudentService

    public class StudentService {
    
        //基于框架
    //    private StudentDao dao = MyUtil.getSqlSession().getMapper(StudentDao.class);
        //自己写的
        private StudentDao dao = MyUtil.getSqlSession().getMapper(StudentDao.class);
    
    
        //设计一个业务的方法 注册 新增方法
        public void insertStudent(Student student){
            //判断以下当前更新的人主键是否冲突
            //if(){}
            dao.insert(student);
        }
    }
    

    SqlSession(这里模仿Mybatis中的SqlSession)

    package proxy;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    
    public class SqlSession {
    
        //可以理解为 这个类的对象 是以前我们MyBatis提供的对象
    
        //预先将mapper.xml文件全部内容读取并解析的过程
        static{
            //读取mapper.xml文件内容
            //解析内容
            //      <mapper namespace="dao.StudentDao">
            //          <insert id="sqlid">
            //              insert into student values(#{sid},#{sname},#{ssex},#{sage})
            //          </insert>
            //      </mapper>
    
            //      mapper类型的对象(namespace属性 List<Insert对象> list<Update对象>)
            //      insert类型的对象(id属性 sql属性)
            //      update类型的对象(id属性 sql属性)
        }
    
        public void insert(String sqlid,Object obj){
            //应该做什么?????
            //原来的JDBC流程
            //1.导包
            //2.加载驱动
            //*3.获取连接(连接池方式管理)
            //*4.通过传递的sqlid找寻一条SQL语句(解析XML文件)
            //5.创建状态参数(预处理 优先加载SQL语句)
            //*6.SQL语句和提供的参数信息组合完整(分析SQL语句#{key},反射在obj对象中找value)
            //7.执行操作executeUpdate();
            //8.关闭
            System.out.println("我是SqlSession中的insert方法,我执行了好多好多");
        }
    
        //模仿Mybatis中的getMapper()方法
        public <T>T getMapper(Class clazz){
            //创建代理对象
            //  ClassLoader 需要被代理的类[] 做哪一件事情(方法)
            ClassLoader loader = clazz.getClassLoader();
            Class[] classes = new Class[]{clazz};
            InvocationHandler handler = new InvocationHandler() {
                //这个invoke方法相当于是代理对象的真正执行方法
                //Object proxy  :   这个对象是通过传入参数(Class clazz) 产生的匿名对象
                //Method method   :  这个是接口中的方法   public void insert(Student student);----->  insert
                //Object[] args   :  这个参数是接口中的参数 public void insert(Student student); -----> (Student student)
                public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                    System.out.println("我是代理执行的方法");
                    System.out.println("代理对象"+proxy.getClass().getName());
                    System.out.println("代理对象代替真实对象做的方法"+method.getName());
                    System.out.println("代理对象接收到真实对象的参数"+args[0]);
                    //insert("sqlid",student);
                    return proxy;
                }
            };
              //创建动态代理对象需要三个参数
              //这里我们通过动态代理机制来为 StudentDao接口来产生匿名对象,执行 StudentMapper.xml文件中的方法
             // 第一个参数为需要代理对象接口的类加载器
             //第二个参数为需要产生代理对象接口的反射
             //第三个参数为具体这个匿名对象执行的方法 这个方法需要解析  StudentMapper.xml文件,然后执行其中的方法
            Object obj = Proxy.newProxyInstance(loader,classes,handler);//代理对象(原来Dao接口的子类)
            //做一个造型
            T t = (T)obj;
            //造型以后的代理对象返回出去
            //代理对象是传递进来参数Class类型的子类对象
            return t;
        }
    
    }
    
    

    相关文章

      网友评论

          本文标题:mybatis中的动态代理解析

          本文链接:https://www.haomeiwen.com/subject/poefbktx.html