重温java知识(三十五、反射机制之十七:反射与注解---Annotation整合工厂设计模式)

使用注解“Annotation"进行开发的最大特点是可以将相应的配置信息写入Annotation后,在项目启动时通过反射获取相应注解Annotation定义并进行操作。

1、Annotation整合工厂设计模式与代理设计模式的例子:

package com.mydemo;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class ReflectDemo {

    public static void main(String[] args) {

        // 实例化接口对象
        MessageService messageService = new MessageService();

        // 调用方法
        messageService.send("这种操作真骚,太TM好用了,就是还没理解精髓");

    }
}

// 业务接口
interface IMessage {
    // 输入业务
    public void send(String msg);
}

// 业务接口实现子类
class CloudMessageImpl implements IMessage {

    /**
     * 方法覆写
     *
     * @param msg
     */
    @Override
    public void send(String msg) {
        System.out.println("【云消息发送】" + msg);
    }
}

// 业务接口实现子类
class NetMessageImpl implements IMessage {

    /**
     * 方法覆写
     *
     * @param msg
     */
    @Override
    public void send(String msg) {
        System.out.println("【网络消息发送】" + msg);
    }
}

class Factory {
    private Factory() {
    }

    /**
     * 返回实例化对象
     *
     * @param clazz
     * @param <T>
     * @return
     */
    public static <T> T getInstance(Class<T> clazz) {

        // 利用反射获取实例化对象
        try {
            return (T) new MessageProxy().bind(clazz.getDeclaredConstructor().newInstance());
        } catch (Exception e) {
            return null;
        }
    }
}

@Target({ElementType.TYPE, ElementType.METHOD}) // 只能用在类和方法上
@Retention(RetentionPolicy.RUNTIME)
@interface UseMessage {

    // 定义要使用的类型
    public Class<?> clazz();

}

// 注解Annotation定义实用类
//@UseMessage(clazz = CloudMessageImpl.class)
@UseMessage(clazz = NetMessageImpl.class)
class MessageService {

    // 定义业务处理类
    private IMessage iMessage;

    /**
     * 无参构造方法
     */
    public MessageService() {
        UseMessage useMessage = MessageService.class.getAnnotation(UseMessage.class);
        this.iMessage = (IMessage) Factory.getInstance(useMessage.clazz());
    }

    /**
     * 发送方法
     *
     * @param msg
     */
    public void send(String msg) {
        this.iMessage.send(msg);
    }

}

// 代理类
class MessageProxy implements InvocationHandler {

    private Object target;

    /**
     * 对象绑定
     *
     * @param target
     * @return
     */
    public Object bind(Object target) {
        this.target = target;
        return Proxy.newProxyInstance(
                target.getClass().getClassLoader(),
                target.getClass().getInterfaces(),
                this
        );
    }

    /**
     * 代理方法
     *
     * @return
     */
    public boolean connect() {
        System.out.println("[---代理操作---]进行消息发送的通道的链接");
        return true;
    }

    /**
     * 代理方法
     */
    public void close() {
        System.out.println("[---代理操作---]关闭连接通道");
    }


    /**
     * 方法覆写
     *
     * @param proxy
     * @param method
     * @param args
     * @return
     * @throws Throwable
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        try {
            if (this.connect()) {
                // 代理调用
                return method.invoke(this.target, args);
            } else {
                throw new Exception("【ERROR】消息无法进行发送!!!");
            }
        } finally {
            // 要记得调用这个
            this.close();
        }
    }
}

运行结果:
[---代理操作---]进行消息发送的通道的链接
【网络消息发送】这种操作真骚,太TM好用了,就是还没理解精髓
[---代理操作---]关闭连接通道

思路讲解:本程序先将工厂设计模式与代理设计模式结合在一起,这样可以实现真实业务与代理业务的分割;同时利用工厂类对外隐藏了代理类的操作细节,这样的整合更加符合实际项目开发结构。在本程序中MessageService类要调用IMessage接口提供的send()方法,所以在MessageService类定义上使用类自定义的@UseMessage注解,以确定要使用的IMessage接口子类,如果要进行子类更换,则直接修改注解定义即可。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值