设计模式-代理模式(静态代理、jdk动态代理以及cglib动态代理)(java代码案例)以及在JDK类库中的应用

本文介绍了代理模式的定义、分类和类图,详细讲解了静态代理、JDK动态代理及CGLIB动态代理的工作原理、优缺点。在静态代理中,代理类需手动实现接口并扩展功能;JDK动态代理则允许在运行时创建代理对象,但要求被代理对象实现接口;CGLIB动态代理则无需接口,但不能用于final或static方法。最后讨论了代理模式在Java RMI中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

定义:

代理模式是指给某一个对象提供一个代理对象,并有代理对象来控制对原对象的引用。

分类:

①静态代理;

②动态代理(jdk动态代理,cglib动态代理);

类图:

静态代理

静态代理就是在代理类中写死原对象的方法,并添加一些功能。

DaoInterface:

package com.headfirst.proxymode.interfaces;

public interface DaoInterface {
	public void add();
	public void delete();
	public void update();
	public String query();
}

UserDao:

package com.headfirst.proxymode.dao;

import com.headfirst.proxymode.interfaces.DaoInterface;

public class UserDao implements DaoInterface {

	public void add() {
		System.out.println("add...");
	}

	public void delete() {
		System.out.println("delete...");
	}

	public void update() {
		System.out.println("update...");
	}

	public String query() {
		System.out.println("query...");
		return null;
	}

}

UserDaoProxy:

package com.headfirst.proxymode.dao;

public class UserDaoProxy extends UserDao {
	
    /**
     * 将userdao交给代理类代其完成一系列的动作,并可以自己完成一些事情
	 */
	
	UserDao dao = null;
	
	public UserDaoProxy(){
		if(dao == null){
			dao = new UserDao();
		}
	}
	
	public void add() {
		dao.add();
		System.out.println("add...log");
	}

	public void delete() {
		dao.delete();
		System.out.println("delete...log");
	}

	public void update() {
		dao.update();
		System.out.println("update...log");
	}

	public String query() {
		dao.query();
		System.out.println("query...log");
		return null;
	}
	
}

执行方法:

public static void main(String[] args) {
	UserDao userDao = new UserDaoProxy();
	userDao.add();
}

案例:

package com.headfirst.proxymode.interfaces;

public interface GiveGifts {

	public void giveFlowers();
	public void givePhone();
	public void giveCar();
	
}
package com.headfirst.proxymode.dao;

import com.headfirst.proxymode.interfaces.GiveGifts;

public class Pursit implements GiveGifts {

	public void giveFlowers() {
		System.out.println("送花");
	}

	public void givePhone() {
		System.out.println("送手机");
	}

	public void giveCar() {
		System.out.println("送车");
	}

}
package com.headfirst.proxymode.dao;

import com.headfirst.proxymode.interfaces.GiveGifts;

public class PursitProxy implements GiveGifts {

	Pursit pursit = null;
	
	public PursitProxy(){
		if(pursit == null){
			pursit = new Pursit();
		}
	}
	
	public void giveFlowers() {
		pursit.giveFlowers();
		System.out.println("送花end");
	}

	public void givePhone() {
		pursit.givePhone();
		System.out.println("送手机end");
	}

	public void giveCar() {
		pursit.giveCar();
		System.out.println("送车end");
	}

}
	public static void main(String[] args) {
		GiveGifts obj = new PursitProxy();
		obj.giveFlowers();
		obj.givePhone();
		obj.giveCar();
	}

优点

可以在不修改原对象功能的前提下,对原对象进行扩展。

缺点

当接口需要增加方法时,要同时修改接口、被代理类和代理类。

 

 

动态代理

jdk动态代理

1.代理类无需实现接口

2.jdk动态代理通过反射技术获取到类加载器和接口,通过Proxy的newProxyInstance方法获取原对象的实例。

接口

package com.headfirst.proxymode.interfaces;

public interface GiveGifts {

	public void giveFlowers();
	public void givePhone();
	public void giveCar();
	
}

