什么是代理模式
代理模式分为静态代理模式,和动态代理模式,代理模式就是创建一个代理对象,由代理对象来接管原对象的引用,静态代理模式需要让代理类和被代理的类实现同一个接口,通过代理类中定义的构造方法将被代理的对象作为参数注入进去,然后实例化代理对象从而实现对方法的调用。
动态代理模式又分为jdk动态代理和cglib动态代理,jdk动态代理是需要实现InvocationHandler接口,并重写invoke方法。而cglib动态代理则是需要实现methodInterceptor接口,并重写interceptor方法。他们之间有一个区别,那就是jdk动态代理需要要接口的定义,因为它是将代理对象转换成接口对象从而实现对方法的调用。而cglib则不需要有接口的定义。
1.静态代理模式
创建一个代理对象,由代理对象接管原对象的引用。
/*** 抽象角色*/
public interface Person {/*** 定义一个sayHi方法*/void sayHi();
}/*** 真实角色*/
public class PersonImpl implements Person {@Overridepublic void sayHi() {System.out.println("Hello everOne!");}
}/*** 代理角色*/
public class MyProxy implements Person {private Person person;public MyProxy(Person person){this.person = person;}@Overridepublic void sayHi() {person.sayHi();}
}/*** 测试*/
public class Main {public static void main(String[] args) {Person person = new PersonImpl();Person myProxy = new MyProxy(person);myProxy.sayHi();}
}
我们可以从以上代码看到,由MyProxy代理对象代理了PersonImpl对象的引用,这就是静态代理模式。其中抽象角色是代理角色和真实角色共同继承的接口,代理角色指的就是代理对象,真实角色指的是被代理的对象。
2.jdk动态代理
为什么有了静态代理模式还需要动态代理模式呢?我们由上面的代码可以看出静态代理模式的一个短板,那就是一次只能代理一个对象,这在部分业务场景是其实很不友好,动态代理模式则能解决这种短板,此时我们对代理类稍加改动,下面是动态代理模式的代码。
/*** 代理角色*/
public class MyProxy implements InvocationHandler {private Object obj;public MyProxy(Object obj){this.obj = obj;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("before "+method.getName());method.invoke(obj,args);System.out.println("after "+method.getName());return null;}
}
我们可以看出,动态代理模式需要实现InvocationHandler接口并重写invoke方法,其中参数method指的是被代理方法的对象,通过getName方法可以获取被代理的方法名,args则是被代理方法的参数。接下来写个main方法测试一下。
/*** 测试*/
public class Main {public static void main(String[] args) {Person person = new PersonImpl();InvocationHandler handler = new MyProxy(person);Person per = (Person) Proxy.newProxyInstance(person.getClass().getClassLoader(), person.getClass().getInterfaces(), handler);per.sayHi();}
}
成功!