代理模式是一种很常见的设计模式,所谓代理,就是指拥有与目标对象的相同的职责的对象,代理对象在实际中代替目标对象与客户端交互。代理对象除了执行目标对象的方法之外,可以额外执行自己的相关逻辑。
代理模式是在不修改目标对象的基础上,进行的扩展,遵循设计原则的开闭原则,也就是对修改关闭,对扩展开放。
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依赖即可。
本文深入解析Java中的代理模式,包括静态代理与动态代理的概念、实现方式及应用场景。通过代码示例,详细阐述了如何利用JDK自带的动态代理和cglib实现动态代理,帮助读者理解并掌握代理模式在实际开发中的运用。
2144

被折叠的 条评论
为什么被折叠?