被代理人

package com.headfirst.proxymode.dao;

import com.headfirst.proxymode.interfaces.GiveGifts;

public class Pursit implements GiveGifts {

	public void giveFlowers() {
		System.out.println("送花");
	}

	public void givePhone() {
		System.out.println("送手机");
	}

	public void giveCar() {
		System.out.println("送车");
	}

}

JDK代理类

package com.headfirst.proxymode.dao;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

import com.headfirst.proxymode.interfaces.GiveGifts;

public class JDKProxy {
	
	Pursit pursit = null;
	
	public Object getInstance(){
		if(pursit == null){
			pursit = new Pursit();
		}
		Class<? extends Pursit> cc = pursit.getClass();
		return Proxy.newProxyInstance(cc.getClassLoader(), cc.getInterfaces(), new InvocationHandler() {
			
			public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
				Object invoke = method.invoke(pursit, args);
				return invoke;
			}
		});
	}
	
}

测试类

	public static void main(String[] args) {
		GiveGifts obj = (GiveGifts) new JDKProxy().getInstance();
		obj.giveFlowers();
		obj.giveCar();
		obj.givePhone();
	}

优点

1.代理对象不需要实现接口,但是被代理对象必须实现接口。

2.当接口需要增加方法时,只需要在接口和被代理类中增加方法,而不需要在代理类中增加。

 

 

CGLIB动态代理

首先导入CGLIB-3.2.5的jar包

被代理类

public class Pursit2 {

	public void giveFlowers() {
		System.out.println("cglib-----送花");
	}

	public void givePhone() {
		System.out.println("cglib-----送手机");
	}

	public void giveCar() {
		System.out.println("cglib-----送车");
	}

}

代理类

package com.headfirst.proxymode.dao;

import java.lang.reflect.Method;

import com.headfirst.proxymode.interfaces.GiveGifts;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

/**
 *	1.实现MethodInterceptor接口
 */
public class cglibProxy implements MethodInterceptor{

	Pursit2 pursit2 = null;
	
	public Object getInstance(){
		if(pursit2 == null){
			pursit2 = new Pursit2();
		}
		//动态创建给定类型的子类对象
		Enhancer enhancer = new Enhancer();
		//将子类对象注入到父类中
		enhancer.setSuperclass(Pursit2.class);
		//设置回调函数
		enhancer.setCallback(this);
		//创建子类
		return enhancer.create();
	}
	
	
	/* 
	 *  JDK的动态代理是通过接口来强制转换的生成以后的代理对象是可以强制转化为我们的接口
	 *
	 *  CGLib的动态代理是通过生成一个被代理对象的子类,然后重写了父类的方法生成的对象,
	 *  可以强制为被代理的对象(也就是用户自己写的类)子类引用赋值给父类
	 *
	 *  此处的 Object o对象是CGLib帮我们new出来子类的对象Java OOP,在new子类的同时,
	 *  实际上默认先调用了我们super()的方法new了父类的同时,必须先new出来父类,这也就是
	 *  间接持有了我们父类的引用我们改变了子类对象的某些属性,是可以间接的操作父类的属性的
	 */
	public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
		proxy.invokeSuper(obj, args);
		return obj;
	}

}
	public static void main(String[] args) {
		Pursit2 obj = (Pursit2) new cglibProxy().getInstance();
		obj.giveCar();
		obj.giveFlowers();
		obj.givePhone();
	}

优点

被代理类不需要实现接口。

缺点

不能用final或者static来修饰,否则无法使用cglib动态代理。

 

三种代理模式的优点以及缺点

JDK类库中的代理模式

java RMI:java remote method invoke,远程方法调用,在这里面Stub对象是代理对象,Stub是由客户端需要调用的远程对象实现了Remote接口而来的一个代理对象,客户端实际上调用的是Stub对象,而不是远程对象。

如何实现java rmi请参考:https://blog.youkuaiyun.com/lmy86263/article/details/72594760

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值