java中的代理模式

本文详细介绍了代理模式的概念,以及静态代理、JDK动态代理和CGlib动态代理的实现方式、特点和应用场景,强调了功能增强和控制访问的重要性。
摘要由CSDN通过智能技术生成

一、什么是代理模式

定义: 给目标对象提供一个代理对象,并且由代理对象控制对目标对象的引用。
目的:

①:功能增强:通过代理业务对原有业务进行增强
②:控制访问:通过代理对象的方式间接的访问目标对象,防止直接访问目标对象给系统带来不必要的复杂性

二、相关概念

目标类:原对象,我们需要代理对象控制他的访问,拓展其功能。
代理类:代理模式产生的对象,是原对象“替身”,已经在原有基础上修改逻辑

在这里插入图片描述

三、实现代理的三种方式

(1).静态代理

1.静态代理的特点

①:代理类是自己手动实现的,需要自己去创建一个类
②:代理类所代理的目标类是固定的

2.利用接口实现静态代理

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

3.代码实现

首先先定义接口

public interface ByClothes {
	void clothes(String size);
}

定义目标对象

public class ClothesFactory implements ByClothes {
	@Override
	public void clothes(String size) {
		System.out.println("已经为您制作好了一整套size为"+size+"的衣服。。。。。。。。");
	}
}

制造代理对象

public class proxy implements ByClothes {

	
	//被包含的真是对象
	public ClothesFactory factory = new ClotheFactory;
	// 对功能的增强
	@Override
	public void clothes(String size) {
		FrontService();
		factory.clothes(size);
		endService();
	}
	
	//前置服务
	public void FrontService() {
		System.out.println("根据您的需求进行市场调研");
	}

	//前置服务
	public void endService() {
		System.out.println("为您提供一条龙的包办服务");
	}
}

制造测试类------买衣服的人

public class Test {
	public static void main(String[] args) {
		Proxy proxy = new Proxy();
		proxy.clothes("xxL");
	}
}

4.静态代理存在的问题

①:当目标类曾多时,代理类也需要增多,导致代理类的关系不便。
②:当接口当中的功能增多或者修改,都会影响实体类,违反开闭原则(程序对访问开放,对修改关闭)

(2).JDK动态代理

1.静态代理和动态代理的区别

静态代理需要我们手动的去创建代理对象,动态代理则是采用jdk提供的方法创建代理对象

2.JDK动态代理的实现

使用java反射包当中的类和接口实现动态代理的功能

3.JDK动态代理逻辑图

在这里插入图片描述

4.jdk动态代理

新建接口

public interface ByShoot {
	void byShoot(String size);
}

新建工厂

public class ShootFactory implements ByShoot{

	@Override
	public void byShoot(String size) {
		System.out.println("已经为您生产出了尺码为"+size+"的鞋子");
	}

}

代理类

public class LisiFactory implements InvocationHandler {

	// 被代理的对象
	private Object factory ;
   public DyProxy(Object factory) {
		 this.factory = factory;
	} 
    
    
    //三个参数的讲解
    //1.Object:jdk创建的代理类,无需赋值
    //2.Method:目标类当中的方法,jdk提供,无需赋值
    //3.Object[]:目标类当中的方法的参数,jdk提供,无需赋值
	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		FrontService();
		method.invoke(factory, args);  //这里的invoke(目标对象,方法参数)
		endService();
		return null;
	}

	// 前置服务
	public void FrontService() {
		System.out.println("根据您的需求进行市场调研");
	}

	// 后置服务
	public void endService() {
		System.out.println("为您提供一条龙的包办服务");
	}
 
 	//该方法并不是固定的,但是内部的Proxy类的创建是核心
	public Object getProxyInstance() {
		// TODO Auto-generated method stub
		return Proxy.newProxyInstance(factory.getClass().getClassLoader(), factory.getClass().getInterfaces(), this);
	}
}

新建测试类

