【日更】 代理

概括

代理是一种设计模式,提供了对目标对象另外的访问方式;即通过代理对象访问目标对象。这样的好处是可以在目标对象实现的基础上,增强额外的功能操作,即扩展目标对象功能 – 开闭原则

在这里插入图片描述

Java中的代理模式

给目标对象提供一个代理对象,并由代理对象控制对目标对象的引用

目的:

  1. 通过代理对象间接访问目标对象,防止直接访问目标对象给系统带来复杂性
  2. 通过代理业务对原有业务进行增强操作
创建代理对象的方式
静态代理

实现目标对象接口或者直接继承目标类,完成逻辑的修改 — 通常使用实现接口方式

在这里插入图片描述
我们在实现接口的时候,目标类和代理类都必须实现目标接口当中所实现的方法,从某种意义上代理类可以帮助我们实现目标类中的方法,并且代理类还可以有自己的扩展
在这里插入图片描述

package com.proxy;

public class StacticProxy {
    public static void main(String[] args) {
        new Driver(new You()).driveCar();
    }
}
interface Drive{
    void driveCar();
}

//真实角色,谁去开车
class You implements Drive{
    @Override
    public void driveCar() {
        System.out.println("简简单单开个车");
    }
}

//代理角色,帮助你洗车和加油  真实对象只负责开车
class Driver implements Drive{

    //代理谁-->真实目标对象
    private Drive drive;

    public Driver (Drive drive) {
        this.drive= drive;
    }

    @Override
    public void driveCar() {
        washCar();
        this.drive.driveCar();//真实对象
        fuelTheCar();
    }

    private void washCar() {
        System.out.println("洗个车");
    }

    private void fuelTheCar() {
        System.out.println("加个油");
    }
}

总结

  1. 真实对象和代理对象要实现同一个接口
  2. 代理对象要代理真实角色

好处:

  1. 代理对象可以做很多真实对象做不了的事情
  2. 真实对象专注做自己的事情
基于JDK接口的动态代理

JDK代理,实际上是对Java接口的处理,而且只能是对接口进行代理,达到效果是,当调用指定接口的指定方法时,会执行特定操作。如:HelloService是一个接口,public String sayHello(String msg)是该接口的一个方法,当代码调用该接口的sayHello方法时,会执行规定好的动作。
这里HelloService接口的实现类是由代理动态生成的实现类。所以想为一个接口生成代理,需要先生成一个代理对象。
生成代理对象,需要 代理的接口 以及 java.lang.reflect.InvocationHandler的实现类

  1. 定义接口
public interface HelloService{
	String sayHello(String msg);
}
  1. 创建代理类
public class DefaultInvocation implements InvocationHandler {
	public Object invoke(Object proxy,Method,Object[] args) throws Throwable{
		System.out.println("被代理的接口方法:" + method);
		System.out.println("被代理的接口方法的入参:" + args);
		Class<?> clazz = method.getDeclaringClass();
		if("com.sunsc.service.HelloService".equals(clazz.getName())&&"sayHello".equals(method.getName()){
			return " hello , receive " + args[0];
		}
		return null;
	}
}
  1. 生成接口的代理对象
    生成代理对象,通过调用Proxy.newProxyInstance(ClassLoader loader,class<?>[] interfaces,InvocationHandler h) 方法即可

ClassLoader 要加载代理对象类的类加载器
Class<?> 要被代理的接口集
InvocationHandler h - InvocationHandler的实现类,调用代理对象的方式时,实际上都是执行了该实现类的invoke方法

public static HelloService getHelloService() {
	// InvocationHandler的实现类
	InvocationHandler invocationHandler = new DefaultInvocation();
	// 要加载代理对象类的类加载器
	ClassLoader classLoader = HelloService.class.getClassLoader();
	// 要被代理的接口
	Class<?>[] interfaces = new Class<?>[] { HelloService.class };
	// 生成HelloService接口的代理对象
	HelloService helloService = (HelloService) Proxy.newProxyInstance(
        classLoader, interfaces, invocationHandler);
	return helloService;
}
  1. 通过代理对象调用接口
public static void main(String[] args) {
	HelloService helloService = getHelloService();
	String result = helloService.sayHello("hello, test");
	System.out.println("result: " + result);
}

public static HelloService getHelloService() {
	// InvocationHandler的实现类
	InvocationHandler invocationHandler = new DefaultInvocation();
	// 要加载代理对象类的类加载器
	ClassLoader classLoader = HelloService.class.getClassLoader();
	// 要被代理的接口
	Class<?>[] interfaces = new Class<?>[] { HelloService.class };
	// 生成HelloService接口的代理对象
	HelloService helloService = (HelloService) Proxy.newProxyInstance(classLoader, interfaces, invocationHandler);
	return helloService;
}
基于CGLIB父类的动态代理

当我们需要给没有实现接口的目标类生成代理对象时,jdk的动态代理就完成不了这样的事情了,这时我们就可以继承目标类,以目标类的子类方式实现,这样的方法叫做cglib的动态代理,也可以叫做子类代理,它是在内存中构建一个子类对象从而对目标对象进行功能的增强

// 目标对象
public class HelloService {
	public void sayHello(){
		System.out.println("hello");
	}
}

// 基于cglib实现的动态代理
public class CglibProxyHelloFactory implements MethodInterceptor {
	// 目标对象
	private Object target;
	public CglibProxyHelloFactory(Object target){
		this.target = target;
	}
	
	@Override
	public Object intercept(Object arg0,Method method,Object[] objects,MethodProxy arg3) throws Throwable{
		System.out.println("cglib 代理前逻辑");
		// 目标对象的目标方法
		method.invoke(target,objects);
		System.out.println("cglib 代理后逻辑");
		return null;
	}
}

// 测试类

public class MainTest {
    public static void main(String[] args) {
        new CglibProxyFactory(new HelloService ()).sayHello();
    }
}	
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

new_repo

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值