为目标对象创建一个替身,以控制对这个对象的访问,即通过代理对象访问目标对象。
好处:可以对目标对象的功能进行扩展。
代理模式一般有三种:静态代理,jdk代理,cglib代理
这三种形式的区别就在于:
1、静态代理和jdk代理的被代理对象都需要实现接口,而cglib的被代理对象不需要实现接口。
2、静态代理的代理对象需要实现接口,而jdk代理和cglib代理不需要实现接口。
3、静态代理是手动生成代理对象,而jdk代理和cglib代理是在内存中动态创建对象。
4、静态代理和jdk代理不需要额外导包,而cglib需要额外导包。
首先,写一个接口和一个被代理对象所需的类。
public interface ICalculator {
public int add(int a, int b);
}
public class Calculator implements ICalculator{
@Override
public int add(int a, int b) {
return a + b;
}
}
静态代理
代理类:
public class CalculatorProxy implements ICalculator{
private ICalculator target;
public CalculatorProxy(ICalculator target) {
this.target=target;
}
@Override
public int add(int a, int b) {
System.out.println("静态代理开始");
int res = target.add(a, b);
System.out.println("静态代理结束");
return res;
}
}
实现代理模式:
public static void main(String[] args) {
ICalculator target = new Calculator();
CalculatorProxy proxy = new CalculatorProxy(target);
int add = proxy.add(1, 2);
System.out.println(add);
}
jdk代理
使用了反射技术,来实现动态代理。
代理类:
public class CalculatorDynamicProxy {
private ICalculator target;
public CalculatorDynamicProxy(ICalculator target) {
this.target=target;
}
public Object getProxyInstance() {
//通过反射动态生成代理对象
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("jdk代理开始");
Object res = method.invoke(target, args);
System.out.println("jdk代理结束");
return res;
}
});
}
}
实现代理模式:
public static void main(String[] args) {
ICalculator target = new Calculator();
ICalculator proxy = (ICalculator) new CalculatorDynamicProxy(target).getProxyInstance();
int add = proxy.add(1, 3);
System.out.println(add);
}
Cglib代理
使用cglib代理又可以称之为子类代理。它会在内存中构建一个子类对象,从而实现对目标对象的功能扩展。
因此,若是被代理的类是final的,那么会抛出异常;若是执行的目标方法是final/static的,那么不会被拦截,即不会执行目标对象额外的业务方法。
public class Calculator{
public int add(int a, int b) {
return a + b;
}
}
public class CalculatorCglibProxy implements MethodInterceptor {
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("cglib代理开始");
Object res = methodProxy.invokeSuper(o, objects);
System.out.println("cglib代理结束");
return res;
}
public Object getProxyInstance(Class clazz) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(clazz);
enhancer.setCallback(this);
return enhancer.create();
}
}
public static void main(String[] args) {
Calculator proxy = (Calculator) new CalculatorCglibProxy().getProxyInstance(Calculator.class);
int add = proxy.add(1, 2);
System.out.println(add);
}