动态代理的目的: 一个接口需要通过动态代理对象为自己产生一个匿名的实现类,平时我们都是自己实现这个接口,然后通过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;
}
}
网友评论