反射与代理模式
(所有源代码已经上传到码云上:https://gitee.com/c3h2/knowledge-study.git 该章节所属reflect包中,具体代码开编号,每个类都有编号)
静态代理
代理设计模式在开发中很常用,掌握代理模式对于Java开发人员来说至关重要。代理模式的核心在于,一个业务有两个类负责,一个类负责业务的真实业务,另外一个负责代理操作,类似于厨房的厨师和切菜的。现在我们先来看一下静态代理模式。
现在我们就来实现一下静态代理(源码reflect.cn.tansanqinger.agency.StaticState.java):
package cn.tansanqinger.agency;
interface IMessage{
void send();
}
class MessageImpl implements IMessage{
@Override
public void send(){
System.out.println("发送消息:www.tansanqinger.cn");
}
}
class MessageImplProxy implements IMessage{
MessageImpl message;//正常业务实现
public MessageImplProxy(MessageImpl message) {
this.message = message;
}
@Override
public void send() {
if(this.connect()){
message.send();
this.close();
}
}
public boolean connect(){
System.out.println("发送消息通道打开……");
return true;
}
public void close(){
System.out.println("关闭消息发送通道……");
}
}
class Factory{//使用工厂设计模式
private Factory(){}//构造方法私有化
public static IMessage getInstance(){
return new MessageImplProxy(new MessageImpl());
}
}
public class StaticState {
public static void main(String[] args) {
IMessage iMessage = Factory.getInstance();
iMessage.send();
}
}
运行结果为:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iAoKaX0J-1600695235585)(C:\Users\C3H2\AppData\Roaming\Typora\typora-user-images\image-20200921201351663.png)]
但是这个时候就需要考虑一个问题了,那就是如果还有很多个这样的业务,但是他们的功能类似,那么就需要编写很多的代理类,在这种情况下,静态代理模式就不能满足需求了,就需要使用更好的方法来取代。
动态代理模式
针对上述出现的问题,我们就需要使用动态代理模式来解决,所谓的动态代理,实际上就是将所有的代理类进行抽取,然后编写成一个公共的。
动态代理类是在JDK1.3的时候就添加到了Java之中,如果你想要实现动态代理,你就需要Invocation
接口和Proxy
类的支持,java.lang.reflect.InvocationHandle
接口的定义为:
public interface InvocationHandler {
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable;
}
同时在java.lang.reflect.Proxy类中提供了一个方法:
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
这种代理对象的创建是依据真实主题类的对象的加载器,和其实现的父接口动态创建的一个新的子类,该子类由JVM在运行的时候自行负责创建。
实现动态代理(源码reflect.cn.tansanqinger.agency.DynamicProxy.java):
package cn.tansanqinger.agency;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
interface IMessageService{
void send();
}
class MessageServiceImpl implements IMessageService{
@Override
public void send(){
System.out.println("发送消息:www.tansanqinger.cn");
}
}
class MessageServiceImplProxy implements InvocationHandler {
Object object;//正常业务实现
public Object bind(Object object) {
this.object = object;
return Proxy.newProxyInstance(object.getClass().getClassLoader(), object.getClass().getInterfaces(), this);
}
public boolean connect(){
System.out.println("发送消息通道打开……");
return true;
}
public void close(){
System.out.println("关闭消息发送通道……");
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object returnValue = null;
if(this.connect()){
returnValue = method.invoke(this.object, args);
this.close();
}
return returnValue;
}
}
class DynamicProxyFactory{//使用工厂设计模式
private DynamicProxyFactory(){}//构造方法私有化
public static IMessageService getInstance(){
return (IMessageService)new MessageServiceImplProxy().bind(new MessageServiceImpl());
}
}
public class DynamicProxy {
public static void main(String[] args) {
IMessageService service = DynamicProxyFactory.getInstance();
service.send();
}
}
运行结果:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-s4CqrHpK-1600695235594)(C:\Users\C3H2\AppData\Roaming\Typora\typora-user-images\image-20200921203313883.png)]
此时的代码利用动态代理设计类动态的构建了接口的实现子类,并且利用InvocationHandler.invoke()
实现标准的代码执行调用,在里面进行代理控制。
CGLIB实现动态代理
上述的动态代理是使用的较多的一种方式,是对接口来进行标准定义的,因此部分开发者就认为不好,于是提出了基于类的的动态代理。CGLIB是属于第三方的插件,在使用的时候需要经CGLIB引入到程序之中。
相关代码(源码reflect.cn.tansanqinger.agency.CGLIBDemo.java):
package cn.tansanqinger.agency;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
class Message{
public void send(String str){
System.out.println("消息发送:"+str);
}
}
class MessageProxy implements MethodInterceptor {
Object object;
public MessageProxy(Object object) {
this.object = object;
}
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
Object returnObject = null;
if(this.connect()){
returnObject = method.invoke(this.object,args);
this.close();
}
return returnObject;
}
public boolean connect(){
System.out.println("发送消息通道打开……");
return true;
}
public void close(){
System.out.println("关闭消息发送通道……");
}
}
public class CGLIBDemo {
public static void main(String[] args) {
Message realObject = new Message();//真实业务主题对象
Enhancer enhancer = new Enhancer();//负责代理控制的类
enhancer.setSuperclass(realObject.getClass());//模拟一个操作的父类
enhancer.setCallback(new MessageProxy(realObject));//设置代理对象
Message proxyObject = (Message) enhancer.create();//创建代理对象,类似于Proxy
proxyObject.send("www.tansanqinger.cn");
}
}