java注解常常用于自动化,简化代码开发成本,减少重复劳动,比如Spring框架使用了很多注解(如@Resource
, @Service
,@Component
等),让组件化可以非常简单的实施,而且代码清晰简洁。
常用注解
标准注解
- @Deprecated
添加到不鼓励使用的项上,当使用这种项时,编译器会发出警告
- @Override
表示是覆盖父类的方法,如果父类没有相同的声明,编译器能报错。
- @PostConstruct & @PreDestroy
被标记的方法,会在对象构造之后或移除之前被调用
- @Resource
资源注入
元注解
应用于注解的注解
- @Target
限定注解可以应用于那些项上,取值属于枚举类型 ElementType
常用取值
类型 | 注解适用场合 |
---|---|
TYPE | 类,enum,接口等 |
METHOD | 方法 |
CONSTRUCTOR | 构造函数 |
FIELD | 成员域 |
- @Retention
表示该注解应该保留多长时间
常用RetentionPolicy.RUNTIME,这种可以通过反射API来访问注解类型。
- @Documented
指定注解应该包含在注解项的文档中
- @Inherited
指定一个注解,当它应用于类型时,能自动被子类继承
常用Spring注解
Spring在支持依赖注入和AOP切面方面,做了很多基于注解的自动化工作。
@Reponsitory
用于数据访问层DAO,定义一个持久层Bean,该注解会自动解析SQLException翻译成通用的异常
@Service
用于业务层,定义一个业务层Bean,是最常用的注解
@Controller
用于WEB层定义MVC控制器
@Compenent
通用意义的组件,以上三者都是组件
自定义注解
有些时候,为了减少重复代码,自动化的做一些事情,需要自定义注解及解释分析。
注解语法
定义
modifiers @interface AnnotationName {
type elementName1();
type elementName2() default xxx;
...
}
注解元素支持的类型:
- 基本类型(int, short, long, byte, char, double, float, boolean)
- String
- Class
- enum类型
- 注解类型
- 以上类型的数组
使用
@AnnotationName(elementName1=value1, elementName2=value2)
一个项可以使用多个注解,只要它们属于不同的类型即可。
解析注解的例子
支持基于json配置的自动化配置接口的注解@Value
- Value.java
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 Value {
String value();
}
- IConfig.java
public interface IConfig {
@Value("url")
String dbUrl();
@Value("pool_size")
int poolSize();
}
- ConfigFactory.java
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Properties;
import com.alibaba.fastjson.JSON;
public class ConfigFactory {
private ConfigFactory() {}
public static IConfig create(final String config) {
final Properties properties = JSON.parseObject(config, Properties.class);
InvocationHandler handler = new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
final Value value = method.getAnnotation(Value.class);
if (value == null)
return null;
String property = properties.getProperty(value.value());
if (property == null)
return null;
final Class<?> returns = method.getReturnType();
if (returns.isPrimitive()) {
if (returns.equals(int.class))
return (Integer.valueOf(property));
else if (returns.equals(long.class))
return (Long.valueOf(property));
else if (returns.equals(double.class))
return (Double.valueOf(property));
else if (returns.equals(float.class))
return (Float.valueOf(property));
else if (returns.equals(boolean.class))
return (Boolean.valueOf(property));
}
return property;
}
};
return (IConfig) Proxy.newProxyInstance(
IConfig.class.getClassLoader(),
new Class[] { IConfig.class },
handler);
}
}
- MainTest.java
public class MainTest {
public static void main(String[] args) {
String strConfig = "{\"url\":\"https://www.suninf.net\", \"pool_size\":\"50\"}";
IConfig config = ConfigFactory.create(strConfig);
String url = config.dbUrl();
int pool_size = config.poolSize();
}
}
参考
- http://josh-persistence.iteye.com/blog/2226493
- http://www.infoq.com/cn/articles/cf-java-annotation
- http://www.cnblogs.com/techyc/p/3455950.html
- http://www.cnblogs.com/peida/archive/2013/04/24/3036689.html
- http://wiki.jikexueyuan.com/project/java-reflection/java-at.html
- http://gityuan.com/2016/01/23/java-annotation/
- http://computerdragon.blog.51cto.com/6235984/1210969
- https://www.zhihu.com/question/36486629