http://rejoy.iteye.com/blog/1627405
这篇文章说的够详细了。但是对照传智播客那个视频,貌似有点问题。
return Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),
target.getClass().getInterfaces(), this);
上面的类加载器,视频中推荐是用目标对象的类加载器。
return Proxy.newProxyInstance(target.getClass.getClassLoader().getContextClassLoader(),
target.getClass().getInterfaces(), this);
还有,把那个代理类改个名字好点,改成某某工厂类,不然听着怪难受的。
package dynamic.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* 实现自己的InvocationHandler
* @author zyb
* @since 2012-8-9
*
*/
public class MyInvocationHandler implements InvocationHandler {
// 目标对象
private Object target;
/**
* 构造方法
* @param target 目标对象
*/
public MyInvocationHandler(Object target) {
super();
this.target = target;
}
/**
* 执行目标对象的方法
*/
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 在目标对象的方法执行之前简单的打印一下
System.out.println("------------------before------------------");
// 执行目标对象的方法
Object result = method.invoke(target, args);
// 在目标对象的方法执行之后简单的打印一下
System.out.println("-------------------after------------------");
return result;
}
/**
* 获取目标对象的代理对象
* @return 代理对象
*/
public Object getProxy() {
return Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),
target.getClass().getInterfaces(), this);
}
}
改成:
package cn.itcast.service.impl;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* @author Administrator
* JDK动态代理工厂。根据目标对象生成代理对象
*/
public class JDKProxyFactory implements InvocationHandler{
//要代理的对象
private Object targetObject;
//负责生成代理对象的工厂方法
public Object createProxyObject(Object object){
//生成PersonServiceBean的代理对象
this.targetObject = object;
Proxy.newProxyInstance(targetObject.getClass().getClassLoader(), targetObject.getClass().getInterfaces(), this);
return null;
}
//代理对象,在获知要调用目标对象的方法时,会回调该方法。在该方法中,代理对象要把对目标对象的操作,委派目标对象执行。
/*
* 有一台打印机(目标对象)实现3C标准(接口,没有质量保证,谁敢用),具有打印功能(方法)。
* 有一个会操作打印机的人(代理对象),店主。
* 现在有人来打印,就叫店主帮他打印。店主知道了客人要求要打印(请求)
* 可是店主自己本身不能打印啊(会打印还得了),核对一下打印的文件(打印前),
* 只能给打印机输入打印指令和参数,让他进行打印(委派目标对象进行处理),收集文件(打印后)
*
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
Object result ;
// TODO Auto-generated method stub
System.out.println("目标对象执行方法前");
result = method.invoke(targetObject, args);
System.out.println("目标对象执行方法后");
return result;
}
}
测试代码:
package junit.test;
import static org.junit.Assert.*;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import cn.itcast.service.PersonService;
import cn.itcast.service.impl.JDKProxyFactory;
import cn.itcast.service.impl.PersonServiceBean;
public class SpringTest {
@Test
public void jdkProxyTest(){
ApplicationContext ctx = new ClassPathXmlApplicationContext(new String[]{"beans.xml"});
PersonService bean = (PersonServiceBean)ctx.getBean("personService1");
//这里就不同过容器进行创建PersonService了
JDKProxyFactory jf = new JDKProxyFactory();
//因为代理对象实现了目标对象的所有接口,所以也可以生产的代理对象也是可以赋值给PersonSercvice
PersonService personService2 = (PersonService) jf.createProxyObject(bean);
personService2.save();
}
}