给目标对象提供一个代理对象,并由代理对象控制对目标对象的引用。其中代理对象起到中介作用,用于连接客户端和目标对象。例如:电脑桌面的快捷方式。电脑对某个程序提供一个快捷方式(代理对象),快捷方式连接客户端和程序,客户端通过操作快捷方式就可以操作那个程序。
通过引入代理对象的方式来间接访问目标对象,防止直接访问目标对象给系统带来的不必要复杂性。
步骤1: 创建抽象对象接口(Subject):声明你(真实对象)需要让代购(代理对象)帮忙做的事(买Mac)
public interface Subject {
public void buyMac();
}
步骤2: 创建真实对象类(RealSubject),即”我“
public class RealSubject implement Subject{
@Override
public void buyMac() {
System.out.println(”买一台Mac“);
}
}
步骤3:创建代理对象类(Proxy),即”代购“,并通过代理类创建真实对象实例并访问其方法
public class Proxy implements Subject{
@Override
public void buyMac{
//引用并创建真实对象实例,即”我“
RealSubject realSubject = new RealSubject();
//调用真实对象的方法,进行代理购买Mac
realSubject.buyMac();
//代理对象额外做的操作
this.WrapMac();
}
public void WrapMac(){
System.out.println(”用盒子包装好Mac“);
}
}
步骤4:客户端调用
public class ProxyPattern {
public static void main(String[] args){
Subject proxy = new Proxy();
proxy.buyMac();
}
}
结果输出
买一台Mac
用盒子包装好Mac
优点
协调调用者和被调用者,降低了系统的耦合度
代理对象作为客户端和目标对象之间的中介,起到了保护目标对象的作用
缺点
由于在客户端和真实主题之间增加了代理对象,因此会造成请求的处理速度变慢;
实现代理模式需要额外的工作(有些代理模式的实现非常复杂),从而增加了系统实现的复杂度。
在静态代理模式中一个静态代理只服务一种类型的目标对象,若要服务多类型的目标对象,则需要为每种目标对象都实现一个静态代理对象。在目标对象较多的情况下,若采用静态代理,则会出现 静态代理对象量多、代码量大,从而导致代码复杂的问题。
动态代理就是,在程序运行期,创建目标对象的代理对象,并对目标对象中的方法进行功能性增强的一种技术。在生成代理对象的过程中,目标对象不变,代理对象中的方法是目标对象方法的增强方法。可以理解为运行期间,对象中方法的动态拦截,在拦截方法的前后执行功能操作。
代理类在程序运行期间,创建的代理对象称之为动态代理对象。这种情况下,创建的代理对象,并不是事先在Java代码中定义好的。而是在运行期间,根据我们在动态代理对象中的“指示”,动态生成的。也就是说,你想获取哪个对象的代理,动态代理就会为你动态的生成这个对象的代理对象。动态代理可以对被代理对象的方法进行功能增强。有了动态代理的技术,那么就可以在不修改方法源码的情况下,增强被代理对象的方法的功能,在方法执行前后做任何你想做的事情。
1)动态代理不需要显式实现与目标对象类(RealSubject)相同的接口,而是将这种实现推迟到程序运行时由 JVM来实现。即:在使用时再创建动态代理类 & 实例;
2)通过Java 反射机制的method.invoke(),通过调用动态代理类对象方法,从而自动调用目标对象的方法。
优点
1)只需要1个动态代理类就可以解决创建多个静态代理的问题,避免重复、多余代码;
2)更强的灵活性;
缺点
1)效率低:相比静态代理中直接调用目标对象方法,动态代理则需要先通过Java反射机制 从而间接调用目标对象方法。
2)应用场景局限:Java 的单继承特性(每个代理类都继承了 Proxy 类),即只能针对接口创建代理类,不能针对类创建代理类。
日志记录、性能统计、安全控制、异常处理等。
1.创建接口,定义目标类需要完成的功能
2.创建目标类,实现接口。
3.创建InvocationHandler接口的实现类。在invoke方法中完成代理类的功能。
目标方法的调用
功能增强
4.使用Proxy类中静态方法Proxy.newProxyInstance完成代理类对象的创建,返回代理对象,并把返回值转为接口类型。
public class JDKDynamicProxy {
public static void main(String[] args) {
CAProxy caProxy = new CAProxy();
IA instance = (IA) caProxy.getInstance(new CA());
instance.say();
instance.fly();
}
}
interface IA{
void say();
void fly();
}
class CA implements IA{
@Override
public void say() {
System.out.println("I am class CA");
}
@Override
public void fly() {
System.out.println("I can fly");
}
}
class CAProxy implements InvocationHandler{
private Object target;
public Object getInstance(Object object){
this.target = object;
return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("I am proxy!");
Object result = method.invoke(target, args);
return result;
}
}
public class CglibDynamicProxy {
public static void main(String[] args) {
CglibProxy cglibProxy = new CglibProxy();
A a = (A) cglibProxy.getInstance(new A());
a.say();
}
}
class A {
public void say(){
System.out.println("I am A");
}
}
class CglibProxy implements MethodInterceptor{
private Object target;
public Object getInstance(Object object){
this.target = object;
Enhancer enhancer = new Enhancer();
// 设置父类为实例类
enhancer.setSuperclass(this.target.getClass());
// 回调方法
enhancer.setCallback(this);
// 创建代理对象
return enhancer.create();
}
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("I am cglib proxy!");
Object result = method.invoke(target, objects);
return result;
}
}