ï»??xml version="1.0" encoding="utf-8" standalone="yes"?>日韩一区二区在线免费,久久国产视频网,亚洲国产不卡http://www.aygfsteel.com/masen/category/54669.htmlzh-cnTue, 03 Feb 2015 00:32:54 GMTTue, 03 Feb 2015 00:32:54 GMT60Java 创徏对象方式http://www.aygfsteel.com/masen/articles/422168.htmlMasenMasenSat, 10 Jan 2015 14:42:00 GMThttp://www.aygfsteel.com/masen/articles/422168.htmlhttp://www.aygfsteel.com/masen/comments/422168.htmlhttp://www.aygfsteel.com/masen/articles/422168.html#Feedback0http://www.aygfsteel.com/masen/comments/commentRss/422168.htmlhttp://www.aygfsteel.com/masen/services/trackbacks/422168.htmlJava 创徏对象方式åQ?br />
    ●  ç”¨new语句创徏对象
    ●  ˜qç”¨åå°„手段,调用java.lang.Class 或è€?java.lang.reflect.Constructor ¾cȝš„newInstance()实例æ–ÒŽ³•
    ●  è°ƒç”¨å¯¹è±¡çš„clone()æ–ÒŽ³•
    ●  ˜qç”¨åºåˆ—化手ŒD?调用java.io.ObjectInputStream 对象çš?readObject()æ–ÒŽ³•.

分别创徏100万个javaBean åQŒæ€§èƒ½å¦‚下åQ?br />

//new : 46,47,47,62,47
//clone : 171,188,172,,157,172
//getClass().newInstance() : 140,141,141,,157,172
//Class.forName and newInstance : 1765,1781,1813,1797,1781
//Proxy.newProxyInstance : 2984
//Serializable : 60422

另外‹¹‹è¯•了Field å’?Method 执行效率åQ?br />
//method : 1406
//feild : 1360 getField("")得到实例和父¾cȝš„“公共”属æ€?span style="white-space:pre">
//getDeclaredField() 得到实例的指定属æ€?Public,protected,dfault,pivate),不包括父¾cÕd±žæ€?/div>
//getFields()˜q”回field数组åQ?得到实例 å’?父类 的所æœ? “公共”属æ€?br />
动态代理:
JDKåQšjdk1.7.0_02 
CGLIBåQšå’Œspring2.0.6 使用同样的cglib-nodep-2.1_3.jar 
CPUåQšP8400 2.53GHz 2.53GHz 
‹¹‹è¯•¾l“æžœ4åQ?nbsp;
Create JDK Proxy: 43 ms 
Create CGLIB Proxy: 129 ms
Run JDK Proxy: 940 ms, 1,500,069 t/s
Run CGLIB Proxy: 299 ms, 4,715,937 t/s
CGLIB创徏代理对象速度大概比JDK Proxy�倍,执行速度是JDK Proxy�倍以�/span>

