MyBatis-02-01-MyBatis的 动态代理与静态代理机制与Demo


动态代理机制

在这里插入图片描述

传统的MyBatis提供的API

在这里插入图片描述

传入的Statement ID参数无法检查错误

Mapper接口

使用Mapper接口,MyBatis 将配置文件中的每一个<mapper> 元素抽象为一个 Mapper 接口,而这个接口中声明的方法和<mapper> 元素中的<select|update|delete|insert> 子元素相对应

在这里插入图片描述

左右接口与id是一一对应的。

在这里插入图片描述

在这里插入图片描述

静态代理与动态代理

区分关键:程序运行阶段这三个实体是否存在
在这里插入图片描述

左面是目标实体,右面是代理实体,上面是接口。
下面两个实体都是去实现上面接口的
代理实体可以对真是实体做扩展

静态代理

一个交作业的接口
两个实现类,学生与班长
班长有学生作为参数
测试类通过实例化班长与学生并赋值,通过调用班长的属性来实现看作业批改的方法

项目结构

Master.java 班长类

package com.mybatis.demo;


//代理类
public class Master implements Submitted{
    
    
	private Student student;
	
	//实现抽象方法
	@Override
	public void submitHomework() {
    
    
		student.submitHomework();
	}

	public Student getStudent() {
    
    
		return student;
	}

	public void setStudent(Student student) {
    
    
		this.student = student;
	}
	
	
	
}

Student.java 学生类

package com.mybatis.demo;


//被代理类
public class Student implements Submitted{
    
    
	private String name;

	//实现接口的方法
	@Override
	public void submitHomework() {
    
    
		System.out.println(name+"交作业");
		
	}

	//get set 方法
	public String getName() {
    
    
		return name;
	}

	public void setName(String name) {
    
    
		this.name = name;
	}
	
	
	
	
}

需要实现的接口

package com.mybatis.demo;

public interface Submitted {
    
    
	
	
	//代理类与被代理类都需要实现的接口
	public void submitHomework();
	
	
}

Test.java 测试类

package com.mybatis.demo;

public class Test {
    
    
	public static void main(String[] args) {
    
    
		Master master=new Master();
		Student student=new Student();
		student.setName("九爷");
		master.setStudent(student);
		
		fun(master);
	}
	
	
	//参数是接口,只要实现了接口,具体对象是谁无所谓
	public static void fun(Submitted sub) {
    
    
		sub.submitHomework();
	}

}

在这里插入图片描述

在这里插入图片描述
左上方是代理类与代理类需要实现的接口
最下方的是一个class,需要我们去定义

在这里插入图片描述

动态代理

项目结构

在这里插入图片描述

MyInvocationHandler.java

package com.mybatis.demo;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class MyInvocationHandler<T> implements InvocationHandler {
    
    

	//被代理对象的类型,接口的类型,通用的T类型
	T obj;
	
	
	//重写此方法 
	//动态代理的核心
	//代理类中,每个方法被调用时候都会执行此方法
	//参数1:动态代理对象
	//参数2:正在执行的方法
	//参数3:是参数2的传入的实际参数
	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    
    
		//通过反射执行代理类的方法
		//参数1:需要被执行的方法,参数2:实际参数
		Object result = method.invoke(obj, args);
		//可以对代理的那个方法进行扩展
		System.out.println("这是方法的扩展");
		return null;
	}

	
	//封装出现代理类对象的方法
	public T createProxySubject() {
    
    
		//生成代理实例
		//参数1:类加载器
		//参数2:class数组,参数类需要实现的接口类型
		//参数3:InvocationHandler类型
		return (T) Proxy.newProxyInstance(Student.class.getClassLoader(),
				new Class[] {
    
    Submitted.class},
				this);
		
	}
	
	

	public T getObj() {
    
    
		return obj;
	}


	public void setObj(T obj) {
    
    
		this.obj = obj;
	}



}

Student.java 被代理类

package com.mybatis.demo;


//被代理类
public class Student implements Submitted{
    
    
	private String name;

	//实现接口的方法
	@Override
	public void submitHomework() {
    
    
		System.out.println(name+"交作业");
		
	}

	//get set 方法
	public String getName() {
    
    
		return name;
	}

	public void setName(String name) {
    
    
		this.name = name;
	}
	
	
	
	
}

Submitted.java 需要实现的接口类

package com.mybatis.demo;

public interface Submitted {
    
    
	
	
	//代理类与被代理类都需要实现的接口
	public void submitHomework();
	
	
}

Test.java 测试类

package com.mybatis.demo;

public class Test {
    
    
	public static void main(String[] args) {
    
    
		
		//动态代理
		Student s=new Student();
		s.setName("张三");
		//动态生成代理对象,(模拟SqlSession中的GetMapper方法的实现)
		MyInvocationHandler<Student> invo=new MyInvocationHandler<>();
		invo.setObj(s);
		Submitted sub=invo.createProxySubject();
		fun(sub);
	}
	
	
	//参数是接口,只要实现了接口,具体对象是谁无所谓
	public static void fun(Submitted sub) {
    
    
		sub.submitHomework();
	}

}

猜你喜欢

转载自blog.csdn.net/qq_44627608/article/details/115351636
今日推荐