什么是代理模式?
代理模式的定义:代理模式给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用。这样做的好处是:可以在目标对象实现的基础上,增强额外的功能操作,即扩展目标对象的功能。
代理模式两类:静态代理和动态代理
静态代理
静态代理角色
抽象角色:声明真实对象和代理对象的共同接口。
代理角色:代理对象角色内部含有对真实对象的引用,从而可以操作真实对象,同时代理对象提供与真实对象相同的接口以便在任何时刻都能够代替真实对象。同时,代理对象可以在执行真实对象操作时,附加其他的操作,相当于对真实对象进行封装。
真实角色:代理角色所代表的真实对象,是我们最终要引用的对象。
package com.example.demo.jProxy;
public interface Subject {
public void request();
}
package com.example.demo.jProxy;
public class RealSubject implements Subject{
@Override
public void request() {
System.out.println("真实对象调用");
}
}
package com.example.demo.jProxy;
public class Proxy implements Subject{
//代理角色具有真实角色的引用
private Subject subject;
public Proxy(Subject subject){
this.subject = subject;
}
@Override
public void request() {
System.out.println("真实角色代理之前---");
subject.request();
System.out.println("真实角色代理之后---");
}
}
package com.example.demo.jProxy;
public class Client {
public static void main(String[] args){
Proxy proxy = new Proxy(new RealSubject());
proxy.request();
}
}
静态代理类优缺点
优点:业务类只需要关注业务逻辑本身,保证了业务类的重用性。这是代理的共有优点。
缺点:
1.代理对象的一个接口只服务于一种类型的对象,如果要代理的方法很多,势必要为每一种方法都进行代理,静态代理在程序规模稍大时就无法胜任了。
2.如果接口增加一个方法,除了所有实现类需要实现这个方法外,所有代理类也需要实现此方法。增加了代码维护的复杂度。
动态代理
动态代理是spring Aop实现的核心,它通过jdk动态代理和cglib动态代理,jdk动态代理是由java内部的反射机制来实现的,cglib动态代理是通过继承来实现的,底层则是借助asm(Java 字节码操控框架)来实现的(采用字节码的方式,给A类创建一个子类B,子类B使用方法拦截的技术拦截所以父类的方法调用)。
jdk动态代理
package com.example.demo.Proxy;
public interface AbstractSubject {
public void request();
}
package com.example.demo.Proxy;
public class realSubject implements AbstractSubject{
@Override
public void request() {
System.out.println("真实主题类");
}
}
package com.example.demo.Proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class DynamicProxy implements InvocationHandler{
private Object object;
public DynamicProxy(Object object){
this.object = object;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("织入调用之前");
Object result = method.invoke(object, args);
System.out.println("织入调用之后");
return result;
}
}
package com.example.demo.Proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
public class client {
public static void main(String[] args) {
//生成$Proxy0的class文件
//System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
InvocationHandler handler = new DynamicProxy(new realSubject());
AbstractSubject subject = (AbstractSubject) Proxy.newProxyInstance(AbstractSubject.class.getClassLoader(),
new Class[]{AbstractSubject.class}, handler);
subject.request();
}
}
动态代理的优势在于可以很方便的对代理类的函数进行统一的处理,而不用修改每个代理类中的方法。是因为所有被代理执行的方法,都是通过在InvocationHandler中的invoke方法调用的,所以我们只要在invoke方法中统一处理,就可以对所有被代理的方法进行相同的操作了。
cglib动态代理
CGLib采用非常底层的字节码技术,可以为一个类创建子类,并在子类中采用方法拦截的技术拦截所有的父类方法的调用,并顺势织入横切逻辑。CGlib和JDK的原理类似,也是通过方法去反射调用目标对象的方法。
package com.example.demo.cglib;
public class subject {
public void request(){
System.out.println("代理对象调用");
}
}
package com.example.demo.cglib;
import java.lang.reflect.Method;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
public class CglibProxy implements MethodInterceptor{
private Enhancer enhancer = new Enhancer();
public Object getProxy(Class clazz) {
enhancer.setSuperclass(clazz);
enhancer.setCallback(this);
return enhancer.create();
}
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println("织入之前");
Object result = proxy.invokeSuper(obj, args);
System.out.println("织入之后");
return result;
}
}
package com.example.demo.cglib;
public class Client {
public static void main(String[] args){
CglibProxy Proxy = new CglibProxy();
subject subject = (subject)Proxy.getProxy(subject.class);
subject.request();
}
}