对象增强方式之动态代理

版权声明:本文为博主原创文章,未经博主允许不得转载。 如果转载,需要获得作者授权。保留追究法律责任的权力 https://blog.csdn.net/swf_shixinshou/article/details/79952421

1.什么是动态代理

        什么代理,这个我在这里就不多说了,此类文章很多,读者一搜就有,如果在这里在写一遍就有点浪费时间了。那么说一下什么是动态代理,就是可以在程序运行的过程中,动态的创建的对象与方法,也就是说在运行之前是没有.class文件让你读入内存,然后创建对象,而是在运行的过程中在内存中创建对象,所以其具有更好的灵活性,为什么具有更好的灵活性请参见我的另一篇文章对象增强方式之装饰者模式。

  2.动态代理的特点:

        2.1、增强的内容是可以修改的,2.2、被增强的对象也是可以切换的。

3.为什么学习动态代理

    学习动态代理有助于我们更加深入的理解框架,特别是spring的面向切面编程AOP,当然不懂动态代理也可以使用框架,可是理解了动态代理,就可以轻松的理解框架的用法的含义。

4.学习动态代理需要哪些东西?

        答案是只有一个方法就够了!!,而这个方法就是newProxyInstance(ClassLoader classLoader, Class[] interfaces, InvocationHandler h);这个方法是Proxy类的一个方法。此方法的作用是:在运行时,动态创建一组指定的接口的实现类对象!

5.newProxyInstance方法的解释

    Object proxy = Proxy.newProxyInstance(ClassLoader classLoader, Class[] interfaces, InvocationHandler h);这几个参数的意义;

            ClassLoader:类加载器 把.class文件加载到内存,形成Class对象,不懂类加载器可以参见我的另一篇文章java的类加载器和Tomcat的类加载器
            2. Class[] interfaces:指定要实现的接口,可以是多个接口,因为是数组,哈哈。

            3. InvocationHandler:代理对象调用实现接口的所有方法,都会调用InvocationHandler的invoke()方法。

    举个栗子:

        

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

import org.junit.Test;

public class ProxyTest {
	@Test
	public void test1(){
		ClassLoader loader = this.getClass().getClassLoader();
		Class[] interfaces = {A.class,B.class};
		Object o = Proxy.newProxyInstance(loader, interfaces, new InvocationHandler(){

			@Override
			public Object invoke(Object proxy, Method method, Object[] args)
					throws Throwable {
				// TODO Auto-generated method stub
				System.out.println("hello 动态代理");
				return null;
			}
			
		});
		A a = (A)o;
		a.aaa();
		a.bbb();
		B b = (B)o;
		b.ccc();
		b.ddd();
	}
}
interface A{
	public void aaa();
	public void bbb();
}
interface B{
	public void ccc();
	public void ddd();
}

执行结果为

    

hello 动态代理
hello 动态代理
hello 动态代理
hello 动态代理

这说明代理对象调用所实现接口的方法都会执行InvocationHandler的invoke()方法。

其实这invoke方法的三个参数是与代理对象方法一一对应的,接下来一张图来解释

    

b就对应于proxy这个代理,ccc方法对应于method ,参数对应于args,当然这个方法没有参数,举得不恰当了,哈哈

6.实现动态增强一个对象

        说了这么多都是在解释这个方法的含义,那么现实中它到底怎么用呢,这就通过一段代码来解释一下,

首先创建一个两个接口,来代表增强点

    

public interface BeforeStrengthen {//前置增强
	public void before();
}
public interface AfterStrengthen {//后置增强
	public void after();
}

然后创建一个工厂类,专门负责给对象增强,和得到代理对象

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

public class ProxyFactory {
	private Object targetObject;//目标对象
	private BeforeStrengthen beforeStrengthen;//前置增强
	private AfterStrengthen afterStrengthen;//后置增强
	private String strengthenMethod;//增强点
	
	
	/**
	 * 用来生成代理对象
	 * @return
	 */
	public Object createProxy() {
		ClassLoader loader = this.getClass().getClassLoader();
		Class[] interfaces = targetObject.getClass().getInterfaces();
		InvocationHandler h = new InvocationHandler() {

			@Override
			public Object invoke(Object proxy, Method method, Object[] args)
					throws Throwable {
				Object result = null;
				if(method.getName().equals(strengthenMethod)){
					// 执行前置增强
					if(beforeStrengthen != null) {
						beforeStrengthen.before();
					}
					
					result = method.invoke(targetObject, args);//执行目标对象的目标方法
					// 执行后置增强
					if(afterStrengthen != null) {
						afterStrengthen.after();
					}
					
				}else{
					result = method.invoke(targetObject, args);//执行目标对象的目标方法
				}
				
				// 返回目标对象的返回值
				return result;
			}
		
		};
		/*
		 *  得到代理对象
		 */
		Object proxyObject = Proxy.newProxyInstance(loader, interfaces, h);
		return proxyObject;
	}
	
	//get和set方法
	public Object getTargetObject() {
		return targetObject;
	}
	public void setTargetObject(Object targetObject) {
		this.targetObject = targetObject;
	}
	public BeforeStrengthen getBeforeStrengthen() {
		return beforeStrengthen;
	}
	public void setBeforeStrengthen(BeforeStrengthen beforeStrengthen) {
		this.beforeStrengthen = beforeStrengthen;
	}
	public AfterStrengthen getAfterStrengthen() {
		return afterStrengthen;
	}
	public void setAfterStrengthen(AfterStrengthen afterStrengthen) {
		this.afterStrengthen = afterStrengthen;
	}


	public String getStrengthenMethod() {
		return strengthenMethod;
	}


	public void setStrengthenMethod(String strengthenMethod) {
		this.strengthenMethod = strengthenMethod;
	}
	
	
}

最后测试:

    

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

import org.junit.Test;

public class ProxyTest {
	@Test
	public void test2(){
		ProxyFactory factory = new ProxyFactory();//创建工厂
		factory.setTargetObject(new C());//设置目标对象
		factory.setBeforeStrengthen(new BeforeStrengthen(){//设置前置增强

			@Override
			public void before() {
				// TODO Auto-generated method stub
				System.out.println("前置增强");
			}
			
		});
		
		factory.setAfterStrengthen(new AfterStrengthen() {//设置后置增强
			public void after() {
				System.out.println("后置增强");
			}
		});
		factory.setStrengthenMethod("aaa");
		A a = (A)factory.createProxy();
		a.aaa();
		System.out.println("===================================");
		a.bbb();
	}
	
interface A{
	public void aaa();
	public void bbb();
}
class C implements A{

	@Override
	public void aaa() {
		System.out.println("我是AAAAA啊");
	}

	@Override
	public void bbb() {
		System.out.println("我是BBBBB啊");
	}
	
}

执行结果

前置增强
我是AAAAA啊
后置增强
===================================
我是BBBBB啊
以上代码就是给我们指定的对象的某一个方法增强了,不知道大家有没有懂呢?如果没懂参见我的另一篇文章对象增强方式之装饰者模式,说不定会有一些启示呢!如果我有不正确的地方,请批评指正

    






    

    





阅读更多
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页