public class Test {
	public static void main(String[] args) {
		ClothesFactory clothesFactory = new ClothesFactory();
    	ByClothes clothes = (ByClothes) new 动态代理类(clothesFactory).hhh(); // 1.代理谁  //2.接口是什么
    	clothes.clothes("XXXL");
    	ShootFactory shootFactory = new ShootFactory();
    	ByShoot shoot = (ByShoot) new 动态代理类(shootFactory).hhh();
    	shoot.shoot("1000");
	}
}

5.JDK代理类实现细节

①:InvocationHandler接口:里边只有一个invoke()方法
invoke()方法:表示我们要求代理对象要完成的功能
1).调用并执行目标的方法
2).功能增强,在目标对象调用时增强其功能
②:Proxy类:核心对象,其目的是创建道理对象
以前我们创建对象是new构造器,现在我们使用Proxy类的方法,代理new的使用
newProxyInstance()方法的作用是创建代理对象,其返回值就是代理对象

//ClassLoader loader:类的加载器,复杂向内存当中加载对象,使用反射的方式获取
// Class<?>[] interfaces:目标对象实现的接口,也是反射获取
//InvocationHandler h:代理类需要完成的功能
public static Object newProxyInstance(ClassLoader loader,
                                      Class<?>[] interfaces,
                                      InvocationHandler h)

(3).cglib动态代理

1.jdk动态代理的问题

使用jdk动态代理存在一个问题,jdk提供的动态代理只能为拥有接口的类进行动态代理,但是对于没有实现接口的类,则没有办法进行动态代理。

2.什么是cglib动态代理

cglib是是第三方的工具库。其原理是继承,cglib通过继承目标类,创建他的子类,在子类当中重写父类的相关方法,实现功能的增强。

3.cglib基本结构

下图所示,代理类去继承目标类,每次调用代理类的方法都会被方法拦截器拦截,在拦截器中才是调用目标类的该方法的逻辑。
在这里插入图片描述

4.cglib实现动态代理的原理

1.生成一个空的字节码对象
2.通过字节码对象生成目标类对象的子类 进行增强
3.实现拦截器,通过连接器实现代理的类方法
4.创建代理对象

5.代码实现

CGLib动态代理中提供了一个类Enhance,需要用它生成一个空的字节码对象,所以我们需要导入外部的jar包依赖。

<dependency>
    <groupId>cglib</groupId>
    <artifactId>cglib</artifactId>
    <version>2.2.2</version>
</dependency>

目标类

/**
 * 目标类
 */
public class ClothesFactory {
    public void clothes(String size) {
        System.out.println("已经为您制作好了一整套size为"+size+"的衣服。。。。。。。。");
    }
}

拦截器


/**
 * 实现拦截器,通过连接器实现代理的类方法
 */
public class MyMethodInterceptor implements MethodInterceptor {
    /**
     *
     * @param o   代理对象
     * @param method 目标对象中的方法
     * @param objects 目标对象中方法的参数
     * @param methodProxy 代理对象中代理方法对象
     * @return
     * @throws Throwable
     */
    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("前置增强");
        methodProxy.invokeSuper(o,objects);  // 动态的回调父类当中的方法
        System.out.println("后置增强");
        return o;
    }
}

代理类

/**
 * 代理类
 */
public class CglibProxy  {
    
    public static Object createProxy(String path) throws ClassNotFoundException {
        Enhancer enhancer = new Enhancer();  //生成空的字节码对象
        enhancer.setSuperclass(Class.forName(path)); //通过字节码对象生成目标类对象的子类 进行增强
        enhancer.setCallback(new MyMethodInterceptor()); //实现拦截器,通过连接器实现代理的类方法
        Object o = enhancer.create();//创建代理对象
        return o;
    }
}

测试

public class Test {
    public static void main(String[] args) throws ClassNotFoundException {
        //生成代理对象
        ClothesFactory proxy = (ClothesFactory) CglibProxy.createProxy("com.qcby.ClothesFactory");
        //方法调用
        proxy.clothes("xxxL");
    }
}
  • 11
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

青城小虫

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

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

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

打赏作者

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

抵扣说明:

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

余额充值