代理模式
代理模式是一种设计模式,提供了对目标对象额外的访问方式,即通过代理对象访问目标对象,这样可以在不修改原目标对象的前提下,提供额外的功能操作,扩展目标对象的功能。
简而言之,代理模式就是设置一个中间代理(通俗意义上的中介)来控制访问原目标对象,以达到增强原对象的功能和简化访问方式。
静态代理
这种代理方式需要代理对象和目标对象实现一样的接口。
1)创建一个接口
//针对用户访问的接口
public interface UserDao {
//增加功能
void add();
//修改功能
void update();
//查询功能
void select();
//删除功能
void delete();
}
2)创建一个目标类
**
* 针对用户访问数据接口的实现
*/
public class UserDaoImp implements UserDao {
@Override
public void add() {
System.out.println("增");
}
@Override
public void update() {
System.out.println("改");
}
@Override
public void select() {
System.out.println("查");
}
@Override
public void delete() {
System.out.println("删");
}
}
3)创建一个代理类
public class JdkProxy {
public static void main(String[] args) {
//接口多态测试userDao
UserDao ud = new UserDaoImp();
ud.add();
ud.delete();
ud.select();
ud.update();
System.out.println("----------------------");
UserDao ud1 = new UserDaoImp2();
ud1.update();
ud1.select();
ud1.delete();
ud1.add();
}
}
jdk动态代理
JDK代理利用了JDK API,动态地在内存中构建代理对象,从而实现对目标对象的代理功能。动态代理又被称为JDK代理或接口代理。
静态代理与动态代理的区别主要在:
静态代理在编译时就已经实现,编译完成后代理类是一个实际的class文件。
动态代理是在运行时动态生成的,即编译完成后没有实际的class文件,而是在运行时动态生成类字节码,并加载到JVM中。
特点:
动态代理的代理类不需要实现接口,但是要求目标类必须实现接口,否则不能使用动态代理。
动态代理例子
1)接口
在动态代理中,这个接口代理类不需要实现,但是被代理类必须实现,否则不能使用动态代理。
Tips: 静态代理的话,代理类和被代理类都需要实现相同的接口。
public interface IUserDao {
void addUser();
}
2)目标类
public class UserDao implements IUserDao {
@Override
public void addUser() {
System.out.println("这是目标类 --> 新增用户");
}
}
3)代理类
动态代理的代理类不需要实现接口,它是动态地在内存中构建代理对象。
public class ProxyFactory {
// 用这个变量来存储被代理对象。
private Object target;
// 代理类的构造方法,把被代理对象作为参数传进去。
public ProxyFactory(Object target) {
this.target = target;
}
// 为被代理对象生成代理对象
public Object getProxyInstance() {
// target.getClass().getClassLoader():被代理类的类加载器
// target.getClass().getInterfaces():被代理类实现的接口
// InvocationHandler(): 需要在其中的 invoke() 方法中增强接口中的方法
return Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
new InvocationHandler() {
@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)测试
public class ProxyTest {
public static void main(String[] args) {
// 创建一个被代理对象
IUserDao target = new UserDao();
// 生成一个代理对象
IUserDao proxy = (IUserDao) new ProxyFactory(target).getProxyInstance();
// 用代理对象执行方法
proxy.addUser();
}
}