代理模式&动态代理

动态代理的用途:java

动态代理的用途与装饰模式很类似,就是为了对某个对象进行加强。全部使用装饰者模式的案例均可以使用动态代理来替换,动态代理能够更好的解耦合ide

加强有3个手段
1. 继承
 被加强对象不能变
 加强内容不能变
2. 装饰者模式
 被加强对象可变
 但加强内容不能变
3. 动态代理
 被加强对象可变
 加强内容也可变
测试

如何实现动态代理?this

定义一个接口Interface, 被加强的对象的类都会实现这个接口spa

 public interface Interface {
 public void fun();
}

实现这个Interface接口:
而这个InterfaceImpl就是动态代理中被加强的内容
代理

 public class InterfaceImpl implements Interface {
 @Override
 public void fun() {
  System.out.println("目标方法调用");
 }
}

定义一个接口Advice, 加强内容的类都会实现这个接口
这个接口有两个未实现的方法:
before()前置加强的方法
after()后置加强的方法
code

 public interface Advice {
 public void before();
 public void after();
}

而实现了Advice接口的对象就是动态代理中加强内容对象

JavaAPI:继承

java.lang.reflect.Proxy接口

Object proxyObject = Proxy.newProxyInstance(ClassLoader classLoader, Class[] interfaces, InvocationHandler h);

返回一个指定接口的代理类实例,该接口能够将方法调用指派到指定的调用处理程序

参数:
classLoader - 定义代理类的类加载器
interfaces - 代理类要实现的接口列表
h - 指派方法调用的调用处理程序
返回:
一个带有代理类的指定调用处理程序的代理实例,它由指定的类加载器定义,并实现指定的接口


java.lang.reflect.InvocationHandler

public Object invoke(Object proxy, Method method, Object[] args);

这个invoke()方法在调用代理对象所实现接口中的方法时调用

* Object proxy:当前对象,即代理对象!在调用谁的方法!
* Method method:当前被调用的方法(目标方法)
* Object[] args:目标方法参数

调用proxy实例的方法时, 都会被InvocationHandler所捕获, 所以只要实现InvocationHandler实现类的invoke()方法, 就能够实现目标方法的加强

定义一个类ProxyFactory

该类经过两个参数的public ProxyFactory(target,advice)构造方法构造ProxyFactory实例, 而后经过该实例的getProxy()方法获得代理对象

 public class ProxyFactory {
	private Object target;    // 目标对象
	private Advice advice;    // 加强对象

	public ProxyFactory(Object target, Advice advice) {
		this.target = target;
		this.advice = advice;
	}

	/**
	 * 获得代理对象
	 */
	public Object getProxy() {
		return Proxy.newProxyInstance(
				target.getClass().getClassLoader(), 
				target.getClass().getInterfaces(),
				new InvocationHandler() {
					@Override
					public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
						// 执行前置加强
						advice.before();
						// 执行目标对象的目标方法, 用result接收返回值
						Object result = method.invoke(target, args);
						// 执行后置加强
						advice.after();
						// 返回目标方法的返回值result
						return result;
					}
				});
	}
}

测试动态代理

public static void main(String[] args) {
	InterfaceImpl target = new InterfaceImpl();
	// 实现一个Advice的实例对象, 这个对象就是动态代理中加强内容
	Advice advice = new Advice() {
		@Override
		public void before() {
			System.out.println("目标方法调用以前, 执行前置加强");
		}

		@Override
		public void after() {
			System.out.println("目标方法调用以后, 执行后置加强");
		}
	};
	ProxyFactory proxyFactory = new ProxyFactory(target, advice);
	Interface proxy = (Interface) proxyFactory.getProxy();
	proxy.fun();
}

Console输出:

方法调用以前, 执行前置加强目标方法调用方法调用以后, 执行后置加强

相关文章
相关标签/搜索