AOP的原理之:JDK的动态代理

废话少说,直接上代码,因为这是面试常考的点,所以放到博客这边利于查看,同时这也是很久以前学习过的知识点,借此机会重温一遍。

一,首先定义接口和具体的实现类:

//接口
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方法,产生的代理是“被代理类”增强后的类。

上一篇:Mybatis的模糊查询以及其它操作


下一篇:##Mybatis框架之—— 基于代理 Dao 实现 CRUD 操作