设计模式之代理模式(Java实现)

本文深入解析Java中的代理模式,包括静态代理与动态代理的概念、实现方式及应用场景。通过代码示例,详细阐述了如何利用JDK自带的动态代理和cglib实现动态代理,帮助读者理解并掌握代理模式在实际开发中的运用。

代理模式是一种很常见的设计模式,所谓代理,就是指拥有与目标对象的相同的职责的对象,代理对象在实际中代替目标对象与客户端交互。代理对象除了执行目标对象的方法之外,可以额外执行自己的相关逻辑。

代理模式是在不修改目标对象的基础上,进行的扩展,遵循设计原则的开闭原则,也就是对修改关闭,对扩展开放。

Java中代理模式分为静态代理和动态代理,而动态代理的实现又可以分为利用jdk动态代理和cglib来实现。

代理模式设计中,涉及到代理对象,目标对象,为了让代理对象拥有目标对象的职责,可以抽象出一个接口,目标对象和代理对象都实现这个接口,只不过,代理对象中保留一个目标对象的实例,代理对象的接口实现中,实际是调用的目标对象的方法。这就是静态代理的实现方式,通过代码表现出来就是:

HelloService.java

package com.xxx.proxy.statics;

public interface HelloService {
	String hello(String name);
}

HelloServiceImpl.java

package com.xxx.proxy.statics;

public class HelloServiceImpl implements HelloService{
	public String hello(String name){
		return "hello,"+name;
	}
}

HelloServiceProxy.java

package com.xxx.proxy.statics;

public class HelloServiceProxy implements HelloService{
	
	private HelloService target;
	
	public HelloServiceProxy(HelloService target){
		this.target = target;
	}
	
	public String hello(String name){
		return target.hello(name);
	}
}

Client.java

package com.xxx.proxy.statics;

public class Client {
	public static void main(String[] args) {
		HelloService service = new HelloServiceProxy(new HelloServiceImpl());
		String greet = service.hello("world");
		System.out.println(greet);
	}
}

运行程序,结果如下:

hello,world

以上通过程序实现了静态代理。这里如果目标对象有了goodbye()方法,那么代理对象如果想要这个goodbye职责,那么他也必须实现goodbye()方法,如果目标对象方法越来越多,代理对象需要代替目标对象行使相关职责,那么代理对象也需要实现相关的接口,为了解决静态代理的这个缺陷,就产生了动态代理。

动态代理不需要代理对象实现目标对象抽象出来的所有方法,简化了代理对象。

动态代理的实现方式有jdk自带的代理方式和spring-aop提供的cglib方式。

jdk自带的代理方式,是通过反射来实现的,代理对象需要实现一个InvocationHandler接口。 实现了InvocationHandler接口的类,只能算是一个在反射中使用handler,要真正创建一个代理对象,还需要通过反射Proxy.newInstance(ClassLoader classLoader,Class<?> interfaces,InvocationHandler handler);这个方法带有三个参数,分别是classLoader,目标对象类加载器

,interfaces,目标对象接口集合,handler,反射调用处理手柄对象。 jdk自带的代理方式实现代理代码如下:

HelloService.java

package com.xxx.proxy.jdk;

public interface HelloService {
	String hello(String name);
	String goodbye(String name);
}

HelloServiceImpl.java

package com.xxx.proxy.jdk;

public class HelloServiceImpl implements HelloService {

	@Override
	public String hello(String name) {
		return "hello,"+name;
	}

	@Override
	public String goodbye(String name) {
		return "goodbye,"+name;
	}

}

HelloServiceProxy.java

package com.xxx.proxy.jdk;

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

public class HelloServiceProxy implements InvocationHandler {
	
	private HelloService target;
	
	public HelloServiceProxy(HelloService target) {
		this.target = target;
	}

	@Override
	public Object invoke(Object proxy, Method method, Object[] args)
			throws Throwable {
		System.out.println("method="+method.getName());
		Object result = method.invoke(target, args);
		System.out.println("result="+result);
		return result;
	}

	public Object getInstance(){
		ClassLoader loader = target.getClass().getClassLoader();
		Class<?>[] interfaces = target.getClass().getInterfaces();
		return Proxy.newProxyInstance(loader, interfaces, this);
	}
}

JDKProxyMain.java

package com.xxx.proxy.jdk;
public class JDKProxyMain {

	public static void main(String[] args) {
		HelloService service = new HelloServiceImpl();
		HelloService proxy = (HelloService) new HelloServiceProxy(service).getInstance();
		proxy.hello("world");
		proxy.goodbye("world");
	}

}

运行JDKProxyMain类的主方法,打印信息如下:

method=hello
result=hello,world
method=goodbye
result=goodbye,world

使用jdk自带代理实现的代理,我们并没有实现目标类HelloServiceImpl对应的任何接口,我们只是实现了InvocationHandler接口,并且利用反射Proxy.newInstance()来构建了一个加强对象。

下面介绍通过cglib方式来实现动态代理。cglib是spring-aop用来做切面编程,它需要定义一个实现了拦截器的类,利用该类来创建一个代理对象。具体实现代码如下:

如果是maven工程,需要引入如下依赖:

<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-context</artifactId>
  <version>4.3.4.RELEASE</version>
</dependency>

HelloService.java

package com.xxx.proxy.cglib;

public class HelloService {
	public String hello(String name){
		return "hello,"+name;
	}
	public String goodbye(String name){
		return "goodbye,"+name;
	}
}

HelloServiceProxy.java

package com.xxx.proxy.cglib;

import java.lang.reflect.Method;

import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

public class HelloServiceProxy implements MethodInterceptor {
	
	private Object target;
	
	public Object getInstance(Object target){
		this.target = target;
		Enhancer enhancer = new Enhancer();
		enhancer.setSuperclass(this.target.getClass());
		enhancer.setCallback(this);
		return enhancer.create();
	}

	@Override
	public Object intercept(Object obj, Method method, Object[] args,
			MethodProxy proxy) throws Throwable {
		Object result = null;
		System.out.println("before method="+method.getName());
		try {
			result = proxy.invokeSuper(obj, args);
		} catch (Exception e) {
			throw e;
		}finally{
			System.out.println("after result="+result);
		}
		return result;
	}

}

CGLibProxyMain.java

package com.xxx.proxy.cglib;

public class CGLibProxyMain {

	public static void main(String[] args) {
		HelloService target = new HelloService();
		HelloServiceProxy proxy = new HelloServiceProxy();
		HelloService service = (HelloService) proxy.getInstance(target);
		service.hello("world");
		service.goodbye("world");
	}

}

运行CGLibProxyMain类的主方法,打印结果如下:

before method=hello
after result=hello,world
before method=goodbye
after result=goodbye,world

 cglib动态代理也是不需要实现目标类的接口。要使用cglib方式实现动态代理,需要加入spring-aop依赖,可以直接加入spring-context依赖即可。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

luffy5459

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

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

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

打赏作者

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

抵扣说明:

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

余额充值