动态代理
Posted WWWYC
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了动态代理相关的知识,希望对你有一定的参考价值。
时间:2017-1-4 22:33
——动态代理(Proxy)概述
1、只学一个方法:
Proxy proxy = newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
2、方法的作用:
在运行时动态创建一个实现了一组指定接口的对象。
3、参数:
1)ClassLoader:类加载器
它是用来加载类的,把.class文件加载到内存,生成Class对象。
2)Class[] interfaces:Class数组
指定要实现的接口们。
3)InvocationHandler:
代理对象的所有方法(个别方法不执行,例如getClass())都会调用InvocationHandler的invoke()方法。
4、动态代理的作用
最终学习AOP(面向切面编程),它与装饰设计模式相似,但比装饰设计模式灵活。
示例代码:
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import org.junit.Test;
public class Demo {
@Test
public void fun(){
/*
* 三大参数
* 1、ClassLoader
* 该方法会动态生成一个类,这个类实现了A、B接口,然后创建这个类的对象
* 需要生成一个类,这个类也需要通过ClassLoader加载到方法区中
*
* 2、Class[] interfaces
* 它是要实现的接口们
*
* 3、InvocationHandler
* 它是调用处理器
*
* 代理对象实现的所有接口中的方法内容都是调用InvocationHandler的invoke()方法
*/
ClassLoader loader = this.getClass().getClassLoader();
InvocationHandler h = new InvocationHandler(){
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("Hello Proxy");
return null;
}
};
//使用三大参数创建代理对象
Object o = Proxy.newProxyInstance(loader, new Class[]{A.class, B.class}, h);
A a = (A)o;
B b = (B)o;
a.a();
b.b();
}
}
interface A{
public Object a(String s, int i);
public Object aa(String s, int i);
}
interface B{
public void b();
}
打印结果:
Hello Proxy
Hello Proxy
——InvocationHandler接口
1、只有一个方法:
public Object invoke(Object proxy, Method method, Object[] args);
在调用代理对象所实现接口中的方法时被调用。
* Object proxy:当前对象,即代理对象。
* Method method:当前被调用的方法(目标方法)。
* Object[] args:实参。
2、invoke()方法与代理对象调用方法的关系
——动态代理应用
增强的方式:
1、继承
* 被增强对象不能变
* 增强内容不能变
2、装饰设计模式
* 被增强对象可变
* 增强内容不可变
3、动态代理
* 被增强对象可变
* 增强内容可变
目标对象:被增强的对象。
代理对象:需要目标对象,然后在目标对象上添加了增强后的对象。
目标方法:被增强的内容。
代理对象 = 目标对象 + 增强内容
=============================================================================
示例代码:
package com.wyc.demo2;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import org.junit.Test;
public class Demo2 {
@Test
public void fun1() {
// 目标对象
Waiter manWaiter = new ManWaiter();
/*
* 给出三个参数,来创建方法,得到代理对象
*/
ClassLoader loader = this.getClass().getClassLoader();
Class[] interfaces = { Waiter.class };
// manWaiter表示目标对象
InvocationHandler h = new WaiterInvocationHandler(manWaiter);
// 得到代理对象,其实代理对象就是在目标对象的基础上进行增强的对象
Waiter waiterProxy = (Waiter)Proxy.newProxyInstance(loader, interfaces, h);
/*
* 在服务方法前添加“你好”,在服务方法后添加“再见”
*/
waiterProxy.serve();
}
}
class WaiterInvocationHandler implements InvocationHandler {
// 目标对象
private Waiter waiter;
public WaiterInvocationHandler(Waiter waiter){
this.waiter = waiter;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("您好");
// 调用目标对象的目标方法
this.waiter.serve();
System.out.println("再见");
return null;
}
}
----------------------------------------------------------------------------------------------------------------------------
package com.wyc.demo2;
public interface Waiter {
// 服务方法
public void serve();
}
----------------------------------------------------------------------------------------------------------------------------
package com.wyc.demo2;
public class ManWaiter implements Waiter {
@Override
public void serve() {
System.out.println("服务中...");
}
}
=============================================================================
——代理工厂实现
=============================================================================
ProxyFactory:
package com.wyc.demo3;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/*
* 代理工厂
* 它用来(组装)生成代理对象
* 所需参数:
* * 目标对象
* * 增强内容
*/
/*
* 1、创建代理工厂
* 2、给工厂设置三个属性:
* * 目标对象:setTargetObject(xxx);
* * 前置增强对象:setBeforeAdvice(该接口的实现类)
* * 后置增强对象:setAfterAdvice(该接口的实现类)
*
* 3、调用createProxy()方法得到代理对象
* * 执行代理对象方法时,首先执行的是BeforeAdvice的before()方法
* * 目标对象的目标方法
* * 最后会执行AfterAdvice的after()方法
*/
public class ProxyFactory {
// 目标对象
private Object targetObject;
// 前置增强对象
private BeforeAdvice beforeAdvice;
// 后置增强对象
private AfterAdvice afterAdvice;
/*
* 用来生成代理对象
*/
public Object createProxy(){
/*
* 1、给出三大参数
*/
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 {
/*
* 在调用代理对象的方法时,会调用该方法,执行这里的内容
*/
// 执行前置增强
if(beforeAdvice != null){
beforeAdvice.before();
}
// 通过反射得到的Method类,调用目标对象的目标方法
Object result = method.invoke(targetObject, args);
// 执行后置增强
if(afterAdvice != null){
afterAdvice.after();
}
// 返回目标对象的返回值
return result;
}
};
/*
* 2、得到代理对象
*/
Object proxyObject = Proxy.newProxyInstance(loader, interfaces, h);
return proxyObject;
}
public Object getTargetObject() {
return targetObject;
}
public void setTargetObject(Object targetObject) {
this.targetObject = targetObject;
}
public BeforeAdvice getBeforeAdvice() {
return beforeAdvice;
}
public void setBeforeAdvice(BeforeAdvice beforeAdvice) {
this.beforeAdvice = beforeAdvice;
}
public AfterAdvice getAfterAdvice() {
return afterAdvice;
}
public void setAfterAdvice(AfterAdvice afterAdvice) {
this.afterAdvice = afterAdvice;
}
}
----------------------------------------------------------------------------------------------------------------------------
测试:
package com.wyc.demo3;
import org.junit.Test;
/*
* 让目标对象和增强内容都可以切换
* 不决定增强对象和增强内容,只起到了装配作用
*/
public class Demo3 {
@Test
public void fun() {
// 创建工厂
ProxyFactory factory = new ProxyFactory();
// 设置目标对象
factory.setTargetObject(new ManWaiter());
// 设置前置增强对象
factory.setBeforeAdvice(new BeforeAdvice() {
@Override
public void before() {
System.out.println("您好");
}
});
// 设置后置增强对象
factory.setAfterAdvice(new AfterAdvice() {
@Override
public void after() {
System.out.println("再见");
}
});
Waiter waiter = (Waiter) factory.createProxy();
waiter.serve();
waiter.money();
}
}
----------------------------------------------------------------------------------------------------------------------------
Waiter接口:
package com.wyc.demo3;
public interface Waiter {
// 服务方法
public void serve();
// 增加方法
public void money();
}
----------------------------------------------------------------------------------------------------------------------------
ManWaiter接口:
package com.wyc.demo3;
public class ManWaiter implements Waiter {
@Override
public void serve() {
System.out.println("服务中...");
}
@Override
public void money() {
System.out.println("收钱...");
}
}
----------------------------------------------------------------------------------------------------------------------------
BeforeAdvice接口:
package com.wyc.demo3;
/*
* 前置增强
*/
public interface BeforeAdvice {
public void before();
}
----------------------------------------------------------------------------------------------------------------------------
AfterAdvice接口:
package com.wyc.demo3;
/*
* 后置增强
*/
public interface AfterAdvice {
public void after();
}
以上是关于动态代理的主要内容,如果未能解决你的问题,请参考以下文章
动态代理模式——JDK动态代理
动态代理
设计模式 结构型模式 -- 代理模式(动态代理(JDK动态代理(JDK动态代理要求必须定义接口,对接口进行代理。)动态代理原理(使用arthas-boot.jar查看代理类的结构)动态代理的作用)(代
动态代理——JDK中的动态代理
Spring 静态代理+JDK动态代理和CGLIB动态代理
(java反射-JDK动态代理)+CGLIB动态代理