JAVA自定义注解的使用

JAVA反射

对于java来说,我们常见的功能都是类、属性、方法,这些在我们常规变成中,起着举足轻重的作用。但是JAVA之所以强大,反射机制才是JAVA的重中之重,在之前几章的博客中曾经提到利用JAVA的反射机制模拟mvc框架,模拟hibernate等数据库框架。但是在反射过程中,还有一项非常重要的元素,那就是注解。

经常接触spring的我们应该都了解,spring中代码里面注解有着极高的出场率,然而在什么时候我们会需要使用注解,注解都能帮我们干什么,相信好多人对注解的理解还是比较模糊的。下面我们详细了解一下注解

注解的定义

先引入一个比较调侃的话,“乔布斯重新定义了手机,罗永浩重新定义了傻逼”PS:这句话出自老罗的一个微博,本人无贬低老罗的意思。

首先让我们来看看官方对注解的定义:

Java 注解用于为 Java 代码提供元数据。作为元数据,注解不直接影响你的代码执行,但也有一些类型的注解实际上可以用于这一目的。Java 注解是从 Java5 开始添加到 Java 的。

从过来人的角度上理解这句话,其实很简单,但是从初学者的角度上来看,应该会是一头雾水,那么按照我的理解,注解应该这样定义:

当你无法对已经定义好的类,属性,方法进行改变;但是需求偏偏非要改变。那么不能改变代码,我们就去改变他的运行方式。

举例:

比如数据库定义好一个字段为日期类型,框架约束好,日期的格式为YYYY-MM-DD,但是偏偏有一个业务,必须要求日期要按照YYYY-MM-DD HH:MM:SS显示。

在比如,我们定义好的对象中,有三个属性,分别是name,age,sex。我们需要通过xml和其他系统进行交互,在我们自己使用的系统中,我们需要这三个字段,但是在和其他系统交互的时候,sex字段是隐私,我们不能给别人,但是我们还要使用这个对象。那么在同其他系统交互过程中,转为xml的时候,我们就要忽略某个字段。

应用:

由于举例中的第一个例子是SPRING MVC返回reponsebody中的常见问题,网上已经有很多解决方案,我们使用第二个例子进行解决

1、创建一个自定义注解类

import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface IgnoreXmlElement {
}

这是一个最基本的注解创建方式。当然我们注解里面还有各种属性,例如我们增加一个name的属性,可以

String name() default "##default";

因为第二个例子本身不需要太复杂的功能,我们暂时就不增加属性了。

2、在我们需要转换XML的类的某个属性上增加上该注解

	@IgnoreXmlElement
	private String sex;

3、在类转换xml的时候,根据注解对这个属性特殊处理

	public String toString() {
		String xml = null;
		try {
			Class<T> c = getEntityClass();
			JAXBContext jc = JAXBContext.newInstance(c);
			Marshaller marshaller = jc.createMarshaller();
			marshaller.setProperty(Marshaller.JAXB_ENCODING, Encode.UTF8);
			marshaller.setListener(new MarshallerListener()); 
			ByteArrayOutputStream bos = new ByteArrayOutputStream();
			marshaller.marshal(this, bos);
			xml = new String(Base64.encodeBase64(bos.toByteArray()), Encode.UTF8);
		} catch (Exception e) {
			throw new RuntimeException("解析为xml时出错:" + e.getMessage());
		}
		return xml;
	}

在类中,我们重写了类的toString方法,方便返回一个xml

marshaller.setListener(new MarshallerListener());

对xml的转化我们这里使用的java自带的jaxbcontext,我们对齐增加一个监听。

package com.easternie.sys.util;

import javax.xml.bind.Marshaller;

import com.easternie.his.webservice.model.data.IgnoreXmlElement;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;

/**
 * 对java对象转xml增加一个监听,如果节点为null空返回空节点
 * 
 * @author ZhangQiang
 *
 */
public class MarshallerListener extends Marshaller.Listener {
	public static final String BLANK_CHAR = "";

	@Override
	public void beforeMarshal(Object source) {
		super.beforeMarshal(source);
		Field[] fields = source.getClass().getDeclaredFields();
		for (Field f : fields) {
			f.setAccessible(true);
			Annotation an = f.getAnnotation(IgnoreXmlElement.class);
			if(an != null) {
				try {
					f.set(source, null);
				} catch (IllegalAccessException e) {
					e.printStackTrace();
				}
			}else {
				try {
					if (f.getType() == String.class && f.get(source) == null) {
						f.set(source, BLANK_CHAR);
					}
				} catch (IllegalAccessException e) {
					e.printStackTrace();
				}
			}
			
		}
	}
}

这个监听实现了如下两个功能,

功能一:如果我们通过反射获取的field的注解不为空,那么说明这个字段是我们转XML时候要忽略的,我们直接把他设置为NULL,这里要说明,在使用JAXBCONTEXT的过程中,我们可以给元素设置为NULL让其不产生XML节点。

功能二:但是如果是NULL就不显示节点了,貌似又违背了我们的需求,我们主动设置为NULL的应该不正常显示,但是如果这个字段本身就为NULL,我们应该给用户返回一个空节点。所有又有了else中的代码,我们增加一个空格,保证返回给用户的是一个空节点,而非连节点都不显示。

总结:

写在最后,注解一般情况下都是结合反射使用,用来处理非常规流程的问题。所以在我们开发过程中遇到此类问题的时候。我们应该可以想到使用注解或者自定义注解,当然上面仅仅是举例在属性上增加注解,实际在类,在方法上增加注解获取注解和上面代码也大同小异,不再过多描述。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值