JAVA高级特性 - 注解

注解是插入到代码中用于某种工具处理的标签。这些标签可以在源码层次上进行操作,或者可以处理编译器将其纳入到注解类文件中。

注解不会改变对程序的编译方式。Java编译器会对包含注解和不包含注解的代码生成相同的虚拟机指令。

在java中,注解通常使用@Annotation来表示,注解通常用于框架的设计,配合反射,从而减少代码量,明确业务逻辑。

我们最为常见的注解是@Override和@Test这种注解,前者用于标明方法为实现某接口,后者则常用于JUNIT.

下面给出个注解的实例定义:

@Target(ElementType.Method)
@Retention(RetentionPolicy.RUNTIME)
public @interface Test
{
    long timeout() default 0L;
}

@Interface声明创建了一个真正的java接口。处理注解的工具将接受实现了该接口的对象。

注解Target和Retention是元注解,它们注解了注解,即标识了Test注解是一个只能用在方法上的注解,并且当类文件载入虚拟机的时候,仍然可以保留下来。

注解的使用通常要配合反射使用,下面给出例子:

package com.inspur.jiyq.corejava.annotation;

import java.awt.Color;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class ButtonFrame extends JFrame{
	private static final long serialVersionUID = 1L;
	
	public static final int DEFAULT_WIDTH = 300;
	public static final int DEFAULT_HEIGHT = 200;
	
	private JPanel panel;
	private JButton yellowButton;
	private JButton blueButton;
	private JButton redButton;
	
	public ButtonFrame()
	{
		setTitle("ButtonTest");
		setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);
		
		panel = new JPanel();
		add(panel);
		
		yellowButton = new JButton("Yellow");
		blueButton = new JButton("Blue");
		redButton = new JButton("Red");
		
		panel.add(yellowButton);
		panel.add(blueButton);
		panel.add(redButton);
		
		ActionListenerInstaller.processAnnotations(this);
	}
	
	@ActionListenerFor(source = "yellowButton")
	public void yellowBackground()
	{
		panel.setBackground(Color.YELLOW);
	}
	
	@ActionListenerFor(source = "blueButton")
	public void blueBackground()
	{
		panel.setBackground(Color.BLUE);
	}
	
	@ActionListenerFor(source = "redButton")
	public void redBackground()
	{
		panel.setBackground(Color.RED);
	}

	public static void main(String[] args)
	{
		ButtonFrame frame = new ButtonFrame();
		frame.setVisible(true);
	}
}

  

package com.inspur.jiyq.corejava.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ActionListenerFor {
	String source();
}

  

package com.inspur.jiyq.corejava.annotation;

import java.awt.event.ActionListener;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * 用于分析注解及新增行为监听器
 */
public class ActionListenerInstaller {
	/**
	 * Process all ActionListenerFor annotations in the given object
	 * 
	 * @param obj
	 *            an object whose methods may have ActionListnerFor annotations
	 */
	public static void processAnnotations(Object obj) {
		try {
			Class<?> cl = obj.getClass();
			for (Method m : cl.getDeclaredMethods()) {
				ActionListenerFor a = m.getAnnotation(ActionListenerFor.class);
				if (a != null) {
					Field f = cl.getDeclaredField(a.source());
					f.setAccessible(true);
					addListener(f.get(obj), obj, m);
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public static void addListener(Object source, final Object param,
			final Method m) throws NoSuchMethodException, SecurityException,
			IllegalAccessException, IllegalArgumentException,
			InvocationTargetException {
		InvocationHandler handler = new InvocationHandler() {
			@Override
			public Object invoke(Object proxy, Method method, Object[] args)
					throws Throwable {
				return m.invoke(param);
			}
		};

		Object listener = Proxy.newProxyInstance(null,
				new Class[] { java.awt.event.ActionListener.class }, handler);
		Method adder = source.getClass().getMethod("addActionListener",
				ActionListener.class);

		adder.invoke(source, listener);
	}
}

  

 

posted @ 2014-04-21 15:27  纪玉奇  阅读(850)  评论(0编辑  收藏  举报