(1)定义接口,此接口是被代理对象实现的接口
public interface UserDAO {
public void save(User u);
}
(2)被代理类,实现了上面定义的接口,对内部的save方法进行了重写,我们要在这个被代理类的前面或者后面加一些其他的逻辑,而该程序本身只有class文件,改不了源码
public class UserDAOImpl implements UserDAO{
public void save(User u) {
System.out.println("user saved!");
}
}
(3)假如要在上面类的后面加上一些日志内容,那么首先要写一个代理类实现InvocationHandler
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class LogInterceptor implements InvocationHandler{
private Object target;
public LogInterceptor(Object target) {
this.target = target;
}
public void beforeMethod() {
System.out.println("save start");
}
@Override
public Object invoke(Object proxy, Method m, Object[] args)
throws Throwable {
beforeMethod();
m.invoke(target,args);//调用target对象的m方法
return null;
}
}
(4)客户端调用:
import static org.junit.Assert.*;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import org.junit.Test;
public class UserServiceTest {
@Test
public void testAdd() throws Exception {
BeanFactory factory = new ClassPathXmlApplicationContext();
UserService service = new UserService();
UserDAO userDAO = (UserDAO) factory.getBean("u");
service.setUserDAO(userDAO);
User u = new User();
service.add(u);
}
@Test
public void testProxy() {
UserDAOImpl userDAO = new UserDAOImpl();
LogInterceptor h = new LogInterceptor(userDAO);
UserDAO userDAOProxy = (UserDAO)Proxy.newProxyInstance(UserDAO.class.getClassLoader(), new Class[]{UserDAO.class}, h);//和被代理对象用同一个classloader,或者userDAO.getClass().getClassLoader();第二个参数指产生的被代理对象应该实现那些接口,本类只实现了UserDAO,也可以写成,userDAO.getClass().getInterfaces()? 第三个是: 当我产生代理之后我调用代理里面的方法之后用哪一个Handler进行处理
userDAOProxy.save(new User());
}
}