java服务器框架 - 注解

注解:
大部分都用来设计JAVA框架 , 由于他的写法简单 , 重复利用高的特点。
注解用修饰符:@interface , 表示 , 实现了java.lang.annotation接口。属性
@Target , @Retention。
@Target 用来修饰类型, ElementType.TYPE 是用来修饰类,
ElementType .METHOD , 是用来修饰方法。
@Retention 是运行类型 , RetentionPolicy.RUNTIME 运行当中的状态。

有方法 , 必须要加默认值

以下我们以前端发送来的消息为列:
找到对应的handler , 去处理对应的方法

例子如下:

package com.game.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
 *  类的注解
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface MessageAnnotation {

	/**
	 * 开启还是关闭
	 */
    boolean isGm() default true;
}
package com.game.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
 * 方法的注解
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface MethodAnnotation {

	 boolean isGm() default true;
}

修饰的类:

package com.game.handler;

import com.game.annotation.MessageAnnotation;
import com.game.annotation.MethodAnnotation;
import com.game.mahjonggame.message.BroadcastOwnDrawWinActionMessage;
@MessageAnnotation
public class TestHandler {

	@MethodAnnotation
	public void testHandler(BroadcastOwnDrawWinActionMessage message){
		System.out.println("aaa-bbb");	
	}
}

怎样通过外部调用,去访问到@MessageAnnotation的方法呢?

	/**
	 * 所有的类初始化一遍  , 把符合情况的保存下来 
	 */
	public RegisterMessage(URL url){
     //把符合情况的拉下来
		try {
				load(url , new ArrayList<Class<?>>());
		} catch (Exception e) {
				e.printStackTrace();
		}
	}

	   private void load(URL url, List<Class<?>> classes) throws Exception {
		if ("jar".equals(url.getProtocol())) {
			findClassByJar(url.getFile(), classes);
		} else {
			File root = new File(url.getPath());
			String prefix = root.getAbsolutePath();
			findClassByCls(root, prefix, classes, PATH);
			for(Class<?> class1:classes){
				registerMessage(class1);
			}
		}
	}

   /**
     * 根据路径遍历获得JAR包下的所有.class文件
     * 
     * @param path
     * @return
     * @throws IOException
     * @throws ClassNotFoundException 
     */
    @SuppressWarnings("resource")
    private void findClassByJar(String path, List<Class<?>> list) {
    	try {
  		path = URLDecoder.decode(path,"utf-8");
    		String jarInfo = path.substring(0, path.lastIndexOf(".jar!"));
    		String jarFilePath = jarInfo.substring(jarInfo.indexOf("/"));
    		JarFile jarFile = new JarFile(jarFilePath + ".jar");
    		Enumeration<JarEntry> entrys = jarFile.entries();
    		while (entrys.hasMoreElements()) {
    			JarEntry entry = entrys.nextElement();
    			if (!entry.isDirectory()) {
  				if (entry.getName().endsWith("Handler.class")) {
    					String clasPath = entry.getName().substring(0, entry.getName().length() - 6);
list.add(Class.forName(clasPath.replace("/", ".")));
    				}
   			}
    		}
    	} catch (Exception e) {
throw new RuntimeException("error in findClassByJar", e);
    	}
    }

// 通过	file.listFiles 方法 找到对应的所有文件 , 用递归的方法  , 找到对应的类

   private void findClassByCls(File file, String prefix, List<Class<?>> list, String packages) {
    	try {
    		if (file.isDirectory()) {
    			for (File f : file.listFiles())
  findClassByCls(f, prefix, list, packages);
    		} else {
    			if (file.getName().endsWith("Handler.class")) {
						String parent = file.getParent();
    				String name = file.getName();
    				String packageName = null;
    				if (parent.equals(prefix))// 如果是根路径
    					packageName = "";
    				else
    					packageName = parent.substring(prefix.length() + 1) + File.separator;
    				String className = name.substring(0, name.length() - 6);
    				String classpath = (packageName + className).replace(File.separator, ".");
    				list.add(Class.forName(packages + "." + classpath));
    				}
    		}
    	} catch (Exception e) {
    	throw new RuntimeException("error in findClassByCls", e);
    	}
    }

@SuppressWarnings("unchecked")
	private void registerMessage(Class<?> cls) throws Exception {
	MessageAnnotation handler = cls.getAnnotation(MessageAnnotation.class);
		if( null != handler ) {
		Method[] methods = cls.getDeclaredMethods();
			for(Method m : methods){
			MethodAnnotation action = m.getAnnotation(MethodAnnotation.class);
				if (action != null) {
					Class[] params = m.getParameterTypes();
						if (params.length != 1) {
						//多个参数
						//throw new IllegalArgumentException("参数只能有一个," + getPositionMsg(cls, m, params[0]));
					}
					Object msg = params[0].newInstance();
					if (!(msg instanceof Message)) {
						/*throw new IllegalArgumentException(
								"参数必须是Message子类," + getPositionMsg(cls, m, params[0]));*/
					}
					Message message = (Message) msg;
					int messageId = message.getId();
					MessageSend msgSwap = messageSwaps.get(messageId);
					// 加载已有的HANDLER
					Object  msgHandler = cls.newInstance();
					MethodAccess methodAccess = MethodAccess.get(cls);
					msgSwap = new MessageSend(params[0], msgHandler, m, methodAccess);
					messageSwaps.put(messageId, msgSwap);
					msgSwap.setGm(action.isGm());
					}
			}
			}
	}
		public MessageSend getMessageSend(int sendId){
		return  messageSwaps.get(sendId);
	}

调用方法:
通过 methodAccess.invoke(handler, method.getName(), msg); 方法调用对应的类

package com.game.annotation;

import java.lang.reflect.Method;

import com.esotericsoftware.reflectasm.MethodAccess;
import com.game.message.Message;
public class MessageSend {

	private Class<Message> msgCls;
	private Object handler;
	private Method method;
	private MethodAccess methodAccess;
	private boolean isGm;
	public MessageSend(Class<Message> msgCls, Object handler, Method method, MethodAccess methodAccess) {
		this.msgCls = msgCls;
		this.method = method;
		this.handler = handler;
		this.methodAccess = methodAccess;
	}
	
   Class<Message> getMsgCls() {
		return msgCls;
	}

	public Method getMethod() {
		return method;
	}

	public Object getHandler() {
		return handler;
	}

	public boolean isGm() {
		return isGm;
	}

 	void setGm(boolean gm) {
		isGm = gm;
	}
	
	public void action(Message msg) throws Exception {
//		method.invoke(handler, msg);//性能太差了
		methodAccess.invoke(handler, method.getName(), msg);
	}

	public String getHandlerClassName() {
		return handler.getClass().getName() + ":" + method.getName();
	}

main 函数:

public class TestMain {

	public static void main(String[] args) {
	RegisterMessage message =  new RegisterMessage(TestMain.class.getResource("/com"));
		try {
		message.getMessageSend(254123).action( new BroadcastOwnDrawWinActionMessage());
		} catch (Exception e) {
			e.printStackTrace();
		};
	}

希望对你有用。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值