Proxy创建动态代理的两个方法:

  1. //方法一
  2. static Class<?> getProxyClass(ClassLoader loader, Class<?>...interfaces);
  3. //方法二
  4. static Object newProxyInstance(ClassLoader loader, Class<?> interfaces, InvocationHander hander);

方法一:创建一个动态代理类所对应的Class对象,该代理类将实现interfaces数组所指定的多个接口。第一个ClassLoader参数指定生成动态代理类的类加载器。方法二:直接创建一个动态代理对象,该对象的实现类实现了interfaces数组指定的系列接口,执行代理对象的每一个方法时都会被替换成InvocationHandler接口(自己创建一个类实现该接口)的实例的invoke方法。(实际上方法一需要创建对象的话,也是要一个InvocationHandler对象的)。

InvoactionHandler的使用方法:

  1. //接口
  2. public interface Person {
  3. void walk();
  4. void sayHello(String name);
  5. }
  1. public class MyInvocationHandler implements InvocationHandler{
  2. @Override
  3. public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
  4. System.out.println("---正在执行的方法:"+method);
  5. if (args!=null){
  6. System.out.println("下面是执行该方法时传入的实参为:");
  7. for (Object val:args){
  8. System.out.println(val);
  9. }
  10. }else System.out.println("该方法没有实参");
  11. return null;
  12. }
  13. }
  1. public class MainTest {
  2. public static void main(String args[]) throws Exception {
  3. InvocationHandler handler=new MyInvocationHandler();
  4. //注意这里的Person是一个接口interface。
  5. Person p= (Person) Proxy.newProxyInstance(Person.class.getClassLoader(),new Class[]{Person.class},handler);
  6. p.walk();
  7. p.sayHello("孙悟空");
  8. }
  9. }

AOP代理:
AOP代理可替代目标对象,AOP代理对象包含了目标对象的全部方法,但AOP代理中的方法与目标对象的方法存在差异:AOP代理里的方法可以在执行目标方法之前、之后插入一些通用处理。
Proxy和Invocation动态代理和AOP代理 - 图1

例子:

  • 思路:创建Dog对象和他的GunDog实现类,创建InvocationHandler的实现类MyInvocationHandler, 在invoke方法中调用目标对象的方法,并且在方法前后加入自定义的Utils类的方法, 创建代理对象工厂类MyProxyFactory,用于生产代理对象。
  1. public interface Dog {
  2. void info();
  3. void run();
  4. }
  1. public class GunDog implements Dog {
  2. @Override
  3. public void info() {
  4. System.out.println("我是一只猎狗");
  5. }
  6. @Override
  7. public void run() {
  8. System.out.println("我奔跑迅捷");
  9. }
  10. }
  1. public class Util {
  2. public void method1(){
  3. System.out.println("----模拟第一个通用方法----");
  4. }
  5. public void method2(){
  6. System.out.println("----模拟第二个通用方法----");
  7. }
  8. }
  1. public class MyInvocationHandler implements InvocationHandler {
  2. //被代理的对象;
  3. private Object target;
  4. public void setTarget(Object object) {
  5. this.target = object;
  6. }
  7. @Override
  8. public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
  9. Util u = new Util();
  10. u.method1();
  11. //注意这里第一个参数不要放proxy进去,因为我们要为指定的target生成动态代理对象
  12. //放proxy是新生成的动态代理对象。
  13. Object result = method.invoke(target, args);
  14. u.method2();
  15. return result;
  16. }
  17. }
  1. public class MyProxyFactory {
  2. public static Object getProxy(Object target){
  3. //创建一个MyInvocationHandler对象
  4. MyInvocationHandler handler=new MyInvocationHandler();
  5. //设置指定的要生成动态代理的target对象
  6. handler.setTarget(target);
  7. //创建并返回一个动态代理对象。
  8. return Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),handler);
  9. }
  10. }
  1. public class MainTest {
  2. public static void main(String args[]) throws Exception {
  3. GunDog dog=new GunDog();
  4. Dog proxyDog= (Dog) MyProxyFactory.getProxy(dog);
  5. proxyDog.info();
  6. proxyDog.run();
  7. }
  8. }

打印:

  1. ----模拟第一个通用方法----
  2. 我是一只猎狗
  3. ----模拟第二个通用方法----
  4. ----模拟第一个通用方法----
  5. 我奔跑迅捷
  6. ----模拟第二个通用方法----

结论:动态代理模式让代码结构更加灵活,解耦。