要说动态代理,应该先由静态代理说起。所谓静态代理,个人认为就是使用组合代替继承。
静态代理例子如下:
UserDao 类
package common.test.dao;
/**
* 对用户操作接口
*/
public interface UserDao {
public void addUser();
}
package common.test.dao.impl;
import common.test.dao.UserDao;
public class UserDaoImpl implements UserDao {
@Override
public void addUser() {
System.out.println("add user...");
}
}
客户端类 public Class Test { public static void main(String args[]) { UserDao userDao = new UserDaoImpl(); userDao.addUser(); } }
现在若想改变UserDao实现,想在执行addUser前添加日志。因此需要修改UserDaoImpl。
如果使用继承的话,可以这样改写UserDaoImapl
public Class UserDaoImpl2 extends UserDaoImpl {
public void addUser() {
System.out.println("记录日志");
super.addUser();
}
}
由于继承具有确定,现在使用组合代替继承
public Class UserDaoImpl2 implements UserDao() {
UserDao userDao = new UserDaoImpl();
public void addUser() {
System.out.println("记录日志");
userDao.addUser();
}
}
这样修改后,客户端代码可改成
public static void main(String[] args){
UserDao dao = new UserDaoImpl2();
dao.addUser();
}
这就是静态代理,本来是要操作UserDaomIpl的,但为了在执行方法前添加一些其它的业务逻辑,然后使用了组合的方式写了UserDaoImpl2,但在UserDaoImpl2中还是调用了UserDaoImpl,所以把UserDaoImpl2 看成UserDaoImpl的代理类了。而原来的UserDaoImpl 成为委托类。
由于代理类是在编译前就有的,所以称其为静态的。
现在若想动态生成 UserDaoImpl2,可这样写。
package common.test.service; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; public class ProxyHandler implements InvocationHandler { Object target; public ProxyHandler(Object target) { super(); this.target = target; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("before ...."); method.invoke(target, null); System.out.println("after ..."); return null; } }
package common.test.service; import java.lang.reflect.Proxy; import common.test.dao.UserDao; import common.test.dao.impl.UserDaoImpl; public class Test { public static void main(String[] args) { UserDaoImpl userDao = new UserDaoImpl(); ProxyHandler handler = new ProxyHandler(userDao); UserDao dao = (UserDao) Proxy.newProxyInstance(userDao.getClass().getClassLoader(), userDao.getClass().getInterfaces(), handler); dao.addUser(); } }