标签:serial 执行 final connect voc war process print instance
一.反射与Annotation
从JDK1.5之后,java开发提供了Annotation技术支持,这种技术为项目的编写带来的新的模型,经过了多年的发展,Annotation的技术得到了非常广泛的应用,并且已经在所有的项目开发之中都会存在.
--获取Annotation:在进行类或方法定义的时候都可以使用一系列的Annotation进行色声明,于是如果要想获取这些Annotation的信息,那么就可以直接通过反射来完成.在java.lang.reflect里面,有一个叫做AccessibleObject类,在这个类中提供有获取Annotation的方法:
获取全部Annotation: public Annotation[] getAnnotations()
获取指定的Annotation: public <T extends Annotation> T getAnnotation(Class<T> annotationClass)
--范例:定义一个接口,并且在接口上使用Annotation
1 package 反射.反射与Annotation;
2
3 import java.lang.annotation.Annotation;
4
5 /**
6 * @author : S K Y
7 * @version :0.0.1
8 */
9 @FunctionalInterface
10 @Deprecated
11 interface IMessage { //存在两个Annotation注解
12 public void send();
13 }
14
15 @SuppressWarnings("serial")
16 class MessageImpl implements IMessage {
17 @Override
18 public void send() {
19 System.out.println("消息发送...");
20 }
21 }
22
23 public class AnnotationDemo {
24 public static void main(String[] args) {
25 //获取接口上的Annotation信息
26 Annotation[] annotations = IMessage.class.getAnnotations(); //获取接口上的所有的Annotation
27 for (Annotation annotation : annotations) {
28 System.out.println(annotation);
29 }
30 }
31 }
--运行结果
@java.lang.FunctionalInterface()
@java.lang.Deprecated()
Process finished with exit code 0
--尝试获取实现类的注解信息
1 public class AnnotationDemo {
2 public static void main(String[] args) {
3 //获取接口上的Annotation信息
4 Annotation[] annotations = IMessage.class.getAnnotations(); //获取接口上的所有的Annotation
5 for (Annotation annotation : annotations) {
6 System.out.println(annotation);
7 }
8 System.out.println("=========================");
9 //获取子类上的Annotation
10 Annotation[] implAnnotations = MessageImpl.class.getAnnotations();
11 for (Annotation implAnnotation : implAnnotations) {
12 System.out.println(implAnnotation);
13 }
14 }
15 }
--运行结果
@java.lang.FunctionalInterface()
@java.lang.Deprecated()
=========================
Process finished with exit code 0
--发现并没有获取到注解@SuppressWarnings("serial"),其原因是该注解无法在程序执行的时候获取.那么尝试获取MessageImpl.send()方法上的Annotation会怎么样呢:
1 public class AnnotationDemo {
2 public static void main(String[] args) throws NoSuchMethodException {
3 //获取接口上的Annotation信息
4 Annotation[] annotations = IMessage.class.getAnnotations(); //获取接口上的所有的Annotation
5 for (Annotation annotation : annotations) {
6 System.out.println(annotation);
7 }
8 System.out.println("=========================");
9 //获取子类上的Annotation
10 Annotation[] implAnnotations = MessageImpl.class.getAnnotations();
11 for (Annotation implAnnotation : implAnnotations) {
12 System.out.println(implAnnotation);
13 }
14 //尝试获取MessageImpl.toString()方法上的Annotation
15 System.out.println("==============================");
16 Method send = MessageImpl.class.getDeclaredMethod("send");
17 Annotation[] sendAnnotations = send.getAnnotations();
18 for (Annotation sendAnnotation : sendAnnotations) {
19 System.out.println(sendAnnotation);
20 }
21 }
22 }
--运行结果
@java.lang.FunctionalInterface()
@java.lang.Deprecated()
=========================
==============================
Process finished with exit code 0
--可以发现也无法在运行时获取到 @Override注解的相关信息.不同的Annotation有他的存在的范围:
@FunctionalInterface:
@Documented
@Retention(RetentionPolicy.RUNTIME) //描述的是运行是生效
@Target(ElementType.TYPE)
public @interface FunctionalInterface {}
@SuppressWarnings("serial"):
@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
@Retention(RetentionPolicy.SOURCE) //描述的是在源代码时生效
public @interface SuppressWarnings {
String[] value();
}
--可以发现"@FunctionalInterface"是在程序运行时生效的Annotation,所以当程序执行的时候可以获取此Annotation,而"@SuppressWarnings"是在源代码编写的时候有效.管观察RetentionPolicy的定义:
public enum RetentionPolicy {
SOURCE,
CLASS,
RUNTIME
}
--在RetentionPolicy枚举类中还存在一个class的定义指的是在类定义的时候生效.
二.自定义Annotation
现在已经清楚了Annotation的获取,以及Annotation的运行策略,但是最为关键性的因素是如何可以实现自定义的Annotation.为此在java中提供有新的语法使用"@interface"来定义Annotation.
范例:自定义Annotation
1 package 反射.反射与Annotation;
2
3 import java.lang.annotation.Retention;
4 import java.lang.annotation.RetentionPolicy;
5 import java.lang.reflect.InvocationTargetException;
6 import java.lang.reflect.Method;
7
8 /**
9 * @author : S K Y
10 * @version :0.0.1
11 */
12 @Retention(RetentionPolicy.RUNTIME)
13 //定义Annotation运行时的策略
14 @interface DefaultAnnotation { //自定义的Annotation,
15 public String title(); //获取数据
16
17 public String url() default "获取数据的默认值"; //获取数据,默认值
18 }
19
20 class Message {
21 @DefaultAnnotation(title = "sendMessage") //title不具备默认值,因此必须去显示的定义
22 public void send(String msg) {
23 System.out.println("[消息发送]" + msg);
24 }
25 }
26
27 public class MyAnnotationDemo {
28 public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
29 Method method = Message.class.getDeclaredMethod("send", String.class); //获取指定的方法
30 DefaultAnnotation annotation = method.getAnnotation(DefaultAnnotation.class);//获取指定的Annotation1
31 String title = annotation.title(); //直接调用Annotation中的方法
32 String url = annotation.url();
33 System.out.println(title + " " + url);
34 String msg = annotation.title() + " " + url;
35 method.invoke(Message.class.getDeclaredConstructor().newInstance(),msg); //利用反射实现消息的发送
36 }
37 }
--运行结果
sendMessage 获取数据的默认值
[消息发送]sendMessage 获取数据的默认值
Process finished with exit code 0
--使用Annotation之后的最大特点是可以结合反射机制实现程序的处理.
三.工厂设计模式与Annotation整合
在清楚了Annotation的整体作用之后,但是Annotation在开发之中,到底可以完成什么样的功能.为了更好的理解Annotation的处理操作的目的,下面将结合工厂设计模式来应用Annotation操作.
1 package 反射.Annotation与工厂设计模式整合;
2
3
4 import java.lang.reflect.InvocationHandler;
5 import java.lang.reflect.Method;
6 import java.lang.reflect.Proxy;
7
8 /**
9 * @author : S K Y
10 * @version :0.0.1
11 */
12 interface IMessage {
13 public void send(String msg);
14 }
15
16 class MessageImpl implements IMessage {
17 @Override
18 public void send(String msg) {
19 System.out.println("[消息发送]" + msg);
20 }
21 }
22
23 class MessageProxy implements InvocationHandler {
24 private Object target;
25
26
27 public Object bind(Object target) {
28 this.target = target;
29 return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
30 }
31
32 public boolean connect() {
33 System.out.println("[代理操作]进行消息发送通道的连接");
34 return true;
35 }
36
37 public void close() {
38 System.out.println("[代理操作]关闭连接通道.");
39 }
40
41 @Override
42 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
43 try {
44 if (this.connect()) {
45 return method.invoke(this.target, args);
46 } else {
47 throw new Exception("[error]消息无法进行发送");
48 }
49 } finally {
50 this.close();
51 }
52 }
53 }
54
55 class Factory {
56 private Factory() {
57 }
58 public static <T> T getInstance(Class<T> tClass) { //直接返回一个实例化的操作对象
59 try {
60 return (T) new MessageProxy().bind(tClass.getDeclaredConstructor().newInstance());
61 } catch (Exception e) {
62 e.printStackTrace();
63 return null;
64 }
65 }
66 }
67 class MessageService{
68 private IMessage message;
69
70 public MessageService() {
71 this.message = Factory.getInstance(MessageImpl.class);
72 }
73 public void send(String msg){
74 this.message.send(msg);
75 }
76 }
77 public class AnnotationFactoryDemo {
78 public static void main(String[] args) throws IllegalAccessException, InstantiationException {
79 MessageService service = new MessageService();
80 service.send("hello");
81
82 }
83 }
--运行结果
[代理操作]进行消息发送通道的连接
[消息发送]hello
[代理操作]关闭连接通道.
Process finished with exit code 0
--上述代码的实现每次都需要在MessageService类中给出MessageImpl.class的声明,使用注解形式来简化代码
1 package 反射.Annotation与工厂设计模式整合;
2
3
4 import java.lang.annotation.Retention;
5 import java.lang.annotation.RetentionPolicy;
6 import java.lang.reflect.InvocationHandler;
7 import java.lang.reflect.Method;
8 import java.lang.reflect.Proxy;
9
10 /**
11 * @author : S K Y
12 * @version :0.0.1
13 */
14 interface IMessage {
15 public void send(String msg);
16 }
17
18 class MessageImpl implements IMessage {
19 @Override
20 public void send(String msg) {
21 System.out.println("[消息发送]" + msg);
22 }
23 }
24
25 class MessageProxy implements InvocationHandler {
26 private Object target;
27
28
29 public Object bind(Object target) {
30 this.target = target;
31 return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
32 }
33
34 public boolean connect() {
35 System.out.println("[代理操作]进行消息发送通道的连接");
36 return true;
37 }
38
39 public void close() {
40 System.out.println("[代理操作]关闭连接通道.");
41 }
42
43 @Override
44 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
45 try {
46 if (this.connect()) {
47 return method.invoke(this.target, args);
48 } else {
49 throw new Exception("[error]消息无法进行发送");
50 }
51 } finally {
52 this.close();
53 }
54 }
55 }
56
57 class Factory {
58 private Factory() {
59 }
60 public static <T> T getInstance(Class<T> tClass) { //直接返回一个实例化的操作对象
61 try {
62 return (T) new MessageProxy().bind(tClass.getDeclaredConstructor().newInstance());
63 } catch (Exception e) {
64 e.printStackTrace();
65 return null;
66 }
67 }
68 }
69 @Retention(RetentionPolicy.RUNTIME)
70 @interface UseMessage{
71 public Class<?> thisClass();
72 }
73 @UseMessage(thisClass = MessageImpl.class)
74 class MessageService{
75 private IMessage message;
76
77 public MessageService() {
78 UseMessage annotation = MessageService.class.getAnnotation(UseMessage.class);
79 this.message = (IMessage) Factory.getInstance(annotation.thisClass());
80 }
81 public void send(String msg){
82 this.message.send(msg);
83 }
84 }
85 public class AnnotationFactoryDemo {
86 public static void main(String[] args) throws IllegalAccessException, InstantiationException {
87 MessageService service = new MessageService();
88 service.send("hello");
89
90 }
91 }
--这样我们就可以依据注解来修改整个程序的功能实现.由于Annotation的存在,对于面向接口的配置处理可以直接利用Annotation的属性完成控制,从而使得整体代码变得简洁.
标签:serial 执行 final connect voc war process print instance
原文地址:https://www.cnblogs.com/skykuqi/p/11445785.html