Java代理模式:实现灵活的控制访问
代理模式是常用的设计模式之一,它提供了一种方式来控制对某个对象的访问,通过引入一个代理对象来间接访问目标对象。在Java中,代理模式广泛应用于远程方法调用、AOP(面向切面编程)等场景。本文将介绍Java代理模式的两种实现方式:静态代理和动态代理,并通过示例代码展示它们的应用。
一、静态代理
静态代理是指在编译时就已经确定代理类、代理方法和被代理类、被代理方法之间的关系。这种方式需要手动创建代理类,实现与被代理类相同的接口或继承相同的父类,并在代理类中调用被代理对象的方法。
下面是一个简单的静态代理示例,其中有一个接口IUserDao,一个实现类UserDaoImpl和一个代理类UserDaoProxy:
public interface IUserDao {void addUser();void deleteUser();
}public class UserDaoImpl implements IUserDao {@Overridepublic void addUser() {System.out.println("添加用户");}@Overridepublic void deleteUser() {System.out.println("删除用户");}
}public class UserDaoProxy implements IUserDao {private IUserDao userDao;public UserDaoProxy(IUserDao userDao) {this.userDao = userDao;}@Overridepublic void addUser() {before();userDao.addUser();after();}@Overridepublic void deleteUser() {before();userDao.deleteUser();after();}private void before() {System.out.println("前置处理");}private void after() {System.out.println("后置处理");}
}
在上面的代码中,UserDaoProxy是代理类,它实现了IUserDao接口,并在构造方法中传入了一个IUserDao类型的对象。在代理类中,我们可以添加一些额外的操作,比如前置处理和后置处理。这样,在调用addUser()和deleteUser()方法时,就会先执行before()方法,再执行目标方法,最后执行after()方法。
二、动态代理
动态代理是指在运行时动态地创建代理类,并实现一组给定的接口。Java提供了java.lang.reflect.Proxy类和java.lang.reflect.InvocationHandler接口来支持动态代理。动态代理相比静态代理更加灵活,可以动态地为目标对象创建代理,而不需要手动编写代理类。
下面是一个使用动态代理的示例,其中有一个接口IUserDao,一个实现类UserDaoImpl和一个实现了InvocationHandler接口的类UserDaoInvocationHandler:
public interface IUserDao {void addUser();void deleteUser();
}public class UserDaoImpl implements IUserDao {@Overridepublic void addUser() {System.out.println("添加用户");}@Overridepublic void deleteUser() {System.out.println("删除用户");}
}import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;public class UserDaoInvocationHandler implements InvocationHandler {private Object target;public UserDaoInvocationHandler(Object target) {this.target = target;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {before();Object result = method.invoke(target, args);after();return result;}private void before() {System.out.println("前置处理");}private void after() {System.out.println("后置处理");}public Object getProxy() {return Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),this);}
}
在上面的代码中,UserDaoInvocationHandler实现了InvocationHandler接口,并在构造方法中传入了一个目标对象。在invoke()方法中,我们可以添加一些额外的操作,比如前置处理和后置处理。在getProxy()方法中,我们使用Proxy.newProxyInstance()方法动态地为目标对象创建代理对象,并返回该代理对象。
需要注意的是,动态代理只能代理接口,不能代理类。因此,目标对象必须实现至少一个接口。
三、总结
Java代理模式是一种常用的设计模式,它提供了一种灵活的方式来控制对某个对象的访问。静态代理需要手动创建代理类,实现与被代理类相同的接口或继承相同的父类。动态代理则可以在运行时动态地为目标对象创建代理对象,更加灵活。无论是静态代理还是动态代理,代理对象都可以添加一些额外的操作,比如前置处理和后置处理,从而增强目标对象的功能。