深入理解Java动态代理与静态代理
静态代理
静态代理是为了实现被代理对象的方法增强而设计的一种代理方式。其中,被代理的对象接口和代理对象接口相同,代理对象持有被代理对象实例的引用,通过代理对象间接调用被代理对象的方法。静态代理的实现需要手工编写代理类,代理类需要实现被代理的所有接口方法,并在处理这些方法的时候添加额外的逻辑,如日志打印、性能监控、异常捕获等。
以下是一个静态代理的示例:
定义接口:
public interface IUserDao {
void save();
}
定义被代理类:
public class UserDao implements IUserDao {
@Override
public void save() {
System.out.println("保存用户");
}
}
定义代理类:
public class UserDaoProxy implements IUserDao {
private IUserDao userDao;
public UserDaoProxy(IUserDao userDao) {
this.userDao = userDao;
}
@Override
public void save() {
System.out.println("开始事务");
userDao.save();
System.out.println("提交事务");
}
}
测试代理:
public class StaticProxyTest {
public static void main(String[] args) {
IUserDao userDao = new UserDao();
UserDaoProxy userDaoProxy = new UserDaoProxy(userDao);
userDaoProxy.save();
}
}
输出结果:
开始事务
保存用户
提交事务
动态代理
动态代理是一种在运行时根据接口动态代理方法的类。它可以在运行时动态地创建被代理对象的代理类,并在代理类中实现被代理对象接口的所有方法,动态代理可以有效降低代码的耦合度、简化编码复杂度以及提高代码的可维护性。
动态代理一般通过JDK提供的接口实现,其中,被代理的对象需要实现接口,代理类不需要手工实现,因为在代理类中实现了被代理对象的所有接口方法。一般来说,我们常用的代理类就是JDK动态代理实现的代理类。
以下是一个使用JDK动态代理的示例:
定义接口:
public interface IUserDao {
void save();
}
定义被代理类:
public class UserDao implements IUserDao {
@Override
public void save() {
System.out.println("保存用户");
}
}
定义代理类:
public class UserDaoProxy implements InvocationHandler {
private Object target; // 被代理对象
public UserDaoProxy(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("开始事务");
Object result = method.invoke(target, args);
System.out.println("提交事务");
return result;
}
}
测试代理:
public class DynamicProxyTest {
public static void main(String[] args) {
IUserDao userDao = new UserDao();
InvocationHandler proxy = new UserDaoProxy(userDao);
ClassLoader classLoader = userDao.getClass().getClassLoader();
IUserDao userDaoProxy = (IUserDao) Proxy.newProxyInstance(classLoader, new Class[]{IUserDao.class}, proxy);
userDaoProxy.save();
}
}
输出结果:
开始事务
保存用户
提交事务
在JDK动态代理实现中,代理类的核心逻辑在invoke()
方法实现中,其中第一个参数是代理类的实例、第二个参数是正在被调用的接口方法、第三个参数是被调用接口方法的参数。在invoke()
方法中,我们可以调用被代理对象的相关方法,并在方法调用前后进行增强处理。
除了JDK动态代理,还有一些其他代理框架如:CGLIB、Javassist等,它们的实现原理与JDK动态代理并不一样,但是它们都可以实现动态代理的功能。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:深入理解Java动态代理与静态代理 - Python技术站