代理模式是一种结构性模式
结构性模式是解决类或对象组合在一起的经典结构
结构性模式包括:代理模式,桥接模式,装饰者模式,适配器模式,门面模式,组合模式,享元模式
代理模式的原理:在不改变原始类的情况下,通过引入原始类(代理类)的情况下,对原始类附加新的功能。
代理模式又分为静态代理和动态代理
静态代理:程序员手动创建,在程序运行前,已经存在代理类的字节码文件
动态代理:程序运行过程中通过反射创建。
静态代理通过继承或者实现接口的方式,对函数方法进行增强。
缺点:为每一个服务都需要创建一个代理类,如果服务特别多,不利于管理
动态代理:
如果被代理类有接口,使用jdk的动态代理
如果被代理的类没有实现接口,且类没有被final 修饰使用cglib的动态代理。
jdk 动态代理的实现
/**
* 被代理类实现的接口
* */
public interface Subject {
/** 被代理类要执行的方法 */
void buyHouse();
}
/**
* @Description: 被代理类
* @Date: 2020/5/12 17:59
* @Author: fuguowen
* @Return
* @Throws
*/
public class RealSubject implements Subject {
/** 目标方法 */
public void buyHouse() {
System.out.println("我会买房子");
}
}
/**
* @Description: 代理类 实现InvocationHandle 接口
* 重写invoke 方法
* 为什么要实现InvocationHandle 接口 Proxy.newProxyInstance()的第三个参数是一个InvocationHandler接口
* @Date: 2020/5/12 17:59
* @Author: fuguowen
* @Return
* @Throws
*/
public class DynamicProxyHandler implements InvocationHandler {
private Object object;
public DynamicProxyHandler(final Object object) {
this.object = object;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("我会找房源");
Object result = method.invoke(object, args);
return result;
}
}
/**
* @Description: JDK 动态代理类的测试
* @Date: 2020/5/12 18:19
* @Author: fuguowen
* @Return
* @Throws
*/
public class MainClass {
public static void main(String[] args) {
/** 创建被代理类 */
Subject subject = new RealSubject();
/**
* ClassLoader loader:指定当前目标对象使用的类加载器,获取加载器的方法是固定的
* Class<?>[] interfaces:指定目标对象实现的接口的类型,使用泛型方式确认类型
* InvocationHandler:指定动态处理器,执行目标对象的方法时,会触发事件处理器的方法
* 找到被代理类的类加载器,被代理类实现的接口,代理类
*/
Subject proxySubject = (Subject) Proxy.newProxyInstance(Subject.class.getClassLoader(),
new Class[]{Subject.class},
new DynamicProxyHandler(subject));
/** 执行被代理类对应的方法 */
proxySubject.buyHouse();
}
}
cglib的动态代理
CGLib采用了非常底层的字节码技术,其原理是通过字节码技术为一个类创建子类,并在子类中采用方法拦截的技术拦截所有父类方法的调用,顺势织入横切逻辑。
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
/**
* @Description: cglib 动态代理 代理类
* @Author: Ling.D.S
* @Date: Created in 2018/11/14 18:36
*/
public class CglibProxy implements MethodInterceptor {
private Object target;//业务类对象,供代理方法中进行真正的业务方法调用
//相当于JDK动态代理中的绑定
public Object getInstance(Object target) {
this.target = target; //给业务对象赋值
Enhancer enhancer = new Enhancer(); //创建加强器,用来创建动态代理类
enhancer.setSuperclass(this.target.getClass()); //为加强器指定要代理的业务类(即:为下面生成的代理类指定父类)
//设置回调:对于代理类上所有方法的调用,都会调用CallBack,而Callback则需要实现intercept()方法进行拦
enhancer.setCallback(this);
// 创建动态代理类对象并返回
return enhancer.create();
}
// 实现回调方法
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println("我会找房源");
proxy.invokeSuper(obj, args); //调用业务类(父类中)的方法
return null;
}
/**
* @Description: cglib 动态代理类的单元测试
* @Date: 2020/5/12 18:22
* @Author: fuguowen
* @Return
* @Throws
*/
public static void main(String[] args) {
/** 创建被代理类 */
RealSubject realSubject = new RealSubject();
CglibProxy cglibProxy = new CglibProxy();
RealSubject realSubjectProxy =
(RealSubject) cglibProxy.getInstance(realSubject);
realSubjectProxy.buyHouse();
}
参考: