由于静态代理的局限性,dao层的变动会导致拦截器的变动,由此带来的一系列框架上的修改,这种缺陷无疑是十分致命的,于是动态代理应运而生。
动态代理通过反射机制实现对dao功能的加载。
应用场景:大量方法需要进行一些公共的操作,比如增删改查前的日志记录、权限验证等。这些代码全放在一个方法中完成的话,会有很多重复性的地方,且不易维护。
Spring AOP(面向切面编程)使用的也是这一技术。
示例场景:用户注册登录前进行权限检查,完成后进行日志记录(通过控制台模拟)
代码示例:
1. 用户注册和登录的功能接口
package jj.DynamicProxy;
public interface UserDao {
abstract void regist(String user,String pd);
abstract void login();
}
2. 注册和登录接口的实现
package jj.DynamicProxy;
public class UserDaoImpl implements UserDao{
@Override
public void regist(String user,String pd) {
System.out.println("正在注册账号。。。for " + user);
}
@Override
public void login() {
System.out.println("正在登陆账号。。。");
}
}
3. 定义拦截器
package jj.DynamicProxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class MyInvocationHandler implements InvocationHandler{
private Object target;
public MyInvocationHandler(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("权限检查。。。");
method.invoke(target, args);
System.out.println("日志记录。。。");
return null;
}
}
4.测试类
package jj.DynamicProxy;
import java.lang.reflect.Proxy;
public class TestProxy {
public static void main(String[] args) {
UserDaoImpl ui = new UserDaoImpl();
MyInvocationHandler myHandler = new MyInvocationHandler(ui);
//返回一个指定接口的代理类实例
UserDao dao= (UserDao)Proxy.newProxyInstance(ui.getClass().getClassLoader(), ui.getClass().getInterfaces(), myHandler);
dao.regist("jj","123");
dao.login();
}
}