首页 > 代码库 > 理解动态代理

理解动态代理

完成InvocationHandler对象的内部功能
分析InvocationHandler对象的运行原理
总结分析动态代理类的设计原理与结构


创建动态类的实例对象及调用其方法

package java_5;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.Collection;

public class Proxy_InvocationHandler_Test {

    public static void main(String[] args) throws NoSuchMethodException,
             SecurityException, InstantiationException, IllegalAccessException,
             IllegalArgumentException, InvocationTargetException {

         ArrayList<Object> arr = new ArrayList<>();
          @SuppressWarnings("unchecked" )
         Collection<String> collection =(Collection<String>) getProxy(arr, new Advice() {
              private long startTime ;
              private long endTime ;

              @Override
              public void beforeMethod(Object proxy, Method method, Object[] args) {
                  startTime = System.currentTimeMillis();
                 System. out.println(method.getName() + "花费了"
                          + ( endTime - startTime ) + "时间" );
             }

              @Override
              public void afterMethod(Object proxy, Method method, Object[] args) {
                  endTime = System.currentTimeMillis();
             }

         });
          // 内部通过调用 invocationhandler的invoke方法来完成调用
         collection.add( "qqq");
         collection.add( "www");
         collection.add( "eee");
         System. out.println(collection.size());
    }

    private static Object getProxy(final Object arr,
              final Advice advice) throws NoSuchMethodException,
             InstantiationException, IllegalAccessException,
             InvocationTargetException {

         Class<?> clazz = Proxy.getProxyClass(arr.getClass ().getClassLoader(),
                 arr. getClass().getInterfaces());
         Constructor<?> constructor = clazz
                 .getConstructor( new Class[] { InvocationHandler.class });
          // 第二种方式:Proxy.newProxyInstance(loader, interfaces, h)
          @SuppressWarnings("unchecked" )
         Object object = constructor
          // 要求在构造时传递参数,说明对象肯定维护了一个成员变量,而且要接收成员。为之所用
                 .newInstance( new InvocationHandler() {
                       @Override
                       public Object invoke(Object proxy, Method method,
                               Object[] args) throws Throwable {
                           // 业务1,调用传进来的业务对象
                          advice.beforeMethod(proxy, method, args);
                          Object o = method.invoke(arr, args);
                           // 业务2,调用传进来的业务对象
                          advice.beforeMethod(proxy, method, args);
                           return o;
                      }
                 });
          return constructor;
    }

}

// 把想要做的业务封装成一个对象
interface Advice {
    void beforeMethod(Object proxy, Method method, Object[] args);

    void afterMethod(Object proxy, Method method, Object[] args);
}
模拟spring的架构原理:实现类似spring的可配置的AOP框架

#name=java.util.ArrayList
name= java_5_AOP.ProxyFactoryBean
name.advice= java_5_AOP.MyAdvice
name.target= java.util.ArrayList


package java_5_AOP;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Properties;

public class FactoryBean {
     private Properties properties ;

     public FactoryBean(InputStream ips) throws IOException {
          properties = new Properties();
          properties .load(ips);
    }

     public Object getProxy(String name) throws ClassNotFoundException,
             InstantiationException, IllegalAccessException {
         String objectName = properties .getProperty(name);
         Class<?> clazz = Class. forName(objectName);
         Object o1 = clazz. newInstance();
          if (o1 instanceof ProxyFactoryBean) {
             ProxyFactoryBean proxyFactoryBean = new ProxyFactoryBean();
             String targetClass = properties .getProperty(name + ".target" );
             String adviceClass = properties .getProperty(name + ".advice" );
             Object o2 = proxyFactoryBean.getProxy((Advice) Class.forName(adviceClass)
                      . newInstance(), Class.forName(targetClass).newInstance ());
              return o2;
         }
          return o1;
    }
}

class ProxyFactoryBean {
     private Advice advice ;

     public Advice getAdvice() {
          return advice ;
    }

     public void setAdvice(Advice advice) {
          this .advice = advice;
    }

     public Object getTarget() {
          return target ;
    }

     public void setTarget(Object target) {
          this .target = target;
    }

     private Object target ;

     public Object getProxy( final Advice advice, final Object object) {
         Object proxy = Proxy.newProxyInstance(object.getClass()
                 .getClassLoader(), object.getClass().getInterfaces(),
                  new InvocationHandler() {

                       @Override
                       public Object invoke(Object proxy, Method method,
                               Object[] args) throws Throwable {
                        //把业封装成对象
                          advice.startMethod(object, method, args);
                          Object o = method.invoke(object, args);
                        //把业封装成对象
                          advice.endMethod(object, method, args);
                           return o;
                      }
                 });
          return proxy;

    }
}

interface Advice {

     void startMethod(Object object, Method method, Object[] args);

     void endMethod(Object object, Method method, Object[] args);
}

class MyAdvice implements Advice {
     private long startTime ;
     private long endTime ;

     public void startMethod(Object object, Method method, Object[] args) {
          startTime = System.currentTimeMillis();
    }

     public void endMethod(Object object, Method method, Object[] args) {
          endTime = System.currentTimeMillis();
         System. out .println(method.getName() + "花了" + ( endTime - startTime )
                 + "毫秒值" );
    }

}



package java_5_AOP;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collection;

public class AOPTest {
     public static void main(String[] args) throws Exception{
         InputStream ips = AOPTest.class .getResourceAsStream("/java_5_AOP/config.properties" );
         FactoryBean fb = new FactoryBean(ips);
         Object obj = fb.getProxy( "name" );
        System. out .println(obj.getClass().getName());
        //只能是collection类型,因为代理对象是一个接口的实现类是目标对象的兄弟所以不能强转为其他的:eg:ArrayList;
          Collection o = (Collection )obj;
          o.add( "qqq");
          o.add( "www");
         System. out .println(o.size());
         
    }
}