区别åQ?br />如果一个目标对象如果实çŽîCº†æŽ¥å£Spring则会选择JDK动态代理策略动态的创徏一个接口实现类åQˆåŠ¨æ€ä»£ç†ç±»åQ‰æ¥ä»£ç†ç›®æ ‡å¯¹è±¡åQŒå¯ä»¥é€šä¿—的理解这个动态代理类是目标对象的另外一个版本,所以这两者之间在强制转换的时候会抛出java.lang.ClassCastException。而所以在默认情况下,如果目标对象没有实现ä»ÖM½•接口åQŒSpring会选择CGLIB代理åQ?其生成的动态代理对象是目标¾cȝš„子类ã€?/span>
spring 配置实用cglib动态代ç?br /> proxy-target-class 属性设为true æˆ?nbsp;<aop:aspectj-autoproxy proxy-target-class="true"/>


]]>
java 注解 (转infoq.com)http://www.aygfsteel.com/masen/articles/422089.htmlMasenMasenTue, 06 Jan 2015 09:54:00 GMThttp://www.aygfsteel.com/masen/articles/422089.htmlhttp://www.aygfsteel.com/masen/comments/422089.htmlhttp://www.aygfsteel.com/masen/articles/422089.html#Feedback0http://www.aygfsteel.com/masen/comments/commentRss/422089.htmlhttp://www.aygfsteel.com/masen/services/trackbacks/422089.html在开发Java½E‹åºåQŒå°¤å…¶æ˜¯Java EE应用的时候,æ€ÀL˜¯å…ä¸äº†ä¸Žå„种配置文äšg打交道。以Java EE中典型的S(pring)S(truts)H(ibernate)架构来说åQ?a style="text-decoration: none; color: #286ab2; outline: none !important; margin: 0px; border: 0px; padding: 0px;">Springã€?a style="text-decoration: none; color: #286ab2; outline: none !important; margin: 0px; border: 0px; padding: 0px;">Strutså’?a style="text-decoration: none; color: #286ab2; outline: none !important; margin: 0px; border: 0px; padding: 0px;">Hibernate˜q™ä¸‰ä¸ªæ¡†æž‰™ƒ½æœ‰è‡ªå·Þqš„XML格式的配¾|®æ–‡ä»¶ã€‚这些配¾|®æ–‡ä»‰™œ€è¦ä¸ŽJava源代码保存同步,否则的话ž®±å¯èƒ½å‡ºçŽ°é”™è¯¯ã€‚è€Œä¸”˜q™äº›é”™è¯¯æœ‰å¯èƒ½åˆ°äº†è¿è¡Œæ—¶åˆÀL‰è¢«å‘现。把同一份信息保存在两个地方åQŒæ€ÀL˜¯ä¸ªåçš„主意。理想的情况是在一个地方维护这些信息就好了。其它部分所需的信息则通过自动的方式来生成。JDK 5中引入了源代码中的注解(annotationåQ‰è¿™ä¸€æœºåˆ¶ã€‚注解ä‹Éå¾—Java源代码中不但可以包含功能性的实现代码åQŒè¿˜å¯ä»¥æ·ÕdŠ å…ƒæ•°æ®ã€‚æ³¨è§£çš„åŠŸèƒ½¾cÖM¼¼äºŽä»£ç ä¸­çš„æ³¨é‡Šï¼Œæ‰€ä¸åŒçš„æ˜¯æ³¨è§£ä¸æ˜¯æä¾›ä»£ç åŠŸèƒ½çš„è¯´æ˜Žï¼Œè€Œæ˜¯å®žçŽ°½E‹åºåŠŸèƒ½çš„é‡è¦ç»„æˆéƒ¨åˆ†ã€‚Java注解已经在很多框架中得到了广泛的使用åQŒç”¨æ¥ç®€åŒ–程序中的配¾|®ã€?/p>

使用注解

