代理模式是java常用的设计模式之一,分为静态代理与动态代理。
静态代理
代理模式给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用。一般会有三个角色:抽象接口、真实对象、代理对象。真实对象、代理对象都需要继承抽象接口。
抽象角色:指代理角色和真实角色对外提供的公共方法,一般为一个接口
真实角色:需要实现抽象角色接口,定义了真实角色所要实现的业务逻辑,以便供代理角色调用。也就是真正的业务逻辑再次。
代理角色:需要实现抽象角色接口,是真实角色的代理,通过真实角色的业务逻辑方法来实现抽象方法,并可以附加自己的操作。将统一的流程控制都放到代理角色中处理。
目的:
- 通过引入代理对象的方式来间接访问目标对象,防止直接访问目标对象给系统带来的不必要复杂性
- 通过代理对象对访问进行控制
静态代理在使用时,需要定义接口或者父类,被代理对象与代理对象一起实现相同的接口或者继承相同父类。一般来说,被代理对象和代理对象时一对一的关系,当然一个代理对象对应多个被代理对象也是可以的。
静态代理,一对一则会出现时静态代理对象量多、代码量大,从而导致代码复杂,可维护性差的问题,一对多则代理对象会出现扩展能力差的问题。
示例:
/*
*接口
/
interface Person{
void study();
}
/*
*被代理对象(真实对象)
/
class Student implements Person{
@Override
public void study(){
System.out.println("学生的任务就是好好学习");
}
}
/*
*代理对象(代理类)
/
class StudentImpl implements Person{
private Student student;
public StudentImpl(Student student){
this.student=student;
}
@Override
public void study(){
System.out.println("学习之前需要检查学习工具是否齐全");
student.study
}
}
//使用
Student student=Student();
StudentImpl impl=new StudentImpl(student);
impl.study();
动态代理
动态代理的主要作用是我们使用动态代理时,系统会帮我们生成一个代理类已供调用。
主要分析几个方法的参数说明:
public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces, InvocationHandler h)throws IllegalArgumentException
参数:
- loader :定义代理的类加载器
- interfaces:代理类要实现的接口列表
- h:指派方法调用的调用处理程序
返回一个带有代理类的指定调用处理程序的代理实例,它由指定的类加载器定义,并实现制定的接口
实现InvocationHandle接口,该接口有一个方法Object invoke(Object proxy,Method method,Object[] args)
- Object proxy:表示需要代理的对象
- Method method:表示要操作的方法
- Object[] args:method方法所需要传入的参数
示例:
/*
*接口
/
interface Person{
void study();
}
/*
*被代理对象(真实对象)
/
class Student implements Person{
@Override
public void study(){
System.out.println("学生的任务就是好好学习");
}
}
/*
*代理对象(代理类)
/
class StudentHandler implements InvocationHandler {
private Object target;
public StudentImpl(Student student){
this.target=target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("学习之前需要检查学习工具是否齐全");
//通过反射调用方法
return method.invoke(target,args);
}
}
//使用
Student student=Student();
Class <?> proxyclazz=Proxy.getProxyClass(Person.class.getClassLoader(),Person.class);
Constructor <?> constructor=proxyclazz.getConstructor(InvocationHandler.class);
Person person = (Person)constructor.newInstance(new StudentHandler(student));
person.study();