java中的代理模式

静态代理
java 复制代码
public interface SmsService {
    void sent(String message);
}
class SmsServiceImpl implements SmsService{
    @Override
    public void sent(String message) {
        System.out.println("这是发送的信息:"+message);
    }
}
class SmsServiceProxy implements SmsService{
    private final SmsService smsService;
    public SmsServiceProxy(SmsService smsService){
        this.smsService = smsService;
    }
    @Override
    public void sent(String message) {
        System.out.println("发送消息前进行增强");
        smsService.sent(message);
        System.out.println("发送消息后进行增强");
    }
}
class Main{
    public static void main(String[] args) {
        SmsServiceImpl smsService = new SmsServiceImpl();
        SmsServiceProxy proxy = new SmsServiceProxy(smsService);
        proxy.sent("哈哈哈哈");
//        发送消息前进行增强
//        这是发送的信息:哈哈哈哈
//        发送消息后进行增强
    }
}
动态代理

JDK动态代理

在 Java 动态代理机制中 InvocationHandler 接口和 Proxy 类是核心

java 复制代码
public interface SmsService {
    void sent(String message);
}
class SmsServiceImpl implements SmsService{
    @Override
    public void sent(String message) {
        System.out.println("这是发送的信息:"+message);
    }
}
public class SmsInvocationHandler implements InvocationHandler {
    private final Object target;
    public SmsInvocationHandler(Object target){
        this.target = target;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("发送消息前进行增强");
        Object result = method.invoke(target, args);
        System.out.println("发送消息后进行增强");
        return result;
    }
} 
public class JDKProxyFactory{
    public static Object getProxy(Object target){
        return Proxy.newProxyInstance(target.getClass().getClassLoader()
                ,target.getClass().getInterfaces(),new SmsInvocationHandler(target));
    }
}
public class Main {
    public static void main(String[] args) {
        SmsService smsService = (SmsService)JDKProxyFactory.getProxy(new SmsServiceImpl());
        smsService.sent("哈哈哈");
//        发送消息前进行增强
//        这是发送的信息:哈哈哈
//        发送消息后进行增强
    }
}
CJLIB动态代理

在 CGLIB 动态代理机制中 MethodInterceptor 接口和 Enhancer 类是核心。

java 复制代码
public class AliSmsService {
    public String send(String message) {
        System.out.println("send message:" + message);
        return message;
    }
}
public class DebugMethodInterceptor implements MethodInterceptor {


    /**
     * @param o           被代理的对象(需要增强的对象)
     * @param method      被拦截的方法(需要增强的方法)
     * @param args        方法入参
     * @param methodProxy 用于调用原始方法
     */
    @Override
    public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        //调用方法之前,我们可以添加自己的操作
        System.out.println("before method " + method.getName());
        Object object = methodProxy.invokeSuper(o, args);
        //调用方法之后,我们同样可以添加自己的操作
        System.out.println("after method " + method.getName());
        return object;
    }

}
public class CglibProxyFactory {

    public static Object getProxy(Class<?> clazz) {
        // 创建动态代理增强类
        Enhancer enhancer = new Enhancer();
        // 设置类加载器
        enhancer.setClassLoader(clazz.getClassLoader());
        // 设置被代理类
        enhancer.setSuperclass(clazz);
        // 设置方法拦截器
        enhancer.setCallback(new DebugMethodInterceptor());
        // 创建代理类
        return enhancer.create();
    }
}
public class Main {
    public static void main(String[] args) {
        AliSmsService aliSmsService = (AliSmsService) CglibProxyFactory.getProxy(AliSmsService.class);
        aliSmsService.send("java");
//        before method send
//        send message:java
//        after method send
    }
}
JDK 动态代理和 CGLIB 动态代理对比]
  1. JDK 动态代理只能代理实现了接口的类或者直接代理接口,而 CGLIB 可以代理未实现任何接口的类。 另外, CGLIB 动态代理是通过生成一个被代理类的子类来拦截被代理类的方法调用,因此不能代理声明为 final 类型的类和方法。
  2. 就二者的效率来说,大部分情况都是 JDK 动态代理更优秀,随着 JDK 版本的升级,这个优势更加明显。
静态代理和动态代理的对比
  1. 灵活性:动态代理更加灵活,不需要必须实现接口,可以直接代理实现类,并且可以不需要针对每个目标类都创建一个代理类。另外,静态代理中,接口一旦新增加方法,目标对象和代理对象都要进行修改,这是非常麻烦的!
  2. JVM 层面:静态代理在编译时就将接口、实现类、代理类这些都变成了一个个实际的 class 文件。而动态代理是在运行时动态生成类字节码,并加载到 JVM 中的。
相关推荐
Swift社区2 小时前
在 Swift 中实现字符串分割问题:以字典中的单词构造句子
开发语言·ios·swift
没头脑的ht2 小时前
Swift内存访问冲突
开发语言·ios·swift
没头脑的ht2 小时前
Swift闭包的本质
开发语言·ios·swift
wjs20242 小时前
Swift 数组
开发语言
吾日三省吾码3 小时前
JVM 性能调优
java
stm 学习ing3 小时前
FPGA 第十讲 避免latch的产生
c语言·开发语言·单片机·嵌入式硬件·fpga开发·fpga
湫ccc4 小时前
《Python基础》之字符串格式化输出
开发语言·python
弗拉唐4 小时前
springBoot,mp,ssm整合案例
java·spring boot·mybatis
oi775 小时前
使用itextpdf进行pdf模版填充中文文本时部分字不显示问题
java·服务器