本文最后更新于:2 个月前
在开始之前,先定义一个被代理接口IPerson和其实现类Person
1 2 3 4 5
| package com.potato;
public interface IPerson { void introduce(); }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| package com.potato;
public class Person implements IPerson { public String name; public int age;
public Person(){} public Person(String name,int age){ this.name = name; this.age = age; }
public void introduce(){ System.out.println(name+"今年"+ age +"岁了"); }
@Override public String toString() { return "Person{" + "name='" + name + '\'' + ", age=" + age + '}'; } }
|
静态代理
直接贴代码了,缺点就是即使进行重复性的方法代理(如同样加入一个记录日志的功能),也需要在代理类中把方法一个一个都实现了,过于繁琐。思考一个解决方法,被代理对象能否直接知道外部的代理对象调用了什么方法呢,第一反应便是反射通过获取外部调用的方法名
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| package com.potato.Proxy;
import com.potato.Entity.IPerson; import com.potato.Entity.Person;
public class StaticProxyTest { public static void main(String[] args){ Proxy1 proxy1 = new Proxy1(new Person("potato",19)); proxy1.introduce(); } public static class Proxy1 implements IPerson { public IPerson proxy; public Proxy1(){} public Proxy1(IPerson proxy){ this.proxy = proxy; } public void introduce(){ this.proxy.introduce(); } } }
|
JDK底层为我们提供了一个解决方案,动态代理
动态代理
一个重要的方法,用于代理一个对象:
跟进方法的定义去查看,需要一个类加载器对象,一个接口数组对象以及一个InvocationHandler对象
对于InvocationHandler
对象,重写一下一个invoke方法,此处的invoke()方法就是在于解决静态代理中需要重复重写方法的缺陷,动态代理的好处就是能获取到外部调用的那个方法,然后通过反射来到内部来执行被代理对象的方法
1 2 3 4 5 6 7 8 9 10 11 12 13
| public class PersonInvocationHandler implements InvocationHandler { IPerson person; public PersonInvocationHandler(){} public PersonInvocationHandler(IPerson person){ this.person = person; }
@Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { method.invoke(person,args); return null; } }
|
其中类加载对象和接口对象的获取还是比较定式的,如下传入参数并转型,即可创建一个代理对象personProxy,调用其introduce()方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| package com.potato;
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Proxy;
public class ProxyTest { public static void main(String[] args){
IPerson person = new Person("potato",20); InvocationHandler invocationHandler = new PersonInvocationHandler(person); IPerson personProxy = (IPerson) Proxy.newProxyInstance(Person.class.getClassLoader(),Person.class.getInterfaces(),invocationHandler); personProxy.introduce(); } }
|
传参Class数组接口的参数位置也可以换为
1 2 3
| IPerson personProxy = (IPerson) Proxy.newProxyInstance(Person.class.getClassLoader(), new Class[]{IPerson.class}, invocationHandler);
|