废话少说,直接上代码,因为这是面试常考的点,所以放到博客这边利于查看,同时这也是很久以前学习过的知识点,借此机会重温一遍。
一,首先定义接口和具体的实现类:
//接口
public interface UserDao {
public void save();
public void update();
public void delete();
public void find();
}
//实现类
public class UserDaoImpl implements UserDao{
public void save() {
System.out.println("保存用户");
}
public void update() {
System.out.println("修改用户");
}
public void delete() {
System.out.println("删除用户");
}
public void find() {
System.out.println("查找用户");
}
}
二,编写代理类:
//手动编写的代理转化类,目的是为了增强保存用户的方法,加上一个“权限校验”
public class MyJdkProxy implements InvocationHandler {
//创建userDao的代理类,对它进行增强
private UserDao userDao;
public MyJdkProxy(UserDao userDao){
this.userDao = userDao;
}
//jdk的动态代理可以对实现了接口的类进行代理
public Object createProxy(){
//newProxyInstance方法需要三个参数,该实现类的类加载器,该实现类的接口,还有
//实现了InvocationHandler接口的实现类实例,这里因为本类实现了InvocationHandler接口,所以填this就可以,
//如果本类没有实现该接口,则可以使用该接口的匿名内部类
Object proxy = Proxy.newProxyInstance(userDao.getClass().getClassLoader(),userDao.getClass().getInterfaces(),this);
return proxy;
}
@Override
//代理实例,调用的方法,方法的参数列表
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//如果匹配到方法,就先增强再返回代理对象。
if("save".equals(method.getName())){
//增强代码:
System.out.println("权限校验");
return method.invoke(userDao,args);
}
//调用原封不动的代码
return method.invoke(userDao,args);
}
}
三、编写测试类:
//测试类
public class SpringDemo1 {
@Test
public void demo1(){
//原始代码:
//UserDao userDao = new UserDaoImpl();
//userDao.save();
//userDao.update();
//userDao.delete();
//userDao.find();
UserDao userDao = new UserDaoImpl();
UserDao proxy = (UserDao) new MyJdkProxy(userDao).createProxy();
proxy.save();
proxy.update();
proxy.delete();
proxy.find();
}
}
四、运行结果:(保证了对保存用户方法的增强,即先进行了校验)
//运行结果
权限校验
保存用户
修改用户
删除用户
查找用户
五、InvocationHandler接口的源码:
package java.lang.reflect;
ic interface InvocationHandler {
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable;
}
总结:代理类必须要实现JAVA中的InvocationHandler接口,重写invoke方法,产生的代理是“被代理类”增强后的类。