----------android培训、java培训、java学习型技术博客、期待与您交流!----------

创建代理:
InvocationHandler接口
    创建实现Collection接口的动态类和查看其名称,分析Proxy.getProxyClass方法的各个参数

    创建动态类的实例对象
       1)用反射获得构造方法
       2)编写一个简单的InvocationHandler类
       3)调用构造方法创建动态类的实例对象,并编写的InvocationHandler类的实例对象穿进去
      
     让JVM创建动态类及其实例对象,需要给它提供哪些信息?
     1)生成的类中有哪些方法,通过让其实现哪些接口的方式进行告知
     2)产生的类字节码必须有一个关联的类加载器对象
     3)生成的类中的方法的代码是怎样的,也得由我们提供,把我们的代码写在一个约好的接口对象

InvocationHandler的运行原理
创建某一接口 MyInterface 的代理:

1)
      InvocationHandler handler = new MyInvocationHandler(...);
             代理实例调用处理程序实现的接口,对代理实例调用方法时,将对方法调用进行编码并将其指派到它的调用处理程序的 invoke 方法
      Class proxyClass = Proxy.getProxyClass(
          MyInterface.class.getClassLoader(), new Class[] { MyInterface .class });
             得到接口代理类的类加载器,要接口数组(因为可能要加载的不是一个接口)
      MyInterface myint = (MyInterface ) proxyClass.getConstructor(new Class[] {                  InvocationHandler.class }).newInstance(new Object[] { handler });
             创建实例对象
      2) 
      MyInterface myint = (MyInterface) Proxy.newProxyInstance(
          MyInterface .class.getClassLoader(),接口的类加载器
          new Class[] { MyInterface .class },要实现动态代理类的接口
          new InvocationHandler(){
               ArrayList target=new ArrayList();
               public Object invoke(Object proxy,Method method,Object[] args)throws Throwable{
                    Object retVal=method.invoke(target,args);
                    return target;此时target是Object类型,传入什么类型,我就是什么类型
               }
            }
          );匿名内部类     为了增强框架功能,封装成一个对象
  
       objProxy.add("abc");方法,涉及到的三要素:objProxy对象、add方法、"abc"参数
       objProxy对象——>Object proxy
       add方法——>Method methods,继承Object只有hashCode,equals,toString这三个方法交给handler
       "abc"参数——>Object[] args
       Class proxy${
              add(Object obj){
                  return handler.invoke(Object proxy,Method method,Object[] args);
              }
       }三、简易Spring,对代理类进行封装
  
 1)advice建议、协议
 public interface Advice{
    void beforMethod(Method method);
    void afterMethod(Method method);
 }
 2)myAdvice用户自己定义的advice,和协议相符合,以便调用代理
 public class myAdvice{
    public void beforMethod(Method method){
         定义自己的功能,或是广告
    }
    public void afterMethod(Method method){
         定义自己的功能,或是广告
    }
 }
 3)ProxyFactoryBean实现代理功能,进行的封装
 public class ProxyFactoryBean { private Advice advice;
  private Object target;
  
         code…        创建代理       
  public Object getProxy() {        }
}
 4)BeanFactory通过读取Properties,获取要代理的类的相关信息
 public class BeanFactory {
  Properties props = new Properties();
  public BeanFactory(InputStream ips){
   try {
    props.load(ips);
   } catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
   }
  }
 }

其实,通过认真学习张老师的视频教程,不难发现,动态代理的核心代码要素一个是代理的接口,该接口声明了代理的核心功能,另一个是java.lang.reflect.InvocationHandler接口,该接口的存在,主要是利用其中的public Object invoke(Objectproxy,Method method,Object[] args)函数的实现来实现代理接口中的方法,在调用被代理的接口中的方法时,该invoke方法就会被调用,且代理对象、所调用方法的Method对象及实际参数都会作为invoke方法的参数,例如:


import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class MyProxy {
	public static void main(String[] args) {
		Action action = (Action)Proxy.newProxyInstance(
				//代理接口的类加载器,或者某个类的加载器
				Action.class.getClassLoader(), 
				//代理类接口的Class
				new Class[]{Action.class}, 
				//InvocationHandler接口的实现
				new MyInvocationHandler()
				);
		
		/*每次调用代理时,都会调用MyInvocationHandler中的
		 * public Object invoke(Object proxy,Method method,Object[] args)这个方法
		 * 该方法对客户是半透明的,换句话说,就是客户知道的其实现了自己的要求,但是其中的其他业务逻辑(比如广告啊什么的),
		 * 用户是事先不知道的,我把这种情况称为半透明。*/
		
		/*调用代理的smile()方法实现Man类的smile()方法时,MyInvocationHandler中的invoke方法里的内容
		 * 都会执行,那么就自然会执行System.out.println("我是"+man.getName()+",我为自己代言");这条语句
		 * 从而打印“我是陈欧,我为自己代言”*/
		action.smile();
		action.speak();
	}

}

interface Action{
	void speak();
	void run();
	void smile();
}

class MyInvocationHandler implements InvocationHandler{
	@Override
	public Object invoke(Object proxy, Method method, Object[] args)
			throws Throwable {
		/*以下是广告阶段,哈哈...
		 * 其实,这就是AOP中的的那个切面
		 * */
		Man man = new Man();
		man.setName("陈欧");
		System.out.println("我是"+man.getName()+",我为自己代言");
		
		//执行代理对象所要代理的核心方法,这些方法才是客户的需求核心
		return method.invoke(man, args);
	}
}
class Man implements Action{
	private String name;
	private int aga;
	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getAga() {
		return aga;
	}

	public void setAga(int aga) {
		this.aga = aga;
	}

	@Override
	public void speak(){
		System.out.println("man can speak");
	}

	@Override
	public void run() {
		System.out.println("man can run");
	}

	@Override
	public void smile() {
		System.out.println("man can smile");
	}
	public void makeMoney(){
		System.out.println("赚钱");
	}
}




这里,还可以将其封装成一个获得动态代理的方法,如下所示:

Man类同上



public class MyProxy {
	public static void main(String[] args) {
		
		Action action = (Action)getProxy(new Man(),new Man());
		action.smile();
		action.speak();	
	}
	
	//注意,Man man可以是其他切面逻辑,这里为了简便,就用的是与代理目标target相同的类
	public static Object getProxy(final Object target,final Man man){
		
		Object proxy = Proxy.newProxyInstance(
				target.getClass().getClassLoader(), 
				target.getClass().getInterfaces(), 
				new InvocationHandler(){

					@Override
					public Object invoke(Object proxy, Method method, Object[] args)
					throws Throwable {
					
					Man man = new Man();
					man.setName("陈欧");
					System.out.println("我是"+man.getName()+",我为自己代言");
					
					//执行代理对象所要代理的核心方法,这些方法才是客户的需求核心
					return method.invoke(target, args);
					}
					
				});
		return proxy;
		
	}
	
}



总结:动态代理听起来感觉很难,但是学起来确实感觉很有意思。