JDK动态代理必须要有接口,且JDK提供的代理只能针对接口做代理。
Spring 框架,使用代理模式对目标对象中的功能进行增强
动态代理设计模式:可以在不修改源代码的清空下,对功能做出增强。
代理对象是在运行期间,通过反射生成的。
Proxy 代理类可以生成代理对象。
- 首先是创建接口类对象;
接口类:
public interface UserDao {
void insert();
void update();
}
接口实现类:现在就是想实现类中的功能进行增强;
传统的方法需要在此部分直接操作,不易于维护和开发,利用动态代理更易于实现;
public class UserDaoImpl implements UserDao {
@Override
public void insert() {
System.out.println("添加用户");
}
@Override
public void update() {
System.out.println("修改用户");
}
}
- 创建动态代理类,使用目标实现类作为参数,进而进行增强和更新;
在使用代理类调用:
newProxyInstance (ClassLoader loader, Class < ?>[]interfaces, InvocationHandler h),
这个方法的时候需要传入:
参数1. *ClassLoader:类加载器:它是用于加载代理对象字节码的,和被代理对象使用相同的类加载器,是固定写法。
参数2:Class[]:字节码数组:它是用于让代理对象和被代理对象有相同方法。固定写法。
参数3:InvocationHandler:用于提供增强的代码,它是让我们写如何代理。我们一般都是些一个该接口的实现类,通常情况下都是匿名内部类,但不是必须的。此接口的实现类都是谁用谁写。
public class ProxyUtils {
public static UserDao getProxy(UserDao dao) { //传入过来的目标对象
UserDao obj= (UserDao) Proxy.newProxyInstance(dao.getClass().getClassLoader(), dao.getClass().getInterfaces(), new InvocationHandler() {
重写的方法中,若判断为两者中的某一个,即对此方法增强;
方法参数同时也需要
proxy:代理对象的引用
method:当前执行的方法,也就是需要增强目标实现类中的方法;
args :当前执行方法所需的参数
return :和被代理对象方法有相同的返回值,即返回增强后的方法对象;
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object invoke=null;
if(method.getName().equals("insert")||method.getName().equals("update")){
System.out.println("权限校验");
invoke = method.invoke(dao); //调用目标对象中的方法
System.out.println("记录日志");
}
return invoke;
}
});
创建对象后,返回一个指定接口的代理类实例,该接口可以将方法调用指派到指定的调用处理程序。
return obj;
}
}
测试类:
1. 创建接口类对象实例
UserDao dao = new UserDaoImpl();
2. 获取代理对象:调用静态类获取一个代理类实例对象;
UserDao proxy = ProxyUtils.getProxy(dao);
3. 使用代理类对象调用目标增强方法;
proxy.insert();
proxy.update();
从而实现对目标对象的功能进行增强,如下图: