Java中的反射与代理

反射与代理模式

(所有源代码已经上传到码云上: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");
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值