//在接触动态代理之前,首先你要先知道一些反射知识,这样方便理解动态代理。
package com.reflectProxy;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class MyReflectProxy {
private Class clazz; //对象所属的类
private Object target; //目标对象
private Method method; //目标方法
public void target(Object target){
this.target = target; //设置目标对象
this.clazz = target.getClass(); //设置目标对象类
}
public Object doMethod(String methodName){
return doMethod(methodName,null);
}
//执行方法
public Object doMethod(String methodName, Object ... params) { //类似数组用法,无限制大小
//重新设置目标方法的参数
Class[] paramTypes = null;
//将方法的对象参数数组转为对应的类参数数组
if(params!=null){
paramTypes = new Class[params.length];
for(int i = 0 ; i < params.length ; i ++ ) {
paramTypes[i] = params[i].getClass();
}
}
try {
//利用反射机制得到方法对象
this.method = clazz.getMethod(methodName, paramTypes); //第二个参数为Class类型
//执行该方法
return this.method.invoke(target, params);
} catch (NoSuchMethodException | SecurityException e1) {
e1.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
return null;
}
}
//测试调用,使用反射来对对象操作
package com.reflectProxy;
import com.entity.Student;
/**
* 用反射方法操作对象
* @author qiugaoying
*/
public class Application {
public static void main(String[] args) {
Student s=new Student();
MyReflectProxy mf=new MyReflectProxy();
mf.target(s);
mf.doMethod("setStuName", "小高");
mf.doMethod("setStuAge",19);
System.out.println("name:"+ mf.doMethod("getStuName")+"age:"+mf.doMethod("getStuAge"));
}
}
/*----------------------------------动态代理-----------------------------------*/
//准备一个接口
package com.Proxy;
public interface Account {
// 查看账户方法
public void queryAccount();
// 修改账户方法
public String updateAccount(String name, String pwd);
//接口实现类
package com.Proxy;
public class AccountImp implements Account {
@Override
public void queryAccount() {
System.out.println("查询账号--------");
}
@Override
public String updateAccount(String name, String pwd) {
System.out.println("更新账号---------");
pwd="000000";
return name+","+pwd;
}
}
//代理类
package com.Proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* 动态代理类
* @author qiugaoying
* 该动态代理利用反射机制,动态获得任何对象的任何方法, 只能代理实现接口的类。
* java.lang.reflect 包中的Proxy类和InvocationHandler 接口提供了生成动态代理类的能力
*/
public class DynamicProxy implements InvocationHandler{
private Object target;
//绑定对象
public Object target(Object target){
this.target=target;
return Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(), this); //返回一个代理对象
}
//动态调用方法
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
// TODO Auto-generated method stub
Object obj=null;
beforeMethod();
//执行前
obj= method.invoke(target, args);
afterMethod();
//执行后
return obj;
}
private void beforeMethod(){
System.out.println("事务开始...");
}
private void afterMethod(){
System.out.println("事务结束...");
}
}
//动态代理 测试
package com.Proxy;
/** 利用动态代理来执行
* @author qiugaoying
*/
public class Application {
public static void main(String[] args) {
Account ac=new AccountImp();
DynamicProxy dp=new DynamicProxy(); //准备一个代理
//绑定代理对象
ac=(Account) dp.target(ac);
ac.queryAccount();
//有参数
String newPwd=ac.updateAccount("小雪", "123456");
System.out.println(newPwd);
}
}
总结:生活中处处充满代理。卖房子的中介所。体育明星的经济人。玩游戏的代理者。等等。 程序中,代理类利用反射机制,实现了任何类任何方法的代理,可谓之强大,在第一次学完代理模式,我只是在停留在静态代理上,认为代理模式和装饰模式差不多,
经过此番动态代理的深入学习,体会代理类之强大,
这让程序员更加专注于业务上
。代理模式可让所有的类都给封装了相同的前后处理方法。而装饰模式是给一个类包装不同的方法。
2012-12-16 小高