专栏名称: 老马说编程
从入门到高级, 深入浅出, 老马和你一起探索编程及计算机技术的本质, 篇篇原创, 用心写作。
目录
相关文章推荐
阿里云云栖号  ·  重磅发布 ... ·  14 小时前  
大淘宝技术  ·  阿里淘天T-Star Lab ... ·  14 小时前  
老刘说NLP  ·  大模型应用推介:多模态RAG、语法纠错、个人 ... ·  17 小时前  
程序猿  ·  还有人手动画图?一键生成 Draw.io ... ·  昨天  
老刘说NLP  ·  再看知识图谱本体生成:RAG用于Mysql数 ... ·  2 天前  
51好读  ›  专栏  ›  老马说编程

(85) 注解 / 计算机程序的思维逻辑

老马说编程  · 公众号  · 程序员  · 2017-04-28 22:52

正文

请到「今天看啥」查看全文



依赖注入容器
现代Java开发经常利用某种框架管理对象的生命周期及其依赖关系,这个框架一般称为DI(Dependency Injection)容器,DI是指依赖注入,流行的框架有Spring、Guice等,在使用这些框架时,程序员一般不通过new创建对象,而是由容器管理对象的创建,对于依赖的服务,也不需要自己管理,而是使用注解表达依赖关系。这么做的好处有很多,代码更为简单,也更为灵活,比如容器可以根据配置返回一个动态代理,实现AOP,这部分我们后续章节再介绍。


看个简单的例子,Guice定义了Inject注解,可以使用它表达依赖关系,比如像下面这样:

public class OrderService {

@Inject
UserService userService;

@Inject
ProductService productService;

//....
}


Servlet 3.0
Servlet是Java为Web应用提供的技术框架,早期的Servlet只能在web.xml中进行配置,而Servlet 3.0则开始支持注解,可以使用@WebServlet配置一个类为Servlet,比如:

@WebServlet(urlPatterns = "/async", asyncSupported = true)
public class AsyncDemoServlet extends HttpServlet {...}


Web应用框架
在Web开发中,典型的架构都是MVC(Model-View-Controller),典型的需求是配置哪个方法处理哪个URL的什么HTTP方法,然后将HTTP请求参数映射为Java方法的参数,各种框架如Spring MVC, Jersey等都支持使用注解进行配置,比如,使用Jersey的一个配置示例为:

@Path("/hello")
public class HelloResource {

@GET
@Path("test")
@Produces(MediaType.APPLICATION_JSON)

public Map test(
@QueryParam("a") String a) {
Map map = new HashMap();
map.put("status", "ok");
return map;
}
}


类HelloResource将处理Jersey配置的根路径下/hello下的所有请求,而test方法将处理/hello/test的GET请求,响应格式为JSON,自动映射HTTP请求参数a到方法参数String a。


神奇的注解
通过以上的例子,我们可以看出,注解似乎有某种神奇的力量,通过简单的声明,就可以达到某种效果。在某些方面,它类似于我们在 62节 介绍的序列化,序列化机制中通过简单的Serializable接口,Java就能自动处理很多复杂的事情。它也类似于我们在并发部分中介绍的 synchronized关键字 ,通过它可以自动实现同步访问。


这些都是声明式编程风格,在这种风格中,程序都由三个组件组成:

  1. 声明的关键字和语法本身

  2. 系统/框架/库,它们负责解释、执行声明式的语句

  3. 应用程序,使用声明式风格写程序


在编程的世界里,访问数据库的SQL语言,编写网页样式的CSS,以及后续章节将要介绍的正则表达式、函数式编程都是这种风格,这种风格降低了编程的难度,为应用程序员提供了更为高级的语言,使得程序员可以在更高的抽象层次上思考和解决问题,而不是陷于底层的细节实现。


创建注解

框架和库是怎么实现注解的呢?我们来看注解的创建。


@Override的定义

我们通过一些例子来说明,先看@Override的定义:

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)

public @interface Override {
}


定义注解与定义接口有点类似,都用了interface,不过注解的interface前多了@,另外,它还有两个元注解@Target和@Retention,这两个注解专门用于定义注解本身。


@Target

@Target表示注解的目标,@Override的目标是方法(ElementType.METHOD),ElementType是一个枚举,其他可选值有:

  • TYPE:表示类、接口(包括注解),或者枚举声明

  • FIELD:字段,包括枚举常量

  • METHOD:方法

  • PARAMETER:方法中的参数

  • CONSTRUCTOR:构造方法

  • LOCAL_VARIABLE:本地变量

  • ANNOTATION_TYPE:注解类型

  • PACKAGE:包


目标可以有多个,用{}表示,比如@SuppressWarnings的@Target就有多个,定义为:

@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
@Retention(RetentionPolicy.SOURCE)

public @interface SuppressWarnings {
String[] value();
}


如果没有声明@Target,默认为适用于所有类型。







请到「今天看啥」查看全文