下面进一步深入分析Java注解的机制。
一、为什么使用Annotation:
在JAVA应用中,我们常遇到一些需要使用模版代码。例如,为了编写一个JAX-RPC web service,我们必须提供一对接口和实现作为模版代码。如果使用annotation对远程访问的方法代码进行修饰的话,这个模版就能够使用工具自动生成。
另外,一些API需要使用与程序代码同时维护的附属文件。例如,JavaBeans需要一个BeanInfo Class与一个Bean同时使用/维护,而EJB则同样需要一个部署描述符。此时在程序中使用annotation来维护这些附属文件的信息将十分便利而且减少了错误。
二、Annotation工作方式:
在5.0版之前的Java平台已经具有了一些ad hocannotation机制。比如,使用transient修饰符来标识一个成员变量在序列化子系统中应被忽略。而@deprecated这个javadoc tag也是一个ad hocannotation用来说明一个方法已过时。从Java5.0版发布以来,
5.0平台提供了一个正式的annotation功能:允许开发者定义、使用自己的annoatation类型。此功能由一个定义annotation类型的语法和一个描述annotation声明的语法,读取annotaion的API,一个使用annotation修饰的class文件,一个annotation处理工具(apt)组成。
annotation并不直接影响代码语义,但是它能够工作的方式被看作类似程序的工具或者类库,它会反过来对正在运行的程序语义有所影响。annotation可以从源文件、class文件或者以在运行时反射的多种方式被读取。
当然annotation在某种程度上使javadoc tag更加完整。一般情况下,如果这个标记对java文档产生影响或者用于生成java文档的话,它应该作为一个javadoc tag;否则将作为一个annotation。
三、Annotation使用方法: 1、类型声明方式:
通常,应用程序并不是必须定义annotation类型,但是定义annotation类型并非难事。Annotation类型声明于一般的接口声明极为类似,区别只在于它在interface关键字前面使用“@”符号。
annotation类型的每个方法声明定义了一个annotation类型成员,但方法声明不必有参数或者异常声明;方法返回值的类型被限制在以下的范围:primitives、String、Class、enums、annotation和前面类型的数组;方法可以有默认值。
下面是一个简单的annotation类型声明:
清单1:
/**
* Describes the Request-For-Enhancement(RFE) that led
* to the presence of the annotated API element.
*/
public @interface RequestForEnhancement {
int id();
String synopsis();
String engineer() default "[unassigned]";
String date(); default "[unimplemented]";
}
代码中只定义了一个annotation类型RequestForEnhancement。 2、修饰方法的annotation声明方式: annotation是一种修饰符,能够如其它修饰符(如public、static、final)一般使用。习惯用法是annotaions用在其它的修饰符前面。annotations由“@+annotation类型+带有括号的成员-值列表”组成。这些成员的值必须是编译时常量(即在运行时不变)。 A:下面是一个使用了RequestForEnhancement annotation的方法声明: 清单2:
@RequestForEnhancement(
id = 2868724,
synopsis = "Enable time-travel",
engineer = "Mr. Peabody",
date = "4/1/3007"
)
public static void travelThroughTime(Date destination) { ... }
B:当声明一个没有成员的annotation类型声明时,可使用以下方式:
清单3:
/**
* Indicates that the specification of the annotated API element
* is preliminary and subject to change.
*/
public @interface Preliminary { }
作为上面没有成员的annotation类型声明的简写方式:
清单4:
@Preliminary public class TimeTravel { ... }
C:
如果在annotations中只有唯一一个成员,则该成员应命名为value:
清单5:
/**
* Associates a copyright notice with the annotated API element.
*/
public @interface Copyright {
String value();
}
更为方便的是对于具有唯一成员且成员名为value的annotation(如上文),在其使用时可以忽略掉成员名和赋值号(=):
清单6:
@Copyright("2002 Yoyodyne Propulsion Systems")
public class OscillationOverthruster { ... }
D:下面是一个复杂的Annotataion类型声明,其成员是Annotation类型的数组
import java.lang.annotation.*;
/**
* Reviews annotation类型只有一个成员,
* 由Review annotation组成的数组
*/
@Retention(RetentionPolicy.RUNTIME)
public @interface Reviews {
Review[] value();
}
/**
* Review annotation类型有3个成员:
* 枚举类型成员grade
* 表示Review名称的字符串类型成员Reviewer
* 具有默认值的字符串类型成员Comment。
*/
public @interface Review {
// 内嵌的枚举类型
public static enum Grade { EXCELLENT, SATISFACTORY, UNSATISFACTORY };
// 下面的方法定义了annotation的成员
Grade grade();
String reviewer();
String comment() default "";
}
Reviews annotation类型只有一个成员,但是这个成员的类型是复杂的:由Review annotation组成的数组。Review annotation类型有3个成员:枚举类型成员grade、表示Review名称的字符串类型成员Reviewer、具有默认值的字符串类型成员Comment。
Annotation类型的成员不能是generic。只有返回值类型是Class的方法可以在annotation类型中使用generic,因为此方法能够用类转换将各种类型转换为Class。
最后,我们来定义一个annotation方法用于罗列出类运行中所有的unchecked异常(这种情况不一定是错误)。这个annotation类型将一个数组作为了唯一的成员。数组中的每个元素都是异常类。为了加强对未检查的异常(此类异常都是在运行时抛出)进行报告,我们可以在代码中对异常的类型进行限制:
public @interface UncheckedExceptions {
Class[] value();
}
3、一个使用实例:
结合上面所讲的,我们在这里建立一个简单的基于annotation测试框架。首先我们需要一个annotation类型来表示某个方法是一个应该被测试工具运行的测试方法。
清单7:
import java.lang.annotation.*;
/**
* Indicates that the annotated method is a test method.
* This annotation should be used only on parameterless static methods.
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Test { }
值得注意的是annotaion类型声明是可以标注自己的,这样的annotation被称为“meta-annotations”。
在上面的代码中,@Retention(RetentionPolicy.RUNTIME)这个meta-annotation表示了此类型的annotation将被虚拟机保留使其能够在运行时通过反射被读取。而@Target(ElementType.METHOD)表示此类型的annotation只能用于修饰方法声明。
下面是一个简单的程序,其中部分方法被上面的annotation所标注:
清单8:
public class Foo {
@Test public static void m1() { }
public static void m2() { }
@Test public static void m3() {
throw new RuntimeException("Boom");
}
public static void m4() { }
@Test public static void m5() { }
public static void m6() { }
@Test public static void m7() {
throw new RuntimeException("Crash");
}
public static void m8() { }
}
使用测试:
import java.lang.reflect.*;
public class RunTests {
public static void main(String[] args) throws Exception {
int passed = 0, failed = 0;
for (Method m : Class.forName(args[0]).getMethods()) {
if (m.isAnnotationPresent(Test.class)) {
try {
m.invoke(null);
passed++;
} catch (Throwable ex) {
System.out.printf("Test %s failed: %s %n", m, ex.getCause());
failed++;
}
}
}
System.out.printf("Passed: %d, Failed %d%n", passed, failed);
}
}
这个程序从命令行参数中取出类名,并且遍历此类的所有方法,尝试调用其中被上面的测试annotation类型标注过的方法。在此过程中为了找出哪些方法被annotation类型标注过,需要使用反射的方式执行此查询。如果在调用方法时抛出异常,此方法被认为已经失败,并打印一个失败报告。最后,打印运行通过/失败的方法数量。
下面文字表示了如何运行这个基于annotation的测试工具:
清单9:
$ java RunTests Foo
Test public static void Foo.m3() failed: java.lang.RuntimeException: Boom
Test public static void Foo.m7() failed: java.lang.RuntimeException: Crash
Passed: 2, Failed 2
注解在很多框架、类库中有广泛的应用。如JUnit测试框架, Spring, Hibernate, EJB等等。这也是开发人员所常常用到的一种方式。
上面的介绍说明了annotation的使用方法、定义方式、分类。初学者可以通过以上的说明制作简单的annotation程序,但是对于一些高级的annotation应用(例如使用自定义annotation生成javabean映射xml文件)还需要进一步的研究和探讨。同时,annotation运行存在两种方式:运行时、编译时。上文中讨论的都是在运行时的annotation应用,但在编译时的annotation应用还没有涉及,因为编译时的annotation要使用annotation processing tool(APT) 。 annotation本身使用时十分简便。例如一个本地变量可以被一个以NonNull命名的annotation类型所标注,来作为对这个本地变量不能被赋予null值的断言。而我们可以编写与之配套的一个annotation代码分析工具,使用它来对具有前面变量的代码进行解析,并且尝试验证这个断言。当然这些代码并不必自己编写。在JDK安装后,在JDK/bin目录中可以找到名为“apt”的工具,它提供了处理annotation的框架:它启动后扫描源代码中的annotation,并调用我们定义好的annotation处理器完成我们所要完成的工作(比如验证前面例子中的断言)。说到这里,annotation的强大功能似乎可以替代XDoclet这类的工具了,随着我们的深入,大家会更加坚信这一点。 注:详细描述请参看JSR 250规范 http://www.jcp.org/aboutJava/communityprocess/pfd/jsr250/
四、annotation实例分析
1.BRFW(Beaninfo Runtime FrameWork)定义: 本人编写的一个annotation功能演示框架。顾名思义,BRFW就是在运行时取得bean信息的框架。 2.BRFW的功能: A.源代码级annotation :在bean的源代码中使用annotation定义bean的信息; B.运行时获取bean数据 :在运行时分析bean class中的annotation,并将当前bean class中field信息取出,功能类似xdoclet; C.运行时bean数据的xml绑定 :将获得的bean数据构造为xml文件格式展现。熟悉j2ee的朋友知道,这个功能类似JAXP。 3.BRFW框架: BRFW主要包含以下几个类: A.Persistent类 :定义了用于修饰类的固有成员变量的annotation。 B.Exportable类 :定义了用于修饰Class的类型的annotation。 C.ExportToXml类 :核心类,用于完成BRFW的主要功能:将具有Exportable Annotation的bean对象转换为xml格式文本。 D.AddressForTest类 :被A和B修饰过的用于测试目的的地址bean类。其中包含了地址定义所必需的信息:国家、省级、城市、街道、门牌等。 E.ContactBookForTest类 :被A和B修饰过的友人通讯录bean类。其中包含了通讯录所必备的信息:友人姓名、年龄、电话、住址(成员为AddressForTest类型的ArrayList)、备注。需要说明的是电话这个bean成员变量是由字符串类型组成的ArrayList类型。由于朋友的住址可能不唯一,故这里的住址为由AddressForTest类型组成的ArrayList。 从上面的列表中,可以发现A、B用于修饰bean类和其类成员;C主要用于取出bean类的数据并将其作xml绑定,代码中使用了E作为测试类;E中可能包含着多个D。 在了解了这个简单框架后,我们来看一下BRFW的代码吧! 4.BRFW源代码分析: A.Persistent类:
package beaninfoframework;
import java.lang.annotation.*;
/**
* 用于修饰类的成员变量的annotation
* @author jackzhou
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Persistent {
String value() default "";
}
B.Exportable类:
package beaninfoframework;
import java.lang.annotation.*;
/**
* 用于修饰类类型的annotation
* @author jackzhou
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Exportable {
// 名称
String name() default "";
// 描述
String description() default "";
// 省略name和description后,用来保存name值
String value() default "";
}
C.AddressForTest类:
package beaninfoframework;
/**
* 用于测试的地址类
* @author jackzhou
*/
@Exportable("address")
public class AddressForTest {
//国家
@Persistent
private String country = null;
//省级
@Persistent
private String province = null;
//城市
@Persistent
private String city = null;
//街道
@Persistent
private String street = null;
//门牌
@Persistent
private String doorplate = null;
public AddressForTest(String country, String province,
String city, String street, String doorplate) {
this.country = country;
this.province = province;
this.city = city;
this.street = street;
this.doorplate = doorplate;
}
}
D.ContactBookForTest类:
package beaninfoframework;
import java.util.ArrayList;
/**
* 用于测试的友人通讯录类
* 包含:姓名、年龄、电话、住址(多个)、备注
* @author jackzhou
*/
@Exportable(name = "contactbook", description = "contact book")
public class ContactBookForTest {
//友人姓名
@Persistent
private String friendName = null;
//友人年龄
@Persistent
private int age = 0;
//友人电话
@Persistent
private ArrayList telephones = null;
//友人住址:家庭、单位
@Persistent
private ArrayList AddressForText = null;
//备注
@Persistent
private String note = null;
public ContactBookForTest(String name, int age,
ArrayList telephoneList,
ArrayList addressList,
String note) {
this.friendName = name;
this.age = age;
this.telephones = new ArrayList<>(telephoneList);
this.AddressForText = new ArrayList<>(addressList);
this.note = note;
}
}
E.ExportToXml类:
package beaninfoframework;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
/**
* 将具有Exportable Annotation的对象转换为xml格式文本
* @author jackzhou
*/
public class ExportToXml {
/**
* 返回对象的成员变量的值(字符串类型)
* @param field 对象的成员变量
* @param fieldTypeClass 对象的类型
* @param obj 对象
* @return 对象的成员变量的值(字符串类型)
*/
private String getFieldValue(Field field, Class fieldTypeClass, Object obj) {
String value = null;
try {
if (fieldTypeClass == String.class) {
value = (String) field.get(obj);
} else if (fieldTypeClass == int.class) {
value = Integer.toString(field.getInt(obj));
} else if (fieldTypeClass == long.class) {
value = Long.toString(field.getLong(obj));
} else if (fieldTypeClass == short.class) {
value = Short.toString(field.getShort(obj));
} else if (fieldTypeClass == float.class) {
value = Float.toString(field.getFloat(obj));
} else if (fieldTypeClass == double.class) {
value = Double.toString(field.getDouble(obj));
} else if (fieldTypeClass == byte.class) {
value = Byte.toString(field.getByte(obj));
} else if (fieldTypeClass == char.class) {
value = Character.toString(field.getChar(obj));
} else if (fieldTypeClass == boolean.class) {
value = Boolean.toString(field.getBoolean(obj));
}
} catch (Exception ex) {
ex.printStackTrace();
value = null;
}
return value;
}
/**
* 输出对象的字段,当对象的字段为Collection或者Map类型时,
* 要调用exportObject方法继续处理
* @param obj 被处理的对象
* @throws Exception
*/
public void exportFields(Object obj) throws Exception {
Exportable exportable = obj.getClass().getAnnotation(Exportable.class);
if (exportable != null) {
if (exportable.value().length() > 0) {
//System.out.println("Class annotation Name:"+exportable.value());
} else {
//System.out.println("Class annotation Name:"+exportable.name());
}
} else {
//System.out.println(obj.getClass()+"类不是使用Exportable标注过的");
}
//取出对象的成员变量
Field[] fields = obj.getClass().getDeclaredFields();
for (Field field : fields) {
//获得成员变量的标注
Persistent fieldAnnotation = field.getAnnotation(Persistent.class);
if (fieldAnnotation == null) {
continue;
}
//重要:避免java虚拟机检查对私有成员的访问权限
field.setAccessible(true);
Class typeClass = field.getType();
String name = field.getName();
String value = getFieldValue(field, typeClass, obj);
//如果获得成员变量的值,则输出
if (value != null) {
System.out.println(getIndent() + "<" + name + ">\n"
+ getIndent() + "\t" + value + "\n" + getIndent() + "");
} //处理成员变量中类型为Collection或Map
else if ((field.get(obj) instanceof Collection)
|| (field.get(obj) instanceof Map)) {
exportObject(field.get(obj));
} else {
exportObject(field.get(obj));
}
}
}
//缩进深度
int levelDepth = 0;
//防止循环引用的检查者,循环引用现象如:a包含b,而b又包含a
Collection cyclicChecker = new ArrayList<>();
/**
* 返回缩进字符串
* @return
*/
private String getIndent() {
String s = "";
for (int i = 0; i < levelDepth; i++) {
s += "\t";
}
return s;
}
/**
* 输出对象,如果对象类型为Collection和Map类型,
* 则需要递归调用exportObject进行处理
* @param obj
* @throws Exception
*/
public void exportObject(Object obj) throws Exception {
Exportable exportable = null;
String elementName = null;
//循环引用现象处理
if (cyclicChecker.contains(obj)) {
return;
}
cyclicChecker.add(obj);
//首先处理Collection和Map类型
if (obj instanceof Collection) {
for (Iterator i = ((Collection) obj).iterator(); i.hasNext();) {
exportObject(i.next());
}
} else if (obj instanceof Map) {
for (Iterator i = ((Map) obj).keySet().iterator(); i.hasNext();) {
exportObject(i.next());
}
} else {
exportable = obj.getClass().getAnnotation(Exportable.class);
//如果obj已经被Exportable Annotation修饰过了(注意annotation是具有继承性的),
//则使用其name作为输出xml的元素name
if (exportable != null) {
if (exportable.value().length() > 0) {
elementName = exportable.value();
} else {
elementName = exportable.name();
}
}
//未被修饰或者Exportable Annotation的值为空字符串,
//则使用类名作为输出xml的元素name
if (exportable == null || elementName.length() == 0) {
elementName = obj.getClass().getSimpleName();
}
//输出xml元素头
System.out.println(getIndent() + "<" + elementName + ">");
levelDepth++;
//如果没有被修饰,则直接输出其toString()作为元素值
if (exportable == null) {
System.out.println(getIndent() + obj.toString());
}
else { //否则将对象的成员变量导出为xml
exportFields(obj);
}
levelDepth--;
//输出xml元素结尾
System.out.println(getIndent() + "");
}
cyclicChecker.remove(obj);
}
public static void main(String[] argv) {
try {
AddressForTest ad = new AddressForTest("China", "Beijing",
"Beijing", "winnerStreet", "10");
ExportToXml test = new ExportToXml();
ArrayList telephoneList = new ArrayList<>();
telephoneList.add("66608888");
telephoneList.add("66608889");
ArrayList adList = new ArrayList<>();
adList.add(ad);
ContactBookForTest adl = new ContactBookForTest("coolBoy",
18, telephoneList, adList, "some words");
test.exportObject(adl);
} catch (Exception ex) {
ex.printStackTrace();
}
}
} 在ExportToXml类之前的类比较简单,这里必须说明一下ExportToXml类:
此类的核心函数是exportObject和exportFields方法,前者输出对象的xml信息,后者输出对象成员变量的信息。 由于对象类型和成员类型的多样性,所以采取了以下的逻辑:
在exportObject方法中,当对象类型为Collection和Map类型时,则需要递归调用exportObject进行处理;而如果对象类型不是Collection和Map类型的话,将判断对象类是否被Exportable annotation修饰过:如果没有被修饰,则直接输出<对象类名>对象.toString()作为xml绑定结果的一部分;如果被修饰过,则需要调用exportFields方法对对象的成员变量进行xml绑定。
在exportFields方法中,首先取出对象的所有成员,然后获得被Persisitent annotation修饰的成员。
在其后的一句:field.setAccessible(true)是很重要的,因为bean类定义中的成员访问修饰都是private,所以为了避免java虚拟机检查对私有成员的访问权限,加上这一句是必需的。 接着后面的语句便是输出<成员名>成员值这样的xml结构。像在exportObject方法中一样,仍然需要判断成员类型是否为Collection和Map类型,如果为上述两种类型之一,则要在exportFields中再次调用exportObject来处理这个成员。
在main方法中,本人编写了一段演示代码:建立了一个由单个友人地址类(AddressForTest)组成的ArrayList作为通讯录类(AddressForTest)的成员的通讯录对象,并且输出这个对象的xml绑定,运行结果如下:
coolBoy
18
66608888
66608889
China
Beijing
Beijing
winnerStreet
10
some words
五、APT工具分析:
1.何谓APT? 根据sun官方的解释,APT(annotation processing tool)是一个命令行工具,它对源代码文件进行检测找出其中的annotation后,使用annotation processors来处理annotation。而annotation processors使用了一套反射API并具备对JSR175规范的支持。 annotation processors处理annotation的基本过程如下:首先,APT运行annotation processors,根据提供的源文件中的annotation生成源代码文件和其它的文件(文件具体内容由annotation processors的编写者决定),接着APT将生成的源代码文件和提供的源文件进行编译生成类文件。 简单的和前面所讲的annotation实例BRFW相比,APT就像一个在编译时处理annotation的javac。而且从sun开发者的blog中看到,java1.6 beta版中已将APT的功能写入到了javac中,这样只要执行带有特定参数的javac就能达到APT的功能。实际上,APT在Java 8中已经被移除,可参看http://openjdk.java.net/projects/jdk8/features,其中的JEP 117。它的功能已经完全集成到javac编译器中去了。 2.为何使用APT? 使用APT主要目的是简化开发者的工作量,因为APT可以在编译程序源代码的同时,生成一些附属文件(比如源文件、类文件、程序发布描述文字等),这些附属文件的内容也都是与源代码相关的。换句话说,使用APT就是代替了传统的对代码信息和附属文件的维护工作。 使用过hibernate或者beehive等软件的朋友可能深有体会。APT可以在编译生成代码类的同时将相关的文件写好,比如在使用beehive时,在代码中使用annotation声明了许多struct要用到的配置信息,而在编译后,这些信息会被APT以struct配置文件的方式存放。 3.如何定义processor? A.APT工作过程: 从整个过程来讲,首先APT检测在源代码文件中哪些annotation存在。然后APT将查找我们编写的annotation processor factories类,并且要求factories类提供annotation processor以处理源文件中所涉及的annotation。接下来,一个合适的annotation processors将被执行,如果在processors生成源代码文件时,该文件中含有annotation,则APT将重复上面的过程直到没有新文件生成。 B.编写annotation processors: 编写一个annotation processors需要使用java1.5 lib目录中的tools.jar提供的以下4个包: com.sun.mirror.apt: 和APT交互的接口; com.sun.mirror.declaration: 用于模式化类成员、类方法、类声明的接口; com.sun.mirror.type: 用于模式化源代码中类型的接口; com.sun.mirror.util: 提供了用于处理类型和声明的一些工具。 每个processor实现了在com.sun.mirror.apt包中的AnnotationProcessor接口,这个接口有一个名为“process”的方法,该方法是在APT调用processor时将被用到的。一个processor可以处理一种或者多种annotation类型。 一个processor实例被其相应的工厂返回,此工厂为AnnotationProcessorFactory接口的实现。APT将调用工厂类的getProcessorFor方法来获得processor。在调用过程中,APT将提供给工厂类一个AnnotationProcessorEnvironment 类型的processor环境类对象,在这个环境对象中,processor将找到其执行所需要的每件东西,包括对所操作的程序结构的参考,与APT通讯并合作一同完成新文件的建立和警告/错误信息的传输。 提供工厂类有两个方式:通过APT的“-factory”命令行参数提供,或者让工厂类在APT的发现过程中被自动定位(关于发现过程详细介绍请看http://java.sun.com/j2se/1.5.0/docs/guide/apt/GettingStarted.html)。前者对于一个已知的factory来讲是一种主动而又简单的方式;而后者则是需要在jar文件的META-INF/services目录中提供一个特定的发现路径: 在包含factory类的jar文件中作以下的操作:在META-INF/services目录中建立一个名为com.sun.mirror.apt.AnnotationProcessorFactory 的UTF-8编码文件,在文件中写入所有要使用到的factory类全名,每个类为一个单独行。
在JDK 8中,tools.jar中的这4个包已经被移除了,因此我们不再举apt的实际例子来分析了。到此为止 :)
参考文献:
http://www.blogjava.net/ericwang/archive/2005/12/13/23743.html
http://www.blogjava.net/weidagang2046/articles/28321.html
http://www.blogjava.net/weidagang2046/articles/27958.html
你可能感兴趣的:(Java&Java企业级架构)
Redis 架构与设计
yuguo.im
redis 架构 数据库
Redis是一种开源的高性能内存键值数据库,其架构设计围绕简单、快速和高效展开。1.Redis的核心架构Redis是一个基于C语言编写的单线程内存数据库,但通过多路复用实现了高效的并发处理。它的架构主要由以下几个模块组成:a.客户端与服务器Redis采用客户端-服务器架构:客户端发送命令请求。服务器处理请求并返回结果。通信使用RESP(RedisSerializationProtocol)协议。b
端到端自动驾驶的分布式传感器融合架构
AI智能涌现深度研究
计算机软件编程原理与应用实践 DeepSeek R1 & 大数据AI人工智能 java python javascript kotlin golang 架构 人工智能
自动驾驶,分布式传感器融合,深度学习,计算机视觉,雷达,lidar,惯性导航,Kalman滤波,决策控制1.背景介绍自动驾驶技术作为未来交通运输的重要发展方向,近年来取得了显著进展。然而,实现真正安全的自动驾驶仍然面临着诸多挑战,其中之一就是如何有效地融合来自不同传感器的数据,构建一个可靠的感知、决策和控制系统。传统的自动驾驶系统通常依赖于单一传感器,例如摄像头或雷达,这会导致感知信息的缺失和鲁棒
MySQL × 向量数据库:大模型时代的黄金组合实战指南
mysql人工智能
一、大模型时代的数据存储革命1.1传统架构的局限性--传统商品表结构CREATETABLEproducts(idINTPRIMARYKEY,titleVARCHAR(255),descriptionTEXT,category_idINT);--典型关键词搜索SELECT*FROMproductsWHEREtitleLIKE'%智能手机%'ORdescriptionLIKE'%旗舰机型%';痛点分析
大模型时代的软件架构设计
AI天才研究院
计算 DeepSeek R1 & 大数据AI人工智能大模型 AI大模型企业级应用开发实战 java python javascript kotlin golang 架构 人工智能 大厂程序员 硅基计算 碳基计算 认知计算 生物计算 深度学习 神经网络 大数据 AIGC AGI LLM 系统架构设计 软件哲学 Agent 程序员实现财富自由
引言当今世界,人工智能(AI)技术正以惊人的速度发展,其中大模型(LargeModels)的崛起尤为引人注目。大模型,也被称为深度学习模型,因其庞大的参数规模和强大的数据处理能力,成为推动AI技术前进的重要力量。随着大模型的广泛应用,软件架构设计面临着前所未有的挑战和机遇。大模型时代的软件架构设计,不仅需要解决传统软件架构所面对的问题,如性能、可靠性和可扩展性等,还需要应对大模型带来的新挑战,如计
第一篇:k8s架构与组件详解
※网络笨猪※
##云原生-容器化-K8S## 架构
没有那么多花里胡哨,直接进行一个K8s架构与组件的学习。一、K8s架构在Master通常上包括kube-apiserver、etcd存储、kube-controller-manager、cloud-controller-manager、kube-scheduler和用于K8s服务的DNS服务器(插件)。这些对集群做出全局决策(比如调度),以及检测和响应集群事件的组件集合也称为控制平面。其实K8s官
项目经验之LZO压缩?思维导图 代码示例(java 架构)
用心去追梦
java 架构 开发语言
LZO(LightweightZip/Unzip)是一种高效的压缩算法,它以快速解压缩著称,适用于需要频繁读取和处理的数据。在Hadoop生态系统中,使用LZO压缩可以显著减少存储空间,并且由于其快速的解压速度,对于大规模数据处理任务来说是非常有利的。以下是关于LZO压缩的项目经验总结、思维导图描述以及Java代码示例。项目经验之LZO压缩LZO的优势快速解压:LZO算法设计时优先考虑了解压速度,
当前主流网络游戏任务系统形式研究(转)
weixin_34174105
为什么80%的码农都做不了架构师?>>>疯狂游戏人:目前国内的网游任务做着是原来越没有意思了,我们差不多都不会去看任务内容,就去任务做了,在自动导航成为大势所趋的情况下更是这样,各种游戏的任务类型都差不多。对游戏经验丰富的玩家真是一种折磨。最近在调查各主流网游的系统。现在就任务系统列举一下,会持续更新,最好给出自己的研究报告。一,《诛仙》1,诛仙任务:和原著有关的经典剧情任务。2,寻宝任务:在完成
游戏任务系统模块架构设计分析
你一身傲骨怎能输
射击游戏项目 游戏
1.引言在现代商业化射击游戏中,任务系统是一个至关重要的模块。它不仅能增加游戏的深度和趣味性,还能通过任务奖励机制提高玩家的参与度和留存率。本文将详细介绍一个高扩展、高性能、高可配置的C#语言任务系统模块的架构设计和实现。2.需求分析2.1功能需求任务创建与管理:支持创建、更新、删除任务。任务分配:支持将任务分配给玩家。任务进度跟踪:实时跟踪玩家的任务进度。任务完成与奖励:处理任务完成后的奖励发放
计算机视觉与机器学习之文档解析与向量化技术加速多模态大模型训练与应用——文件向量化大模型!
知世不是芝士
计算机视觉 人工智能 大语言模型 ai大模型 多模态大模型 机器学习 LLM
目录前言1、TextIn文档解析技术1.1、文档解析技术1.2、目前存在的问题1.2.1、不规则的文档信息示例1.3、合合信息的文档解析1.3.1、合合信息的TextIn文档解析技术架构1.3.2、版面分析关键技术Layout-engine1.3.3、文档树提取关键技术Catalog-engine1.3.4、双栏1.3.5、非对称双栏1.3.6、双栏+表格1.3.7、无线表格1.3.8、合并单元格
Android App开发之Jetpack架构,Android大厂高频面试题解析
m0_66144992
程序员 架构 移动开发 android
因此,Jetpack来了!Jetpack是什么?===========Jetpack是Google推出的一套系列组件集。Jetpack的出现以及Google标准化开发模式的确立,代表了Android原生开发的未来方向,意味着Android发展已经逐渐成熟。为什么要学?======在开发世界,永远是技术至上,一门新技术的盛行总是有原因的,要么比老框架性能提升不少,要不更加易用等等。作为开发者,更是要
《2025 年最新!5 步实现群晖 NAS 远程访问全攻略》
u010905359
公网助手 网络
本文将以神卓NAS公网助手为核心工具,结合2025年最新技术,手把手教你5步完成远程访问配置!第一步:检查NAS系统与网络环境确保群晖DSM系统已升级至DSM7.3及以上版本(2025年最新兼容性优化)。登录NAS后台,进入「控制面板」→「网络」→「连接性」,确认设备已接入互联网。记录NAS的局域网IP地址(如192.168.1.100),后续步骤需使用。注意:若使用企业级路由器,
Partition架构
m0_74825656
面试 学习路线 阿里巴巴 架构
优质博文:IT-BLOG-CNPartition架构【1】结构:Region至少3个Zone,Zone内至少两个Partition,Partition内至少1个K8SMemberCluster;【2】故障域:故障域及核心链路至少Zone内收敛,甚至Partition收敛。故障域之间不应该有交互(状态流等);【3】变更规范:不同时变更多个Zone,甚至不同时变更多个Partition;【4】Fede
玩转Java微服务:架构设计与实战进阶终极指南
Light60
低代码 实战篇 技能篇 Java微服务 Spring Cloud 分布式架构 容器化部署 服务治理
摘要本文深入解析Java微服务核心原理与落地实践,涵盖SpringCloudAlibaba生态体系实战技巧。通过全链路代码示例演示服务注册发现、分布式配置、熔断限流等关键模块实现,结合电商案例阐述DDD领域驱动设计在微服务拆分的应用。提供可落地的性能优化方案与云原生演进路线,助您构建高可用、易扩展的现代化分布式系统。关键词:Java微服务、SpringCloud、分布式架构、容器化部署、服务治理一
计算机毕业设计Java-ssm餐厅线上点菜系统源码+系统+数据库+lw文档
双双科技
java 数据库 开发语言
计算机毕业设计Java-ssm餐厅线上点菜系统源码+系统+数据库+lw文档计算机毕业设计Java-ssm餐厅线上点菜系统源码+系统+数据库+lw文档本源码技术栈:项目架构:B/S架构开发语言:Java语言开发软件:ideaeclipse前端技术:Layui、HTML、CSS、JS、JQuery等技术后端技术:JAVA运行环境:Win10、JDK1.8数据库:MySQL5.7/8.0源码地址:htt
YOLOv9与YOLOv8创新点差异概述:
奔强的程序
YOLO
架构改进:YOLOv8:引入了新的骨干网络,检测头,以及损失函数,旨在提高性能和灵活性。YOLOv9:可能在架构上进行了进一步的优化,比如改进了特征提取的方式、增强了多尺度检测能力等。这些改进有助于模型在处理不同大小和形状的目标时更加有效。梯度信息利用:YOLOv9的一个显著创新点是主打“可编程梯度信息来学习任何内容”。这意味着模型在训练过程中可能更加关注梯度信息的质量和流向,从而更有效地进行参数
5G核心网和协议接口
Elon Reeve Brian
光纤通信原理与应用 移动基站设备维护 5G
**部分笔记**5G其他的功能架构5.3.2数据存储参考架UDSF(用户数据存储功能)在网络功能(NF)中的共享方式以及控制面网络功能对UDSF的访问方式。UDSF可以由同一PLMN中的所有NF共享,其中控制面NF可以共享存储它们非结构化数据的UDSF,或者每个NF可以拥有自己的UDSF。3GPP指定了NF通过N18/Nudsf接口访问UDSF。系统架构允许任何NF在UDSF中存储和检索其非结构化
DeepSeek技术全景解析:架构创新与行业差异化竞争力
二进制coder
人工智能 架构 AGI AI
一、DeepSeek技术体系的核心突破架构设计:效率与性能的双重革新Multi-headLatentAttention(MLA):通过将注意力头维度与隐藏层解耦,实现显存占用降低30%的同时支持4096超长上下文窗口。深度优化的MoE架构:结合256个路由专家与1个共享专家,实现稀疏激活机制(每个Token仅激活8个专家),在代码生成任务中推理速度提升40%。混合模态支持:支持文本、代码、数学符号
DeepSeek 最新发布 DeepEP:一款用于 MoE 模型训练和推理的开源 EP 通信库
强哥之神
人工智能 LLM 机器学习 Latent Space 语言模型 deepseek
采用Mixture-of-Experts(MoE)架构的大型语言模型在没有相应计算量增加的情况下显著提升了模型容量。然而,这种方法也引入了一些挑战,尤其是在GPU之间的通信方面。在MoE模型中,对于任何给定的token,只有一部分专家是活跃的,因此在设备之间高效地交换数据至关重要。传统的全对全(all-to-all)通信方法可能会造成瓶颈,增加延迟,并导致GPU资源利用不足。在对延迟敏感的场景中,
MapStruct 对象转换工具【DDD 架构】
栈老师不回家
架构 架构
文章目录一、前言二、对象模型1.DTO数据传输对象2.BO业务对象3.PO持久化对象4.VO值对象三、MapStruct对象转换1.工具介绍2.代码演示一、前言上篇我们学习了DDD架构,从上到下依次是:用户接口层、应用层、领域层和基础层。那么不同层的实体类是怎么定义的呢?这些实体类之间又该如何互相转换?请记住这两个问题。本篇由你的栈☞带你一探究竟。二、对象模型在软件开发中,DTO、BO、PO、VO
【TOGAF系列】架构开发方法(ADF)第十二章
东临碣石82
架构
第12章:H阶段:架构变更管理本章着眼于建立管理新架构变更的程序。12.1目标H阶段的目标是:确保保持架构开发周期确保架构治理框架得到执行确保企业架构能力满足当前要求12.2输入本节定义了阶段H的输入。12.2.1企业外部参考资料架构参考资料(见TOGAF标准——架构内容)12.2.2非架构输入架构工作请求(见TOGAF标准——架构内容)12.2.3架构输入■企业架构的组织模型(见TOGAF标准—
编程中的拓扑思维:突破传统架构的创新之路
Kurbaneli
架构
在编程领域,我们常常遵循既定的架构模式和设计原则,从面向过程到面向对象,再到如今流行的微服务架构,每种范式都在特定时期推动了软件系统的发展。然而,随着技术的飞速演进和复杂系统需求的不断增加,一种全新的思维模式——拓扑思维,正悄然兴起,为编程世界带来新的活力与可能性。拓扑学基础与编程的关联拓扑学,作为数学的一个分支,主要研究几何图形在连续变形下保持不变的性质。在编程语境中,我们可以将软件系统看作是一
Spring Cloud Alibaba与Spring Boot、Spring Cloud版本对应关系
web13093320398
面试 学习路线 阿里巴巴 spring boot spring cloud java
一、前言在搭建SpringCloud项目环境架构的时候,需要选择SpringBoot和SpringCloud进行兼容的版本号,因此对于选择SpringBoot版本与SpringCloud版本的对应关系很重要,如果版本关系不对应,常见的会遇见项目启动不起来,怪异的则会是你的项目出现一些诡异的问题,查资料也不好查。下面就收集一下SpringBoot与SpringCloud版本之间的对应关系,在搭建项目
企业级AI办公落地实践:基于钉钉/飞书的标准产品解决方案
阿三0404
人工智能 机器学习 深度学习
一、平台化AI的崛起:开箱即用的智能革命2024年企业AI应用调研数据显示:73%的中型企业选择平台标准产品而非自研头部SaaS平台AI功能渗透率达89%典型ROI周期从18个月缩短至3-6个月核心优势对比:维度自研方案平台标准产品部署周期6-12个月1-4周初始成本¥500万+¥5-50万/年维护复杂度需专业团队平台自动更新场景覆盖高度定制通用场景+有限定制二、主流平台AI能力全景图2.1钉钉A
java毕业设计家教管理系统mybatis+源码+调试部署+系统+数据库+lw
练练科技
数据库 java mybatis
java毕业设计家教管理系统mybatis+源码+调试部署+系统+数据库+lwjava毕业设计家教管理系统mybatis+源码+调试部署+系统+数据库+lw本源码技术栈:项目架构:B/S架构开发语言:Java语言开发软件:ideaeclipse前端技术:Layui、HTML、CSS、JS、JQuery等技术后端技术:JAVA运行环境:Win10、JDK1.8数据库:MySQL5.7/8.0源码地址
java毕业生设计宠物领养管理系统计算机源码+系统+mysql+调试部署+lw
你眼里的星星
java mysql 宠物
java毕业生设计宠物领养管理系统计算机源码+系统+mysql+调试部署+lwjava毕业生设计宠物领养管理系统计算机源码+系统+mysql+调试部署+lw本源码技术栈:项目架构:B/S架构开发语言:Java语言开发软件:ideaeclipse前端技术:Layui、HTML、CSS、JS、JQuery等技术后端技术:JAVA运行环境:Win10、JDK1.8数据库:MySQL5.7/8.0源码地址
SpringCloud微服务实战——搭建企业级开发框架(二十四):集成行为验证码和图片验证码实现登录功能
全栈程序猿
Maven SpringCloud spring cloud 微服务 java
随着近几年技术的发展,人们对于系统安全性和用户体验的要求越来越高,大多数网站系统都逐渐采用行为验证码来代替图片验证码。行为验证码指的是通过用户行为来验证用户身份的验证码,如滑动拼图、识别图片中的特定物品等。 行为验证码的重要性在于可以有效地防止机器人和恶意程序对网站或应用程序进行恶意攻击、刷流量、撞库等行为,从而保障了用户和网站的安全。相较于传统的图形验证码等方式,行为验证码更难被破解,同时
PostgreSQL常用函数
shy好好学习
Pg数据库 postgresql 数据库
PostgreSQL常用函数PostgreSQL作为一款企业级开源数据库,其丰富的函数库为开发者提供了强大的数据处理工具。本文将全面深入地探讨PostgreSQL中的常用函数,帮助读者系统地掌握数据库函数的应用。1.字符串处理函数1.1基础字符串操作length(string):计算字符串长度trim():去除字符串两端空格left(string,n):从左侧截取指定长度字符串right(stri
Aloudata 正式发布 NoETL 数据工程架构与三款创新产品,率先实现 Data Fabric 在中国的最佳实践
12月15日,国内领先的自动化数据管理软件提供商Aloudata(大应科技)在线举办了「NoETL!重构数据生产力」战略与产品发布会,AloudataCEO周卫林携创始团队正式发布面向未来的NoETL数据工程架构,并发布AloudataAIR逻辑数据平台、AloudataBIG主动元数据平台和AloudataCAN自动化指标平台三款颠覆性创新产品,为企业解决数字化转型中的难点、痛点提供了全新的思路
electron 的原理,使用场景,简单用法
学会了没
electron javascript 前端
一、核心原理架构组成Chromium渲染引擎:负责界面渲染,每个窗口都是一个独立的Chromium实例。Node.js运行时:提供对系统底层API的访问(如文件系统、网络等)。主进程与渲染进程:主进程:应用程序的入口,管理窗口生命周期和原生API(如菜单、对话框)。渲染进程:每个窗口对应一个渲染进程,运行前端代码,通过preload脚本安全地桥接Node.js功能。进程间通信(IPC)ipcMai
(5-3)DeepSeek多模态大模型架构:Janus-Pro模型
码农三叔
训练 RAG 多模态) 架构 transformer deekseek 人工智能 大模型
5.3Janus-Pro模型Janus-Pro的架构采用了解耦视觉编码的设计理念,将多模态理解与视觉生成任务分离开来,以充分发挥各自优势。Janus-Pro的核心创新在于将视觉编码过程分为两个独立的路径,从而解决传统统一编码中“理解”和“生成”任务之间的冲突。5.3.1解耦视觉编码Janus-Pro模型在架构设计上继承并优化了Janus的核心理念——视觉编码的解耦,这种设计通过分离多模态理解任务和
[黑洞与暗粒子]没有光的世界
comsci
无论是相对论还是其它现代物理学,都显然有个缺陷,那就是必须有光才能够计算
但是,我相信,在我们的世界和宇宙平面中,肯定存在没有光的世界....
那么,在没有光的世界,光子和其它粒子的规律无法被应用和考察,那么以光速为核心的
&nbs
jQuery Lazy Load 图片延迟加载
aijuans
jquery
基于 jQuery 的图片延迟加载插件,在用户滚动页面到图片之后才进行加载。
对于有较多的图片的网页,使用图片延迟加载,能有效的提高页面加载速度。
版本:
jQuery v1.4.4+
jQuery Lazy Load v1.7.2
注意事项:
需要真正实现图片延迟加载,必须将真实图片地址写在 data-original 属性中。若 src
使用Jodd的优点
Kai_Ge
jodd
1. 简化和统一 controller ,抛弃 extends SimpleFormController ,统一使用 implements Controller 的方式。
2. 简化 JSP 页面的 bind, 不需要一个字段一个字段的绑定。
3. 对 bean 没有任何要求,可以使用任意的 bean 做为 formBean。
使用方法简介
jpa Query转hibernate Query
120153216
Hibernate
public List<Map> getMapList(String hql,
Map map) {
org.hibernate.Query jpaQuery = entityManager.createQuery(hql);
if (null != map) {
for (String parameter : map.keySet()) {
jp
Django_Python3添加MySQL/MariaDB支持
2002wmj
mariaDB
现状
首先,Django@Python2.x 中默认的引擎为 django.db.backends.mysql 。但是在Python3中如果这样写的话,会发现 django.db.backends.mysql 依赖 MySQLdb[5] ,而 MySQLdb 又不兼容 Python3 于是要找一种新的方式来继续使用MySQL。 MySQL官方的方案
首先据MySQL文档[3]说,自从MySQL
在SQLSERVER中查找消耗IO最多的SQL
357029540
SQL Server
返回做IO数目最多的50条语句以及它们的执行计划。
select top 50
(total_logical_reads/execution_count) as avg_logical_reads,
(total_logical_writes/execution_count) as avg_logical_writes,
(tot
spring UnChecked 异常 官方定义!
7454103
spring
如果你接触过spring的 事物管理!那么你必须明白 spring的 非捕获异常! 即 unchecked 异常! 因为 spring 默认这类异常事物自动回滚!!
public static boolean isCheckedException(Throwable ex)
{
return !(ex instanceof RuntimeExcep
mongoDB 入门指南、示例
adminjun
java mongodb 操作
一、准备工作
1、 下载mongoDB
下载地址:http://www.mongodb.org/downloads
选择合适你的版本
相关文档:http://www.mongodb.org/display/DOCS/Tutorial
2、 安装mongoDB
A、 不解压模式:
将下载下来的mongoDB-xxx.zip打开,找到bin目录,运行mongod.exe就可以启动服务,默
CUDA 5 Release Candidate Now Available
aijuans
CUDA
The CUDA 5 Release Candidate is now available at http://developer.nvidia.com/<wbr></wbr>cuda/cuda-pre-production. Now applicable to a broader set of algorithms, CUDA 5 has advanced fe
Essential Studio for WinRT网格控件测评
Axiba
JavaScript html5
Essential Studio for WinRT界面控件包含了商业平板应用程序开发中所需的所有控件,如市场上运行速度最快的grid 和chart、地图、RDL报表查看器、丰富的文本查看器及图表等等。同时,该控件还包含了一组独特的库,用于从WinRT应用程序中生成Excel、Word以及PDF格式的文件。此文将对其另外一个强大的控件——网格控件进行专门的测评详述。
网格控件功能
1、
java 获取windows系统安装的证书或证书链
bewithme
windows
有时需要获取windows系统安装的证书或证书链,比如说你要通过证书来创建java的密钥库 。
有关证书链的解释可以查看此处 。
public static void main(String[] args) {
SunMSCAPI providerMSCAPI = new SunMSCAPI();
S
NoSQL数据库之Redis数据库管理(set类型和zset类型)
bijian1013
redis 数据库 NoSQL
4.sets类型
Set是集合,它是string类型的无序集合。set是通过hash table实现的,添加、删除和查找的复杂度都是O(1)。对集合我们可以取并集、交集、差集。通过这些操作我们可以实现sns中的好友推荐和blog的tag功能。
sadd:向名称为key的set中添加元
异常捕获何时用Exception,何时用Throwable
bingyingao
用Exception的情况
try {
//可能发生空指针、数组溢出等异常
} catch (Exception e) {
【Kafka四】Kakfa伪分布式安装
bit1129
kafka
在http://bit1129.iteye.com/blog/2174791一文中,实现了单Kafka服务器的安装,在Kafka中,每个Kafka服务器称为一个broker。本文简单介绍下,在单机环境下Kafka的伪分布式安装和测试验证 1. 安装步骤
Kafka伪分布式安装的思路跟Zookeeper的伪分布式安装思路完全一样,不过比Zookeeper稍微简单些(不
Project Euler
bookjovi
haskell
Project Euler是个数学问题求解网站,网站设计的很有意思,有很多problem,在未提交正确答案前不能查看problem的overview,也不能查看关于problem的discussion thread,只能看到现在problem已经被多少人解决了,人数越多往往代表问题越容易。
看看problem 1吧:
Add all the natural num
Java-Collections Framework学习与总结-ArrayDeque
BrokenDreams
Collections
表、栈和队列是三种基本的数据结构,前面总结的ArrayList和LinkedList可以作为任意一种数据结构来使用,当然由于实现方式的不同,操作的效率也会不同。
这篇要看一下java.util.ArrayDeque。从命名上看
读《研磨设计模式》-代码笔记-装饰模式-Decorator
bylijinnan
java 设计模式
声明: 本文只为方便我个人查阅和理解,详细的分析以及源代码请移步 原作者的博客http://chjavach.iteye.com/
import java.io.BufferedOutputStream;
import java.io.DataOutputStream;
import java.io.FileOutputStream;
import java.io.Fi
Maven学习(一)
chenyu19891124
Maven私服
学习一门技术和工具总得花费一段时间,5月底6月初自己学习了一些工具,maven+Hudson+nexus的搭建,对于maven以前只是听说,顺便再自己的电脑上搭建了一个maven环境,但是完全不了解maven这一强大的构建工具,还有ant也是一个构建工具,但ant就没有maven那么的简单方便,其实简单点说maven是一个运用命令行就能完成构建,测试,打包,发布一系列功
[原创]JWFD工作流引擎设计----节点匹配搜索算法(用于初步解决条件异步汇聚问题) 补充
comsci
算法 工作 PHP 搜索引擎 嵌入式
本文主要介绍在JWFD工作流引擎设计中遇到的一个实际问题的解决方案,请参考我的博文"带条件选择的并行汇聚路由问题"中图例A2描述的情况(http://comsci.iteye.com/blog/339756),我现在把我对图例A2的一个解决方案公布出来,请大家多指点
节点匹配搜索算法(用于解决标准对称流程图条件汇聚点运行控制参数的算法)
需要解决的问题:已知分支
Linux中用shell获取昨天、明天或多天前的日期
daizj
linux shell 上几年 昨天 获取上几个月
在Linux中可以通过date命令获取昨天、明天、上个月、下个月、上一年和下一年
# 获取昨天
date -d 'yesterday' # 或 date -d 'last day'
# 获取明天
date -d 'tomorrow' # 或 date -d 'next day'
# 获取上个月
date -d 'last month'
#
我所理解的云计算
dongwei_6688
云计算
在刚开始接触到一个概念时,人们往往都会去探寻这个概念的含义,以达到对其有一个感性的认知,在Wikipedia上关于“云计算”是这么定义的,它说:
Cloud computing is a phrase used to describe a variety of computing co
YII CMenu配置
dcj3sjt126com
yii
Adding id and class names to CMenu
We use the id and htmlOptions to accomplish this. Watch.
//in your view
$this->widget('zii.widgets.CMenu', array(
'id'=>'myMenu',
'items'=>$this-&g
设计模式之静态代理与动态代理
come_for_dream
设计模式
静态代理与动态代理
代理模式是java开发中用到的相对比较多的设计模式,其中的思想就是主业务和相关业务分离。所谓的代理设计就是指由一个代理主题来操作真实主题,真实主题执行具体的业务操作,而代理主题负责其他相关业务的处理。比如我们在进行删除操作的时候需要检验一下用户是否登陆,我们可以删除看成主业务,而把检验用户是否登陆看成其相关业务
【转】理解Javascript 系列
gcc2ge
JavaScript
理解Javascript_13_执行模型详解
摘要: 在《理解Javascript_12_执行模型浅析》一文中,我们初步的了解了执行上下文与作用域的概念,那么这一篇将深入分析执行上下文的构建过程,了解执行上下文、函数对象、作用域三者之间的关系。函数执行环境简单的代码:当调用say方法时,第一步是创建其执行环境,在创建执行环境的过程中,会按照定义的先后顺序完成一系列操作:1.首先会创建一个
Subsets II
hcx2013
set
Given a collection of integers that might contain duplicates, nums, return all possible subsets.
Note:
Elements in a subset must be in non-descending order.
The solution set must not conta
Spring4.1新特性——Spring缓存框架增强
jinnianshilongnian
spring4
目录
Spring4.1新特性——综述
Spring4.1新特性——Spring核心部分及其他
Spring4.1新特性——Spring缓存框架增强
Spring4.1新特性——异步调用和事件机制的异常处理
Spring4.1新特性——数据库集成测试脚本初始化
Spring4.1新特性——Spring MVC增强
Spring4.1新特性——页面自动化测试框架Spring MVC T
shell嵌套expect执行命令
liyonghui160com
一直都想把expect的操作写到bash脚本里,这样就不用我再写两个脚本来执行了,搞了一下午终于有点小成就,给大家看看吧.
系统:centos 5.x
1.先安装expect
yum -y install expect
2.脚本内容:
cat auto_svn.sh
#!/bin/bash
Linux实用命令整理
pda158
linux
0. 基本命令 linux 基本命令整理
1. 压缩 解压 tar -zcvf a.tar.gz a #把a压缩成a.tar.gz tar -zxvf a.tar.gz #把a.tar.gz解压成a
2. vim小结 2.1 vim替换 :m,ns/word_1/word_2/gc
独立开发人员通向成功的29个小贴士
shoothao
独立开发
概述:本文收集了关于独立开发人员通向成功需要注意的一些东西,对于具体的每个贴士的注解有兴趣的朋友可以查看下面标注的原文地址。
明白你从事独立开发的原因和目的。
保持坚持制定计划的好习惯。
万事开头难,第一份订单是关键。
培养多元化业务技能。
提供卓越的服务和品质。
谨小慎微。
营销是必备技能。
学会组织,有条理的工作才是最有效率的。
“独立
JAVA中堆栈和内存分配原理
uule
java
1、栈、堆
1.寄存器:最快的存储区, 由编译器根据需求进行分配,我们在程序中无法控制.2. 栈:存放基本类型的变量数据和对象的引用,但对象本身不存放在栈中,而是存放在堆(new 出来的对象)或者常量池中(字符串常量对象存放在常量池中。)3. 堆:存放所有new出来的对象。4. 静态域:存放静态成员(static定义的)5. 常量池:存放字符串常量和基本类型常量(public static f