Java 代理模式

3 篇文章 0 订阅

代理模式分为静态代理和动态代理

静态代理

介绍

类似于生活中的中介代理房东租房、婚介代理要结婚的情侣布置婚礼现场等等。

实现

拿房东租房为例

Rent接口

package com.curtian.study.static_proxy.demo1;

public interface Rent {

    void rent();
}

Rent接口的第一个实现类,房东

package com.curtian.study.static_proxy.demo1;

/**
 * 房东
 */
public class Host implements Rent{

    @Override
    public void rent() {
        System.out.println("房东租房子");
    }
}

Rent接口的第二个实现类,中介

package com.curtian.study.static_proxy.demo1;

public class Proxy implements Rent{

    private Host host;

    @Override
    public void rent() {
        seeHouse();
        host.rent();
        hetong();
        rate();
    }

    public Proxy(Host host) {
        this.host = host;
    }

    private void seeHouse(){
        System.out.println("中介带看房子");
    }

    private void hetong(){
        System.out.println("签署租赁合同");
    }

    private void rate(){
        System.out.println("收取中介费");
    }

}

从代码中我们也可以发现,中介只是在被代理的类的方法上加了一些额外的方法(seeHouse、hetong、rate)

静态代理总结

接口(Rent租房接口)真实角色(Host房东)代理角色(Proxy房屋中介)组成。

好处

是可以是使真实角色操作更加存粹(房东只管租房一件事情),很明显的体现了面向对象七大原则的单一职责原则。公共业务就交给代理角色。

缺点

一个真实角色就对应一个代理角色,比如房东对应房屋中介、要结婚的情侣对应婚介所

动态代理

介绍

拥有静态代理的所有优点以及可以动态生成代理类。

分类

动态代理分为三大类:

  • 基于接口的:jdk动态代理
  • 基于类的:cglib
  • java字节码实现的:javasist

JDK动态代理

(目前博主只了解了jdk动态代理)

JDK动态代理核心

Proxy类InvocationHandler接口
Proxy用于生成代理类,实现InvocationHandler接口可以通过反射获取被代理的类的方法, 然后在此基础上添加一些附属操作

举例

给所有类的方法加一些日志。

UserService接口
package com.curtian.study.static_proxy.demo2;

public interface Userservice {

    void add();

    void delete();
}
UserServiceImpl类
package com.curtian.study.static_proxy.demo2;

import org.springframework.stereotype.Service;

@Service
public class UserServiceImpl implements Userservice{
    @Override
    public void add() {
        System.out.println("加法");
    }

    @Override
    public void delete() {
        System.out.println("减法");
    }
}

ProxyInvocationHandler(核心)
package com.curtian.study.dynamic_proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class ProxyInvocationHandler implements InvocationHandler {

    //被代理的对象
    private Object target;

    public void setTarget(Object target){
        this.target = target;
    }

    /**
     * 生成代理类
     * @return
     */
    public Object getProxy(){
        return Proxy.newProxyInstance(this.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
    }

    /**
     * 当代理类执行方法的时候,会回调到这个方法,附属操作也是在这里加的
     * @param proxy
     * @param method
     * @param args
     * @return
     * @throws Throwable
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println(proxy.getClass().getName());
        log("调用了" + method.getName() + "方法");
        return method.invoke(target, args);
    }

    private void log(String msg){
        System.out.println(msg);
    }
}
Test(测试)
/**
 * 动态代理
 * 介绍:动态代理和静态代理角色一样
 * 动态代理的代理类是动态生成的,不是我们直接写好的!
 * 动态代理分为两大类:基于接口的动态代理,基于类的动态代理。
 *      1.基于接口--Jdk动态代理【本次示例】
 *      2.基于类:cglib
 *      3.java字节码实现: javasist
 * 示例中的两个核心类/接口,Proxy类、invocationHandler接口
 *
 * */
public class Main {
    public static void main(String[] args) {
        UserServiceImpl userService = new UserServiceImpl();
        ProxyInvocationHandler proxyInvocationHandler = new ProxyInvocationHandler();
        proxyInvocationHandler.setTarget(userService);
        Userservice proxy = (Userservice) proxyInvocationHandler.getProxy();
        proxy.add();
        proxy.delete();
    }
}

运行情况:
在这里插入图片描述

Java代理模式是一种结构型设计模式,其目的是为其他对象提供一种代理以控制对这个对象的访问。代理对象可以在客户端和目标对象之间充当中介,以便于客户端访问目标对象时,可以在不改变目标对象的情况下添加一些额外的功能,比如安全性、远程访问、缓存等。 在Java中,代理模式可以通过两种方式实现:静态代理和动态代理。静态代理需要手动编写代理类,而动态代理可以在运行时通过反射机制动态生成代理类,更加灵活。 举个例子,假设我们有一个接口`Subject`,其中定义了一些方法。我们希望在调用这些方法时,增加一些额外的日志记录功能。我们可以编写一个代理类`SubjectProxy`,在代理类中实现接口方法并调用目标对象的方法,同时在方法前后添加日志记录的代码。客户端则通过代理类访问目标对象。 静态代理示例代码如下: ```java public interface Subject { void doSomething(); } public class RealSubject implements Subject { @Override public void doSomething() { System.out.println("RealSubject do something."); } } public class SubjectProxy implements Subject { private Subject realSubject; public SubjectProxy(Subject realSubject) { this.realSubject = realSubject; } @Override public void doSomething() { System.out.println("Before do something."); realSubject.doSomething(); System.out.println("After do something."); } } public class Client { public static void main(String[] args) { Subject realSubject = new RealSubject(); Subject subjectProxy = new SubjectProxy(realSubject); subjectProxy.doSomething(); } } ``` 动态代理示例代码如下: ```java public class SubjectHandler implements InvocationHandler { private Object target; public SubjectHandler(Object target) { this.target = target; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("Before " + method.getName()); Object result = method.invoke(target, args); System.out.println("After " + method.getName()); return result; } } public class Client { public static void main(String[] args) { Subject realSubject = new RealSubject(); InvocationHandler handler = new SubjectHandler(realSubject); Subject subjectProxy = (Subject) Proxy.newProxyInstance(realSubject.getClass().getClassLoader(), realSubject.getClass().getInterfaces(), handler); subjectProxy.doSomething(); } } ``` 无论是静态代理还是动态代理,代理模式都可以在不改变目标对象的情况下,为其添加额外的功能,提高代码的可复用性和灵活性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值