反射与Annotation
从JDK1.5之后Java开发提供了Annotation技术支持,这种技术为项目的编写带来新的模型,而后经过了长时间的发展,Annotation技术得到了非常广泛的应用,并且已经在所有的项目开发之中都会存在
1、反射取得Annotation信息
在进行类或方法定义的时候都可以使用一系列的 Annotation进行声明,于是如果要想获取这些Annotation的信息,那么就可以直接通过反射来完成。在java.lang.reflect里面有一个AccessibleObject类,在本类中提供有获取Annotation类的方法:
- 获取全部Annotation :public Annotation [] getAnnotations
- 获取指定Annotation :public T getAnnotation(Class annotationClass)
使用Annotation
public class JavaDemo {
public static void main(String[] args) throws Exception {
//获取接口上的Annotation
{
Annotation[] annotations = IMessage.class.getAnnotations(); //获取接口上的全部Annotation
for (Annotation annotation : annotations) {
System.out.println(annotation);
}
}
System.out.println("==================================");
//获取MessageImpl子类上的Annotation
{
Annotation[] annotations = MessageImpl.class.getAnnotations();
for (Annotation annotation : annotations) {
System.out.println(annotation);
}
}
System.out.println("==================================");
//获取MessageImpl.send子类上的Annotation
{
Method method = MessageImpl.class.getDeclaredMethod("send", String.class);
Annotation[] annotations = method.getAnnotations();
for (Annotation annotation : annotations) {
System.out.println(annotation);
}
}
}
}
@FunctionalInterface
@Deprecated(since = "2.0")
interface IMessage{ //有两个Annotation
void send(String message);
}
@SuppressWarnings("serial") //无法在程序执行的时候获取
class MessageImpl implements IMessage , Serializable {
@Override //无法在程序执行的时候获取
public void send(String message) {
System.out.println("发送消息!!!");
}
}
//@java.lang.FunctionalInterface()
//@java.lang.Deprecated(forRemoval=false, since="2.0")
//==================================
//==================================
不同的Annotation有它的存在范围
“@FunctionalInterface”是在运行时生效的Annotation,“@suppresswarnings”是在源代码编写的时候有效
2、自定义Annotation
在Java里面提供有新的语法,使用“@interface”来定义Annotation
自定义Annotation
public class JavaDemo {
public static void main(String[] args) throws Exception {
Method method = Message.class.getMethod("send", String.class); //获取指定方法
DefaultAnnotation annotation = method.getAnnotation(DefaultAnnotation.class); //获取指定的Annotation
System.out.println(annotation.title());
System.out.println(annotation.name());
String message = annotation.title() + "(" + annotation.name() + ")";
method.invoke(Message.class.getDeclaredConstructor().newInstance() , message);
}
}
@Retention(RetentionPolicy.RUNTIME) //定义Annotation运行策略
@interface DefaultAnnotation { //自定义Annotation
String title(); //获取数据
String name() default "linlin"; //获取数据,默认值
}
class Message {
@DefaultAnnotation(title = "1.0")
public void send(String message){
System.out.println("发送消息!!!" + message);
}
}
//1.0
//linlin
//发送消息!!!1.0(linlin)
使用Annotation之后的最大特点是可以结合反射机制实现程序的处理
3、工厂设计模式与Annotation整合
public class JavaDemo {
public static void main(String[] args) throws Exception {
MessageService service = new MessageService();
service.send("linlin");
}
}
@Retention(RetentionPolicy.RUNTIME)
@interface UseMesseage{
Class<?> clazz();
}
@UseMesseage(clazz = MessageImpl.class) //利用Annotation实现类的使用
class MessageService{
private IMessage message;
public MessageService(){
UseMesseage annotation = MessageService.class.getAnnotation(UseMesseage.class);
this.message = (IMessage) Factory.getInstance(annotation.clazz()); //直接通过Annotation获取
}
public void send(String message){
this.message.send(message);
}
}
class Factory{
private Factory() {}
public static <T> T getInstance(Class<T> clazz){ //直接返回一个实例化对象
try {
return (T) new MessageProxy().bind(clazz.getDeclaredConstructor().newInstance());
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
class MessageProxy implements InvocationHandler{
private Object target;
public Object bind(Object target){
this.target = target;
return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.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 {
try {
if(connect()){
return method.invoke(target , args);
} else {
throw new RuntimeException("消息发送失败");
}
} finally {
close();
}
}
}
interface IMessage{
void send(String message);
}
class MessageImpl implements IMessage {
@Override
public void send(String message) {
System.out.println("发送消息:" + message);
}
}
//{代理操作}连接消息通道
//发送消息:linlin
//{代理操作}关闭连接通道
由于Annotation的存在,所以对于面向接口的编程的配置处理将可以直接利用Annotation的属性完成控制,从而使得整体代码变得简洁