1.静态代理模式
1.1 编写接口
public interface Person {
String sing(String name);
String dance(String name);
}
1.2 代理类与被代理类都实现该接口,代理类中定义被代理类对象,同时增强被代理类中的同名方法
//被代理类
public class Kun implements Person{
@Override
public String sing(String name) {
System.out.println("坤坤唱了"+name);
return "打篮球";
}
@Override
public String dance(String name) {
System.out.println("坤坤跳了"+name);
return "爆炸了";
}
}
//代理类
public class KunProxy implements Person{
//被代理对象
private Person person = new Kun();
@Override
public String sing(String name) {
System.out.println("收600w");
String res = person.dance(name);
return res+"。。。。灭火";
}
@Override
public String dance(String name) {
System.out.println("收900w");
String res = person.sing(name);
return res+"。。。。摔一跤";
}
}
1.3 对外只使用代理类对象来进行方法调用
public class Test {
public static void main(String[] args) {
//1.创建代理对象
Person person = new KunProxy();
//2.调用代理对象方法
String res = person.sing("鸡你太美");
System.out.println(res);
}
}
2.动态代理
相比静态代理,进行动态代理的对象是动态创建的
2.1 编写共同的接口
public interface Person {
String sing(String name);
String dance(String name);
}
2.2 编写被代理类
//被代理类
public class Kun implements Person{
@Override
public String sing(String name) {
System.out.println("坤坤唱了"+name);
return "打篮球";
}
@Override
public String dance(String name) {
System.out.println("坤坤跳了"+name);
return "爆炸了";
}
}
jdk动态代理,程序运行时动态产生代理类并创建其代理类对象
2.3 编写创建动态代理类及其对象的工具类
public class KunProxyUtils {
//被代理对象
private Person person = new Kun();
//动态创建代理对象
public Person createProxy(){
//运行时动态生成动态代理类,并将其加载到内存中,再创建动态代理类对象
//参数1:类加载器,用于加载动态代理类
//参数2,自定义接口,即代理类与被代理类实现的同一接口
//参数3,实现InvocationHandler接口的类对象,再底层会调用其中的invoke方法
// 因为通过jdk动态代理生成的代理类虽然实现了同一接口,但不知道接口中的方法具体应该执行什么工作
// 所以需要将其中要进行的工作封装到一个方法中,并传给jdk动态代理方法
// jdk动态代理机制就定义了这样的一个接口InvocationHandler,其中的invoke方法定义好了方法的名字和参数
return (Person) Proxy.newProxyInstance(KunProxyUtils.class.getClassLoader(),person.getClass().getInterfaces(),new MethodHandler());
}
}
jdk动态代理机制生成代理类的过程:
(可以使用匿名内部类省略下面编写实现InvocationHandler接口中invoke方法的步骤)
public static Person createProxy(){
return (Person) Proxy.newProxyInstance(KunProxyUtils.class.getClassLoader(), person.getClass().getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println(method.getName()+"被调用了");
if(method.getName().equals("sing")){
//要进行增强的代码
System.out.println("收600w");
//让被代理对象执行要调用的方法
Object res = method.invoke(person,args);
//要进行增强的代码
System.out.println("谢谢");
return res;
}else if(method.getName().equals("dance")){
//要进行增强的代码
System.out.println("收900w");
//让被代理对象执行要调用的方法
Object res = method.invoke(person,args);
//要进行增强的代码
System.out.println("再爆炸");
return res;
}else {
System.out.println("不支持该服务");
return null;
}
}
});
}
2.4 编写实现InvocationHandler接口中invoke方法的类,其中定义想要代理类执行的代码
public class MethodHandler implements InvocationHandler {
private Person person;
//接收被代理对象
public MethodHandler(Person person){
this.person = person;
}
/**
* 其中定义代理类对象要进行的工作,jdk动态代理机制在底层调用,代理对象任意方法被调用时都会调用该invoke方法
* @param proxy 代理对象自身
* @param method 要调用的代理对象的方法
* @param args 要调用的代理对象的方法的参数
* @return
* @throws Throwable
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println(method.getName()+"被调用了");
if(method.getName().equals("sing")){
//要进行增强的代码
System.out.println("收600w");
//让被代理对象执行要调用的方法
Object res = method.invoke(person,args);
//要进行增强的代码
System.out.println("谢谢");
return res;
}else if(method.getName().equals("dance")){
//要进行增强的代码
System.out.println("收900w");
//让被代理对象执行要调用的方法
Object res = method.invoke(person,args);
//要进行增强的代码
System.out.println("再爆炸");
return res;
}else {
System.out.println("不支持该服务");
return null;
}
}
}
2.5 编写测试
public class Test {
public static void main(String[] args) {
//通过创建代理工具类得到的person是一个代理类对象
Person person = KunProxyUtils.createProxy();
Object res1 = person.sing("鸡你太美");
System.out.println(res1);
Object res2 = person.dance("蠢蠢欲动");
System.out.println(res2);
}
}
输出结果
整个调用过程:
由此可见,在调用动态代理对象中任意方法时,都会调用InvocationHandler接口中的invoke方法