怪本身二,曾一度理解java的@和python的@是相似的概念,在刷了python后,回头来再看java的注解各类懵逼,立下此文,以警后人,顺便,题段诗:java
python代码跑完后,冬雷滚滚夏雨雪。python
java项目看完时,家祭无忘告乃翁。spring
——————————————————————华丽的分割线———————————————————api
综述:框架
python的@是一种语法糖,主要是对装饰器的应用,更贴近函数式的概念。在装饰器中是有具体的代码逻辑,会改变装饰对象的行为和性质。装饰器通常用在方法和类上函数
而java的注解仅仅是一种代码层面上的注释,仅仅是个代码能看懂的标记,不会改变装饰对象,实际的逻辑都是框架去作的。注解能够用在方法,类,变量上。.net
对java产生误解的地方就是,实际上python仅经过装饰器就能实现AOP,而看java的时候还须要应用动态代理,去设计切点,链接点,通知,心想,怎么搞得那么复杂...还有注解的定义里啥代码也没有是在搞毛,这个注解会干吗。然鹅其实人家啥也不干。。。纯粹是被python惯坏了设计
——————————————————————华丽的分割线———————————————————代理
python:对象
def timer(func):
def _timer(*args,**kw):
begin=datetime.now().microsecond
rs=func(*args,**kw)
end=datetime.now().microsecond
print("函数%s耗时%d"%(func.__name__,end=begin)) return rs return _timer
def foo():
print("function foo")
这样即至关于foo=timer(foo),即函数为变量
再调用foo(),至关于跑一下在运行原来的foo前有个begin后有个end一减算一下时间,便可知道foo的运行时间
那么@timer这个函数加给任意一个函数,都能得出它的实际,就跟AOP同样同样的
——————————————————————华丽的分割线———————————————————
java:
java从jdk1.5后开始支持注解,仅仅是标记,阅读的时候用人类语言理解就行。
在自定义注解时有几个jdk提供的元注解
注解 | 说明 |
---|---|
@Target | 表示该注解能够用在什么地方,由ElementType枚举定义 CONSTRUCTOR:构造器的声明 FIELD:域声明(包括enum实例) LOCAL_VARIABLE:局部变量声明 METHOD:方法声明 PACKAGE:包声明 PARAMETER:参数声明 TYPE:类、接口(包括注解类型)或enum声明 ANNOTATION_TYPE:注解声明(应用于另外一个注解上) TYPE_PARAMETER:类型参数声明(1.8新加入) TYPE_USE:类型使用声明(1.8新加入) PS:当注解未指定Target值时,此注解可使用任何元素之上,就是上面的类型 |
@Retention | 表示须要在什么级别保存该注解信息,由RetentionPolicy枚举定义 SOURCE:注解将被编译器丢弃(该类型的注解信息只会保留在源码里,源码通过编译后,注解信息会被丢弃,不会保留在编译好的class文件里) CLASS:注解在class文件中可用,但会被VM丢弃(该类型的注解信息会保留在源码里和class文件里,在执行的时候,不会加载到虚拟机(JVM)中) RUNTIME:VM将在运行期也保留注解信息,所以能够经过反射机制读取注解的信息(源码、class文件和执行的时候都有注解的信息) PS:当注解未定义Retention值时,默认值是CLASS |
@Documented | 表示注解会被包含在javaapi文档中 |
@Inherited | 容许子类继承父类的注解 |
比方说spring中Controller
@Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Component public @interface Controller { String a() default “”; }
@Controller(“/path”) public class testController { }
这里有个快捷方式,就是说注解Controller里只有一个参数a时,在使用时就不用a="/path",直接写上就行