在一般的Java开发中åQŒæœ€å¸¸æŽ¥è§¦åˆ°çš„可能就æ˜?a style="text-decoration: none; color: #286ab2; outline: none !important; margin: 0px; border: 0px; padding: 0px;">@Overrideå’?a style="text-decoration: none; color: #286ab2; outline: none !important; margin: 0px; border: 0px; padding: 0px;">@SupressWarnings˜q™ä¸¤ä¸ªæ³¨è§£äº†ã€‚ä‹É用@Override的时候只需要一个简单的声明卛_¯ã€‚è¿™¿Uç§°ä¸ºæ ‡è®°æ³¨è§£ï¼ˆmarker annotation åQ‰ï¼Œå®ƒçš„出现ž®×ƒ»£è¡¨äº†æŸç§é…ç½®è¯­ä¹‰ã€‚而其它的注解是可以有自己的配¾|®å‚数的。配¾|®å‚æ•îC»¥åå€¼å¯¹çš„æ–¹å¼å‡ºçŽ°ã€‚ä‹Éç”?@SupressWarnings的时候需要类似@SupressWarnings({"uncheck", "unused"})˜q™æ ·çš„语法。在括号里面的是该注解可供配¾|®çš„倹{€‚由于这个注解只有一个配¾|®å‚敎ͼŒè¯¥å‚数的名称默认为valueåQŒåƈ且可以省略。而花括号则表½Cºæ˜¯æ•°ç»„¾cÕdž‹ã€‚在JPA中的@Table注解使用¾cÖM¼¼@Table(name = "Customer", schema = "APP")˜q™æ ·çš„语法。从˜q™é‡Œå¯ä»¥çœ‹åˆ°åå€¼å¯¹çš„用法。在使用注解时候的配置参数的值必™åÀL˜¯¾~–译时刻的常量ã€?/p>

从某¿Uè§’度来è¯ß_¼Œå¯ä»¥æŠŠæ³¨è§£çœ‹æˆæ˜¯ä¸€ä¸ªXML元素åQŒè¯¥å…ƒç´ å¯ä»¥æœ‰ä¸åŒçš„预定义的属性。而属性的值是可以在声明该元素的时候自行指定的。在代码中ä‹É用注解,ž®Þq›¸å½“于把一部分元数据从XMLæ–‡äšg¿UÕdˆ°äº†ä»£ç æœ¬íw«ä¹‹ä¸­ï¼Œåœ¨ä¸€ä¸ªåœ°æ–¹ç®¡ç†å’Œ¾l´æŠ¤ã€?/p>

开发注�/h2>

在一般的开发中åQŒåªéœ€è¦é€šè¿‡é˜…读相关的API文档来了解每个注解的配置参数的含义,òq¶åœ¨ä»£ç ä¸­æ­£¼‹®ä‹É用即可。在有些情况下,可能会需要开发自å·Þqš„æ³¨è§£ã€‚这在库的开发中比较常见。注解的定义有点¾cÖM¼¼æŽ¥å£ã€‚下面的代码¾l™å‡ºäº†ä¸€ä¸ªç®€å•的描述代码分工安排的注解。通过该注解可以在源代码中记录每个¾cÀLˆ–接口的分工和˜q›åº¦æƒ…况ã€?br />

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Assignment {
    String assignee();
    int effort();
    double finished() default 0;
} 

@interface用来声明一个注解,其中的每一个方法实际上是声明了一个配¾|®å‚数。方法的名称ž®±æ˜¯å‚数的名¿UŽÍ¼Œ˜q”回值类型就是参数的¾cÕdž‹ã€‚可以通过default来声明参数的默认倹{€‚在˜q™é‡Œå¯ä»¥çœ‹åˆ°@Retentionå’?a style="text-decoration: none; color: #286ab2; margin: 0px; border: 0px; padding: 0px; outline: none !important;">@Target˜q™æ ·çš„元注解åQŒç”¨æ¥å£°æ˜Žæ³¨è§£æœ¬íw«çš„è¡ŒäØ“ã€‚@Retention用来声明注解的保留策略,æœ?a style="text-decoration: none; color: #286ab2; margin: 0px; border: 0px; padding: 0px; outline: none !important;">CLASSã€?a style="text-decoration: none; color: #286ab2; margin: 0px; border: 0px; padding: 0px; outline: none !important;">RUNTIMEå’?a style="text-decoration: none; color: #286ab2; margin: 0px; border: 0px; padding: 0px; outline: none !important;">SOURCE˜q™ä¸‰¿Uï¼Œåˆ†åˆ«è¡¨ç¤ºæ³¨è§£ä¿å­˜åœ¨ç±»æ–‡äšg、JVM˜qè¡Œæ—¶åˆ»å’Œæºä»£ç ä¸­ã€‚只有当声明为RUNTIME的时候,才能够在˜qè¡Œæ—¶åˆ»é€šè¿‡åå°„API来获取到注解的信息。@Target用来声明注解可以被添加在哪些¾cÕdž‹çš„元素上åQŒå¦‚¾cÕdž‹ã€æ–¹æ³•和域等ã€?/p>

在程序中æ·ÕdŠ çš„æ³¨è§£ï¼Œå¯ä»¥åœ¨ç¼–è¯‘æ—¶åˆÀLˆ–是运行时åˆÀL¥˜q›è¡Œå¤„理。在¾~–译时刻处理的时候,是分成多­‘Ÿæ¥˜q›è¡Œçš„。如果在某趟处理中äñ”生了新的Java源文ä»Óž¼Œé‚£ä¹ˆž®±éœ€è¦å¦å¤–一­‘Ÿå¤„理来处理新生成的源文件。如此往复,直到没有新文件被生成为止。在完成处理之后åQŒå†å¯¹Java代码˜q›è¡Œ¾~–译。JDK 5中提供了apt工具用来å¯Ò޳¨è§£è¿›è¡Œå¤„理。apt是一个命令行工具åQŒä¸Žä¹‹é…å¥—çš„˜q˜æœ‰ä¸€å¥—用来描˜q°ç¨‹åºè¯­ä¹‰ç»“构的Mirror API。Mirror APIåQˆcom.sun.mirror.*åQ‰æ˜q°çš„æ˜¯ç¨‹åºåœ¨¾~–译时刻的静态结构。通过Mirror API可以获取到被注解的Java¾cÕdž‹å…ƒç´ çš„信息,从而提供相应的处理逻辑。具体的处理工作交给apt工具来完成。编写注解处理器的核心是AnnotationProcessorFactoryå’?a style="text-decoration: none; color: #286ab2; outline: none !important; margin: 0px; border: 0px; padding: 0px;">AnnotationProcessor两个接口。后者表½Cºçš„æ˜¯æ³¨è§£å¤„理器åQŒè€Œå‰è€…åˆ™æ˜¯äØ“æŸäº›æ³¨è§£¾cÕdž‹åˆ›å¾æ³¨è§£å¤„理器的工厂ã€?/p>

以上面的注解Assignmentä¸ÞZ¾‹åQŒå½“每个开发äh员都在源代码中更新进度的话,ž®±å¯ä»¥é€šè¿‡ä¸€ä¸ªæ³¨è§£å¤„理器来生成一个项目整体进度的报告ã€?首先是注解处理器工厂的实现ã€?br />

public class AssignmentApf implements AnnotationProcessorFactory {  
    public AnnotationProcessor getProcessorFor(Set<AnnotationTypeDeclaration> atds,? AnnotationProcessorEnvironment env) {
        if (atds.isEmpty()) {
           return AnnotationProcessors.NO_OP;
        }
        return new AssignmentAp(env); //˜q”回注解处理å™?
    } 
    public Collection<String> supportedAnnotationTypes() {
        return Collections.unmodifiableList(Arrays.asList("annotation.Assignment"));
    }
    public Collection<String> supportedOptions() {
        return Collections.emptySet();
    }
}


 

AnnotationProcessorFactory接口有三个方法:getProcessorFor是根据注解的¾cÕdž‹æ¥è¿”回特定的注解处理器;supportedAnnotationTypes是返回该工厂生成的注解处理器所能支持的注解¾cÕdž‹åQ›supportedOptions用来表示所支持的附加选项。在˜qè¡Œapt命ä×o行工å…ïLš„æ—¶å€™ï¼Œå¯ä»¥é€šè¿‡-A来传递额外的参数¾l™æ³¨è§£å¤„理器åQŒå¦‚-Averbose=true。当工厂通过 supportedOptionsæ–ÒŽ³•声明了所能识别的附加选项之后åQŒæ³¨è§£å¤„理器ž®±å¯ä»¥åœ¨˜qè¡Œæ—¶åˆ»é€šè¿‡AnnotationProcessorEnvironmentçš„getOptionsæ–ÒŽ³•获取到选项的实际倹{€‚注解处理器本èín的基本实现如下所½Cºã€?br />

public class AssignmentAp implements AnnotationProcessor { 
    private AnnotationProcessorEnvironment env;
    private AnnotationTypeDeclaration assignmentDeclaration;
    public AssignmentAp(AnnotationProcessorEnvironment env) {
        this.env = env;
        assignmentDeclaration = (AnnotationTypeDeclaration) env.getTypeDeclaration("annotation.Assignment");
    }
    public void process() {
        Collection<Declaration> declarations = env.getDeclarationsAnnotatedWith(assignmentDeclaration);
        for (Declaration declaration : declarations) {
           processAssignmentAnnotations(declaration);
        }
    }
    private void processAssignmentAnnotations(Declaration declaration) {
        Collection<AnnotationMirror> annotations = declaration.getAnnotationMirrors();
        for (AnnotationMirror mirror : annotations) {
            if (mirror.getAnnotationType().getDeclaration().equals(assignmentDeclaration)) {
                Map<AnnotationTypeElementDeclaration, AnnotationValue> values = mirror.getElementValues();
                String assignee = (String) getAnnotationValue(values, "assignee"); //获取注解的�
            }
        }
    }   
} 



注解处理器的处理逻辑都在processæ–ÒŽ³•中完成。通过一个声明(DeclarationåQ‰çš„getAnnotationMirrorsæ–ÒŽ³•ž®±å¯ä»¥èŽ·å–åˆ°è¯¥å£°æ˜Žä¸Šæ‰€æ·ÕdŠ çš„æ³¨è§£çš„å®žé™…å€¹{€‚得到这些å€ég¹‹åŽï¼Œå¤„理èµäh¥ž®×ƒ¸éš¾äº†ã€?/p>

在创建好注解处理器之后,ž®±å¯ä»¥é€šè¿‡apt命ä×o行工å…äh¥å¯ÒŽºä»£ç ä¸­çš„æ³¨è§£˜q›è¡Œå¤„理ã€?命ä×o的运行格式是apt -classpath bin -factory annotation.apt.AssignmentApf src/annotation/work/*.javaåQŒå³é€šè¿‡-factory来指定注解处理器工厂¾cȝš„名称。实际上åQŒapt工具在完成处理之后,会自动调用javac来编译处理完成后的源代码ã€?/p>

JDK 5中的apt工具的不­‘³ä¹‹å¤„在于它是Oracle提供的私有实现。在JDK 6中,通过JSR 269把自定义注解处理器这一功能˜q›è¡Œäº†è§„范化åQŒæœ‰äº†æ–°çš?a style="text-decoration: none; color: #286ab2; outline: none !important; margin: 0px; border: 0px; padding: 0px;">javax.annotation.processing˜q™ä¸ªæ–°çš„API。对Mirror API也进行了更新åQŒåŞ成了新的javax.lang.model包。注解处理器的ä‹É用也˜q›è¡Œäº†ç®€åŒ–,不需要再单独˜qè¡Œapt˜q™æ ·çš„命令行工具åQŒJava¾~–译器本íw«å°±å¯ä»¥å®Œæˆå¯Ò޳¨è§£çš„处理。对于同æ ïLš„功能åQŒå¦‚果用JSR 269的做法,只需要一个类ž®±å¯ä»¥äº†ã€?br />

@SupportedSourceVersion(SourceVersion.RELEASE_6)
@SupportedAnnotationTypes("annotation.Assignment")
public class AssignmentProcess extends AbstractProcessor {
    private TypeElement assignmentElement; 
    public synchronized void init(ProcessingEnvironment processingEnv) {
        super.init(processingEnv);
        Elements elementUtils = processingEnv.getElementUtils();
        assignmentElement = elementUtils.getTypeElement("annotation.Assignment");
    } 
    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
        Set<? extends Element> elements = roundEnv.getElementsAnnotatedWith(assignmentElement);
        for (Element element : elements) {
            processAssignment(element);
        }
    }
    private void processAssignment(Element element) {
        List<? extends AnnotationMirror> annotations = element.getAnnotationMirrors();
        for (AnnotationMirror mirror : annotations) {
            if (mirror.getAnnotationType().asElement().equals(assignmentElement)) {
                Map<? extends ExecutableElement, ? extends AnnotationValue> values = mirror.getElementValues();
                String assignee = (String) getAnnotationValue(values, "assignee"); //获取注解的�
            }
        }
    } 
} 



仔细比较上面两段代码åQŒå¯ä»¥å‘现它们的基本¾l“构是类似的。不同之处在于JDK 6中通过元注è§?a style="text-decoration: none; color: #286ab2; outline: none !important; margin: 0px; border: 0px; padding: 0px;">@SupportedAnnotationTypes来声明所支持的注解类型。另外描˜q°ç¨‹åºé™æ€ç»“构的javax.lang.model包ä‹É用了不同的类型名¿U°ã€‚ä‹É用的时候也更加½Ž€å•,只需要通过javac -processor annotation.pap.AssignmentProcess Demo1.java˜q™æ ·çš„æ–¹å¼å³å¯ã€?/p>

上面介绍的这两种做法都是在编译时刻进行处理的。而有些时候则需要在˜qè¡Œæ—¶åˆ»æ¥å®Œæˆå¯¹æ³¨è§£çš„处理。这个时候就需要用到Java的反ž®„API。反ž®„API提供了在˜qè¡Œæ—¶åˆ»è¯Õd–注解信息的支持。不˜q‡å‰ææ˜¯æ³¨è§£çš„保留策略声明的是运行时。Java反射APIçš?a style="text-decoration: none; color: #286ab2; outline: none !important; margin: 0px; border: 0px; padding: 0px;">AnnotatedElement接口提供了获取类、方法和域上的注解的实用æ–ÒŽ³•。比如获取到一个Class¾cÕd¯¹è±¡ä¹‹åŽï¼Œé€šè¿‡getAnnotationæ–ÒŽ³•ž®±å¯ä»¥èŽ·å–åˆ°è¯¥ç±»ä¸Šæ·»åŠ çš„æŒ‡å®šæ³¨è§£¾cÕdž‹çš„æ³¨è§£ã€?/p>

实例分析

下面通过一个具体的实例来分析说明在实践中如何来使用和处理注解。假定有一个公司的雇员信息¾pȝ»ŸåQŒä»Žè®‰K—®æŽ§åˆ¶çš„角度出发,寚w›‡å‘˜çš„工资的更新只能由å…ähœ‰ç‰¹å®šè§’色的用æˆäh‰èƒ½å®Œæˆã€‚考虑到访问控刉™œ€æ±‚的普遍性,可以定义一个注解来让开发äh员方便的在代码中声明讉K—®æŽ§åˆ¶æƒé™ã€?br />
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface RequiredRoles
{ String[] value(); } 

下一步则是如何对注解˜q›è¡Œå¤„理åQŒè¿™é‡Œä‹É用的Java的反ž®„APIòq¶ç»“å?a style="text-decoration: none; color: #286ab2; outline: none !important; margin: 0px; border: 0px; padding: 0px;">动态代ç?/a>。下面是动态代理中的InvocationHandler接口的实现ã€?br />

public class AccessInvocationHandler<T> implements InvocationHandler {
    final T accessObj;
    public AccessInvocationHandler(T accessObj) {
        this.accessObj = accessObj;
    }
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        RequiredRoles annotation = method.getAnnotation(RequiredRoles.class); //通过反射API获取注解
        if (annotation != null) {
            String[] roles = annotation.value();
            String role = AccessControl.getCurrentRole();
            if (!Arrays.asList(roles).contains(role)) {
                throw new AccessControlException("The user is not allowed to invoke this method.");
            }
        }
        return method.invoke(accessObj, args);
    } 
}


在具体ä‹É用的时候,首先要通过Proxy.newProxyInstanceæ–ÒŽ³•创徏一个EmployeeGateway的接口的代理¾c»ï¼Œä½¿ç”¨è¯¥ä»£ç†ç±»æ¥å®Œæˆå®žé™…的操作ã€?/p>

]]>
Ö÷Õ¾Ö©Öë³ØÄ£°å£º Ð˰²ÏØ| ¾ÅÁú³ÇÇø| ÄþÃ÷ÏØ| áÓÖÝÊÐ| º×ɽÊÐ| ¹ãÈÄÏØ| ÀÖÖÁÏØ| ¼ªÄ¾ÄËÏØ| ±õº£ÏØ| ÄϽ­ÏØ| ̨½­ÏØ| ¸ßÇå| »Ý°²ÏØ| ÕÄÆÖÏØ| µÂÖÝÊÐ| »ÆÆ½ÏØ| °²Â½ÊÐ| ²©°×ÏØ| ³¤É³ÏØ| ·ïÉ½ÏØ| ÀöË®ÊÐ| º¼½õºóÆì| È«½·ÏØ| ÎäÇåÇø| Îä¹¦ÏØ| ¾£ÃÅÊÐ| °¢À­ÉÆÓÒÆì| ½­Ô´ÏØ| °²»ÕÊ¡| Áô°ÓÏØ| ¶õÍÐ¿ËÆì| ʯÆÁÏØ| ´ó¸ÛÇø| ³¤·áÏØ| ±Ï½ÚÊÐ| ÄÇÇúÏØ| ÆÁ¶«ÏØ| »Ý°²ÏØ| ÄϲýÏØ| äê´¨ÏØ| Á°Ô´ÊÐ|