`
江南白衣
  • 浏览: 550027 次
  • 来自: 广州
社区版块
存档分类
最新评论

侵入,无侵入? Annotation vs Interface

阅读更多
1. Interface
   使用Interface 定义对象的类型,框架根据对象的接口来提供服务,这种模式是古而有之的Java框架设计者必习之法,从最重量的EJB到最轻量的Spring,都离不开这种方式,也的确解决了很多问题。比如在大家熟悉的Spring里:
  • BeanFactoryAware接口,框架看到它就会调用Bean的setBeanFactory(BeanFactory beanFactory) 函数,将BeanFactory传给它,让它自行用BeanFactory获得更多Bean,而不仅限于依赖注入的Bean。
  • FactoryBean接口,框架看到它就不会把这个Bean放入自己的Context,而是调用它的getObject()函数,将返回的结果作为Bean放入。Spring里很多功能依赖于这个扩展机制,因为它可以用Factory模式返回任意类型对象,而不是<bean class="foo">中class指定类型。
  • InitializingBean接口,因为很多Bean在各setter注入后,还需要一个总的init函数进行初始化,比如需要同时根据注入的属性A和 B,来初始化属性C的值。这时候框架就会调用afterPropertiesSet() 初始化。

        等等,最后一个InitializingBean接口很邪恶阿!!硬要POJO实现一个名字怪怪的afterPropertiesSet()函数,侵入得不能再侵入阿。


2. 无侵入
        所以,Spring提供了另一种方式,在配置文件里定义初始方法的名字:

       <bean class="foo" init-method="init"/>
        其实Spring提倡的无侵入有两种层次:

        一种是像Quartz,JMX,WebService这些模块,POJO啥都不用做,Spring使用AOP,FactoryBean这样的机制使它们白日飞升变为WebService,或者具有定时执行的能力。

        一种是像init-method的例子,POJO并不很明显的实现Spring的接口,知觉Spring的存在,自己实现自己的函数,然后由Spring的配置文件去调用它们。

        前一种无侵入的作用非常明显,后一种的意义就看具体的场景了,有时候实现一下Spring的接口也没什么所谓,但有时候各种原因会希望不显式的实现接口。

 3. Annotation   
      在JDK5新增了Annotation的模式。Annotation 是XML配置模式的竞争者,但题目太大本篇就不讨论了,个人观点是主要看数据属于配置数据还是代码元数据。

      本文forcus Interface vs Annotation来定义对象类型和行为。最开始用Annotation 使Java代码不再那么受传统模式局限的是TestNG,然后JUnit 4紧跟其后,在默认机制之外,可以用annotation 来灵活定义setup函数和测试函数。

   4. 对比演示
  下面,我们以SpringSide里的UndeleteEntity接口和@Undelete 标识的实现,具体演示一下两者。

  项目需求是如果把Entity对象定义为不能删除,Dao基类的remove函数就不会真正删除该对象,而是设置状态列为"无效"。

Interface是这样实现的:
Interface 定义:

public interface UndeletableEntity {
    void setStatus(String status);
}Interface 在Entity使用:

public class Book implements UndeletableEntity {
  private String status;  public void setStatus(String status) {
   this.status = status;
  }
 }

Interface 在框架中使用:

//根据Class 判断
if(UndeletableEntity.class.isAssignableFrom(Book.class)){
    ...
}
//根据Bean实体判断
if(bookinstanceof UndeletableEntity{
   ((UldeletableEntity)bean).setStatus("-1");
}


    大家都很熟悉的写法,就不解释了。

Annotation是这样实现的:
   Annotation 定义:

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Undeletable {
  String status() default "status";
}
   原本怪Sun怎么这么抠门,用@interface 而不另外搞一个关键字,原来Sun的意思就是把Interface和Annotation的定位一样呀。

   @Target 定义Annotation 可用在什么地方,比如类型,函数,函数参数等。Type代表Class,Interface...

   @Retention(RetentionPolicy.RUNTIME)表明是个运行期的annotation,否则后面的代码就不会起作用了。

   String status() 定义了annotation有个status的属性,而且可以定义默认值为 "status"。

   Annotation在Entity使用:

@Undeletable
  public class Book{
    private String status;
     public void setStatus(String status) {
        this.status = status;
     }
  } 

@Undeletable(status = "status2")
    public class BookWithNewStatus {
    private String status2;
    public void setStatus2(String status2) {
        this.status2 = status2;
    }
} 


在框架中的判断:

if (entityClass.isAnnotationPresent(Undeletable.class)) {
    Undeletable anno = (Undeletable) entityClass.getAnnotation(Undeletable.class);
    statusProperty = anno.status();
}

   可见,annotation的模式,比interface要少一点侵入性,不规定死status列的名称,而且还可以灵活定义更多元属性,比如定义无效时的值为"-1","unvalid"。

   但是,这种模式也和所有动态的东西向一样,失去了编译期校验的优势,POJO如果没有setStatus() 这个函数在编译期也检查不出来。

   BTW.标题太长了,其实也属于幼学琼林系列,show一下用interface 和 annotation 定义元数据,交给框架去反射的基本写法。

分享到:
评论
18 楼 dogstar 2006-11-08  
加载期动态织入感觉有些动态语言的意思了,呵呵
17 楼 galaxystar 2006-11-08  
还是羡慕你们,我们是做互联网平台的,项目必须严重考虑性能!
否则,硬件上的投入,又要头痛了!
16 楼 partech 2006-11-08  
galaxystar 写道

静态编译期织入,性能上是没有太大损失!运行期比较有考验!
aspectj在jboss应用中也大量使用了动态!
不过与jboss本身有关系!

莫非真的成了!vs ? 

加载期动态织入,性能也没有太大损失啊。
并且有些问题,静态编译是搞不定的,如循环依赖。
15 楼 galaxystar 2006-11-08  
partech 写道
galaxystar 写道
那你能保证无侵入,又高性能?
系统设计上趋于完美,还是个目标!没人做到了!

不过,我还也是非常看好aspect的静态写法的!

你告诉我,加载时植入(LTW)如何影响性能了?



静态编译期织入,性能上是没有太大损失!运行期比较有考验!
aspectj在jboss应用中也大量使用了动态!
不过与jboss本身有关系!
14 楼 liusong1111 2006-11-08  
!与?的世纪之战...
请教一下,declare annotation与APT(annotation process tool)可不可以这样理解:前者是工程化的代码加强,后者是底层化的代码生成?一个纵向,一个横向?

13 楼 partech 2006-11-08  
galaxystar 写道
那你能保证无侵入,又高性能?
系统设计上趋于完美,还是个目标!没人做到了!

不过,我还也是非常看好aspect的静态写法的!

你告诉我,加载时植入(LTW)如何影响性能了?
12 楼 galaxystar 2006-11-08  
那你能保证无侵入,又高性能?
系统设计上趋于完美,还是个目标!没人做到了!

不过,我还也是非常看好aspect的静态写法的!
11 楼 partech 2006-11-08  
galaxystar 写道
当系统变得完美,往往会付出相等的代价!比如性能

这话说得,难道性能是完美之外的事情?
10 楼 galaxystar 2006-11-08  
当系统变得完美,往往会付出相等的代价!比如性能
9 楼 partech 2006-11-08  
比如:
aspect persistence {

declare @type : org.springside.bookstore.commons.model..* &&
                !(org.springside.bookstore.commons.model.OrderItem): @Entity;
...
}
8 楼 edgeloner 2006-11-08  
对老百姓好才是真的好。
劳民伤财的都不好。
java很多劳民伤财的地方,
7 楼 Feiing 2006-11-08  
Allen 写道
Feiing 写道
Annotation, J2EE 衰落的标志?


这个,为什么这样说呢?我入行尚浅,看不太明白……


开玩笑的, 只是我个人看 Annotation 不太舒服
6 楼 Allen 2006-11-08  
Feiing 写道
Annotation, J2EE 衰落的标志?


这个,为什么这样说呢?我入行尚浅,看不太明白……
5 楼 Feiing 2006-11-08  
呵呵, partech 兄如此推崇 aspectj, 有时间一定研究下

另, partech 是否有兴趣描述一些 aspectj 的具体应用让我等长长见识?
4 楼 kent 2006-11-08  
无非是三种方式:
继承,反射,AOP(此处annotation在某种意义上来说有点像AOP的实现方式)

也许只有动态类型,才能真正的无侵入
可是动态类型又带来了一系列新的问题
java可能永远也不支持动态类型



3 楼 江南白衣 2006-11-08  
看来这个declare annotation是不看不行了。哪里有讲这个比较好的文档?
2 楼 partech 2006-11-08  
Feiing 写道
Annotation, J2EE 衰落的标志?

基于Aspect的Declare Annotation,才能做到彻底的无侵入。AO复兴的标志?
1 楼 Feiing 2006-11-08  
Annotation, J2EE 衰落的标志?

相关推荐

    java annotation 手册.doc

    定义注解类型时,使用 `@interface` 关键字,并可以包含成员(无参数的方法,表示注解的属性)以及默认值。 ```java public @interface MyAnnotation { String name() default "defaultName"; int value() ...

    annotation-log

    Annotation,源自Java语言,是一种元数据,它提供了一种安全且非侵入的方式来关联信息与代码元素,如类、方法或变量。这些元数据可以被编译器或运行时环境用来进行代码分析、验证或者自动生成代码。例如,Spring框架...

    JDK5.0-Java Annotation 介绍

    Java Annotation(注解)是自JDK 5.0开始引入的一种元数据,它提供了一种安全、非侵入式的方式来向编译器、虚拟机或者其他的工具提供关于代码的信息。这种信息可以用来进行编译时检查、运行时处理、代码生成等。注解...

    运用javassist和annotation修改class的特定method的class byte code

    通过这种方式,我们可以在不侵入原始代码的情况下,灵活地扩展或修改类的行为。同时,由于注解的存在,这种修改可以更加有针对性,只针对具有特定标记的方法执行。 总之,Javaassist结合注解提供了一种强大的工具,...

    Hydra架构介绍1

    Google 针对自己的分布式跟踪系统 Dapper 在生产环境下运行两年多时间积累的经验,在论文中重点提到了分布式跟踪系统对业务系统的零侵入这个先天优势,并总结了大量的应用场景,还提及它的不足之处。 领域模型...

    Java动态代理自建注解

    在Java编程中,动态代理是一种强大的工具,它允许...这种方式具有很高的灵活性,可以应用于多种场景,如日志记录、性能监控、权限控制等,而且不侵入原始业务逻辑。理解并掌握这一技术对于提升Java开发能力非常有帮助。

    android 仿ios侧滑返回 注解式完美实现

    这样做的优点是减少了代码侵入性,使得Activity代码更加简洁。 为了进一步优化,我们还可以考虑以下几点: - 支持自定义滑动敏感度和边缘宽度。 - 处理屏幕旋转和其他生命周期事件的影响。 - 考虑与现有的导航组件...

    starterDemo.rar

    public @interface CustomAnnotation { String value() default ""; } ``` 在这里,`@Retention(RetentionPolicy.RUNTIME)` 指定了该注解将在运行时保留,`@Target(ElementType.METHOD)` 表示这个注解可以应用于...

    ssh注解资料

    注解的本质是提供了一种安全、非侵入式的机制来添加元数据到代码中。Java提供了三种类型的注解:源码注解、类型注解和运行时注解。源码注解主要供编译器使用,类型注解则用于类型系统,而运行时注解可以在程序运行...

    注解是什么1

    1. **非侵入性**:注解不会改变程序的基本结构和执行逻辑,它仅仅是添加额外的元信息。这使得注解成为一种理想的工具,用于在不修改代码主体的情况下添加扩展功能。 2. **可读性**:虽然注解的主要目的是供机器解析...

    Spring2.5的新特性

    这些新特性包括:注解驱动的依赖性注入(annotation-driven dependency injection),使用注解而非XML元数据来自动侦测classpath上的Spring组件,注解对生命周期方法的支持,一个新的web控制器模型将请求映射到加...

    Spring aop 记录操作日志 Aspect 源码

    在IT行业中,Spring AOP(面向切面编程)是一种强大的工具,它允许我们在代码中实现横切关注点,如日志记录、权限控制等,而无需侵入业务逻辑。本篇将深入探讨如何使用Spring AOP来记录操作日志,并通过自定义Aspect...

    SpringMVC利用AOP实现自定义注解记录日志

    总结,Spring MVC结合AOP和自定义注解可以方便地实现日志记录功能,无需侵入业务代码。这种方法具有良好的可扩展性和灵活性,可以轻松适应不同场景的日志需求。同时,通过调整切面的定义,我们可以控制日志记录的...

    spring自定义切面实例

    通过合理的切点定义和切面类设计,我们能够在不侵入业务逻辑的前提下,轻松地添加额外的功能,如日志记录、性能监控等。这不仅提高了代码的可维护性和可读性,还增强了系统的灵活性和可扩展性。

    spring-boot-mybatis-plus数据层框架

    - **无侵入性**:引入MyBatis-Plus不会对现有项目造成任何影响,保证了项目的平滑过渡。 - **损耗小**:启动时自动注入基本的CRUD操作,几乎不会带来额外的性能损耗,使得开发过程更加直观。 - **强大的CRUD操作**:...

    Dubbo服务框架 v2.7.9-源码.zip

    3. **面向接口代理**:Dubbo支持基于Java的动态代理,实现了服务的无侵入性。 4. **服务自动注册与发现**:服务提供者启动时自动向注册中心注册,服务消费者通过注册中心获取服务提供者的地址。 5. **负载均衡**:...

    spring - aop.zip

    总结起来,Spring AOP为开发者提供了强大的功能,可以在不侵入原有业务逻辑的情况下添加横切关注点,提高了代码的复用性和可维护性。通过理解并熟练掌握切面、通知、连接点、切入点和织入这些核心概念,可以有效地...

    Spring系列面试题129道(附答案解析)

    - 轻量级和最小侵入性:Spring是轻量级的,对业务对象的影响最小。 - 依赖注入(DI)支持:Spring通过控制反转(IoC)支持将对象之间的依赖关系通过配置文件或注解来管理。 - 面向切面编程(AOP):Spring支持面向切...

    Spring AOP与动态代理

    总结来说,Spring AOP通过动态代理机制实现了对代码的无侵入式增强,使得我们能够更灵活地管理横切关注点,提升了代码的复用性和模块化。无论是JDK动态代理还是CGLIB动态代理,它们都是Spring AOP实现其功能的关键...

    整理后java开发全套达内学习笔记(含练习)

    Annotation [java] 代码注释 [ænәu'teiʃәn] anonymous adj.匿名的[ә'nɒnimәs]'(反义:directly adv.直接地,立即[di'rektli, dai'rektli]) apply v.应用,适用 [ә'plai] application n.应用,应用程序 [,æ...

Global site tag (gtag.js) - Google Analytics