`
uule
  • 浏览: 6352709 次
  • 性别: Icon_minigender_1
  • 来自: 一片神奇的土地
社区版块
存档分类
最新评论

DI

 
阅读更多

跟开涛学Spring

 

DI:

 

Spring IoC容器注入依赖资源主要有以下两种基本实现方式:

 

构造器注入:就是容器实例化Bean时注入那些依赖,通过在在Bean定义中指定构造器参数进行注入依赖,包括实例工厂方法参数注入依赖,但静态工厂方法参数不允许注入依赖;

     一、根据参数索引注入

<constructor-arg index="1" value="1"/>

     二、根据参数类型进行注入

<constructor-arg type="java.lang.String" value="Hello World!"/>

类名必须为全限定类名如java.lang.String,int

     三、根据参数名进行注入

<constructor-arg name="message" value="Hello World!"/>

     四、在构造器上使用 @java.beans.ConstructorProperties({"message"})  注解来指定参数名

构造器注入时,需确保编译时class文件包含“变量信息”,具体查看编译时是否包含“变量调试信息”请右击项目,在弹出的对话框选择属性;然后在弹出的对话框选择“Java Compiler”条目,在“Class 文件 生成”框中选择“添加变量信息到Class文件(调试器使用)     

     有一点需要大家注意就是静态工厂方式和实例工厂方式根据参数名字注入的方式只支持通过在class文件中添加“变量调试信息”方式才能运行,ConstructorProperties注解方式不能工作,它只对构造器方式起作用,不建议使用根据参数名进行构造器注入。

     

setter注入:通过setter方法进行注入依赖;

public class BooleanTestBean {  

   private boolean success;  

   public void setSuccess(boolean success) {  

this.success = success;  

   }  

   public boolean isSuccess() {  

return success;  

   }  

}  

 

<!-- boolean参数值可以用on/off,yes/no,1/0  -->  

<bean id="bean2" class="cn.javass.spring.chapter3.bean.BooleanTestBean">  

   <property name="success" value="on"/>  

   <!--<property name="success" value="yes"/>  -->  

   <!--<property name="success" value="1"/>  -->  

</bean>  

 

Spring容器目前能对各种基本类型把配置的String参数转换为需要的类型。

注:Spring类型转换系统对于boolean类型进行了容错处理,除了可以使用“true/false”标准的Java值进行注入,还能使用“yes/no”、“on/off”、“1/0”来代表“真/假”,所以大家在学习或工作中遇到这种类似问题不要觉得是人家配置错了,而是Spring容错做的非常好。

 

 

注入Bean ID:

...

注入集合:

注入List 、Set

       

<bean id="listBean" class="cn.javass.spring.chapter3.bean.ListTestBean">  
		    <property name="values">  
			<list>  
			    <value>1</value>  
			    <value>2</value>  			    
			</list>  
		   </property>  
		</bean>  
		
		<bean id="setBean" class="cn.javass.spring.chapter3.bean.SetTestBean">  
		     <property name="values">  
			<set>  
			<value>1</value>  
			<value>2</value>  			
			</set>  
		     </property>  
		</bean>

 

注入Collection

因为Collection类型是Set和List类型的基类型,所以使用<set>或<list>标签都可以进行注入

 

注入数组类型:

使用<array>标签来配置注入

 

注入字典(Map)类型:

使用<map>标签来配置注入,其属性“key-type”和“value-type”分别指定“键”和“值”的数据类型

默认都为String

 

Properties注入:

使用<props>标签

 

 

引用其它Bean:

构造器注入、Setter注入

属性:  <property id="" ref="bean"/>

标签:  <property id="">

   <ref bean="bean"></ref>

</proterty>

 

其他方式:

<ref local=””/>

<ref local=””/>配置方式:用于引用通过<bean id=”beanName”>方式中通过id属性指定的Bean,它能利用XML解析器的验证功能在读取配置文件时来验证引用的Bean是否存在。因此如果在当前配置文件中有相互引用的Bean可以采用<ref local>方式从而如果配置错误能在开发调试时就发现错误。

 

<ref parent=””/>:

用于引用父容器中的Bean,不会引用当前容器中的Bean,当然父容器中的Bean和当前容器的Bean是可以重名的,获取顺序是直接到父容器找。

 

 

内部Bean定义

内部Bean就是在<property>或<constructor-arg>内通过<bean>标签定义的Bean,该Bean不管是否指定id或name,对其他外部Bean都不可见,

 

 

DI 扩展

 

 

循环依赖

总结:

出现循环引用的时候,使用setter方式调用无参的构造器创建对象即可避免死循环

 

补充:出现循环依赖是设计上的问题,一定要避免

请参考《敏捷软件开发:原则、模式与实践》中的“无环依赖”原则

包之间的依赖结构必须是一个直接的无环图形(DAG)。也就是说,在依赖结构中不允许出现环(循环依赖)。 

 

 

lazy-init:

延迟初始化Bean

 

Spring容器会在创建容器时提前初始化“singleton”作用域的Bean,“singleton”就是单例的意思即整个容器每个Bean只有一个实例。

Spring容器预先初始化Bean通常能帮助我们提前发现配置错误,所以如果没有什么情况建议开启,除非有某个Bean可能需要加载很大资源,而且很可能在整个应用程序生命周期中很可能使用不到,可以设置为延迟初始化

       延迟初始化的Bean通常会在第一次使用时被初始化;或者在被非延迟初始化Bean作为依赖对象注入时在会随着初始化该Bean时被初始化,因为在这时使用了延迟初始化Bean。

 

depends-on:

      depends-on是指指定Bean初始化及销毁时的顺序,使用depends-on属性指定的Bean要先初始化完毕后才初始化当前Bean,由于只有“singleton”Bean能被Spring管理销毁,所以当指定的Bean都是“singleton”时,使用depends-on属性指定的Bean要在指定的Bean之后销毁。

 

<property name="file" value="D:/test.txt"/>配置:Spring容器能自动把字符串转换为java.io.File

 

init-method="init" :指定初始化方法,在构造器注入和setter注入完毕后执行。

       

destroy-method="destroy":指定销毁方法,只有“singleton”作用域能销毁,“prototype”作用域的一定不能,其他作用域不一定能;后边再介绍。

                //一定要注册销毁回调,否则我们定义的销毁方法不执行  

context.registerShutdownHook();  

 

 

自动装配:

目前Spring3.0支持“no”、“byName”、“byType”、“constructor”四种自动装配,默认是“no”指不支持自动装配的,其中Spring3.0已不推荐使用之前版本的“autodetect”自动装配,推荐使用Java 5+支持的(@Autowired)注解方式代替;如果想支持“autodetect”自动装配,请将schema改为“spring-beans-2.5.xsd”或去掉。

 

       自动装配的好处是减少构造器注入和setter注入配置,减少配置文件的长度。自动装配通过配置<bean>标签的“autowire”属性来改变自动装配方式。

可以采用在“<beans>”标签中通过“default-autowire”属性指定全局的自动装配方式,即如果default-autowire=”byName”,将对所有Bean进行根据名字进行自动装配。

 

byName:

通过设置Bean定义属性autowire="byName",意思是根据名字进行自动装配,只能用于setter注入。

比如我们有方法“setHelloApi”,则“byName”方式Spring容器将查找名字为helloApi的Bean并注入,如果找不到指定的Bean,将什么也不注入。

 

 

是不是不要配置<property>了,如果一个bean有很多setter注入,通过“byName”方式是不是能减少很多<property>配置。

此处注意了,在根据名字注入时,将把当前Bean自己排除在外:比如“hello”Bean类定义了“setHello”方法,则hello是不能注入到“setHello”的。

 

byType:

通过设置Bean定义属性autowire="byType",意思是指根据类型注入,用于setter注入

比如如果指定自动装配方式为“byType”,而“setHelloApi”方法需要注入HelloApi类型数据,则Spring容器将查找HelloApi类型数据,如果找到一个则注入该Bean,如果找不到将什么也不注入,如果找到多个Bean将优先注入<bean>标签“primary”属性为true的Bean,否则抛出异常来表明有个多个Bean发现但不知道使用哪个

在根据类型注入时,将把当前Bean自己排除在外

 

根据类型找到多个Bean时,对于集合类型(如List、Set)将注入所有匹配的候选者

也可:

1、通过设置Bean的“autowire-candidate”属性为false来把指定Bean后自动装配候选者中移除

<bean class="cn.javass.spring.chapter2.helloworld.HelloImpl"/>  

<!-- 从自动装配候选者中去除 -->  

<bean class="cn.javass.spring.chapter2.helloworld.HelloImpl"  

autowire-candidate="false"/>  

<bean id="bean1" class="cn.javass.spring.chapter3.bean.HelloApiDecorator"  

autowire="byType"/> 

 

2、通过设置Bean定义的“primary”属性为true来把指定自动装配时候选者中首选Bean:

<bean class="cn.javass.spring.chapter2.helloworld.HelloImpl"/>  

<!-- 自动装配候选者中的首选Bean-->  

<bean class="cn.javass.spring.chapter2.helloworld.HelloImpl" 

primary="true"/>  

<bean id="bean" class="cn.javass.spring.chapter3.bean.HelloApiDecorator"  

autowire="byType"/>  

 

constructor:

通过设置Bean定义属性autowire="constructor",功能和“byType”功能一样,根据类型注入构造器参数

 

<bean class="cn.javass.spring.chapter2.helloworld.HelloImpl"/>  

<!-- 自动装配候选者中的首选Bean-->  

<bean class="cn.javass.spring.chapter2.helloworld.HelloImpl" primary="true"/>  

<bean id="bean"  

    class="cn.javass.spring.chapter3.bean.HelloApiDecorator"  

    autowire="constructor"/>

 

autodetect:

自动检测是使用“constructor”还是“byType”自动装配方式已不推荐使用。如果Bean有空构造器那么将采用“byType”自动装配方式,否则使用“constructor”自动装配方式。此处要把3.0的xsd替换为2.5的xsd,否则会报错。

 

不是所有类型都能自动装配

不能自动装配的数据类型:Object、基本数据类型(Date、CharSequence、Number、URI、URL、Class、int)等;

通过“<beans>”标签default-autowire-candidates属性指定的匹配模式,不匹配的将不能作为自动装配的候选者,例如指定“*Service,*Dao”,将只把匹配这些模式的Bean作为候选者,而不匹配的不会作为候选者;

通过将“<bean>”标签的autowire-candidate属性可被设为false,从而该Bean将不会作为依赖注入的候选者。

 

数组、集合、字典类型的根据类型自动装配和普通类型的自动装配是有区别的:

数组类型、集合(Set、Collection、List)接口类型:

将根据泛型获取匹配的所有候选者并注入到数组或集合中,如“List<HelloApi> list”将选择所有的HelloApi类型Bean并注入到list中,而对于集合的具体类型将只选择一个候选者,“如 ArrayList<HelloApi> list”将选择一个类型为ArrayList的Bean注入,而不是选择所有的HelloApi类型Bean进行注入;

 

字典(Map)接口类型:

同样根据泛型信息注入,键必须为String类型的Bean名字,值根据泛型信息获取,如“Map<String, HelloApi> map” 将选择所有的HelloApi类型Bean并注入到map中,而对于具体字典类型如“HashMap<String, HelloApi> map”将只选择类型为HashMap的Bean注入,而不是选择所有的HelloApi类型Bean进行注入。

 

自动装配缺点

最重要的缺点就是没有了配置,在查找注入错误时非常麻烦,还有比如基本类型没法完成自动装配,所以可能经常发生一些莫名其妙的错误,

在此我推荐大家不要使用该方式,最好是指定明确的注入方式,或者采用最新的Java5+注解注入方式。所以大家在使用自动装配时应该考虑自己负责项目的复杂度来进行衡量是否选择自动装配方式。

 

自动装配注入方式能和配置注入方式一同工作吗?

当然可以,大家只需记住配置注入的数据会覆盖自动装配注入的数据

       大家是否注意到对于采用自动装配方式时如果没找到合适的的Bean时什么也不做,这样在程序中总会莫名其妙的发生一些空指针异常,而且是在程序运行期间才能发现,有没有办法能在提前发现这些错误呢?接下来就让我来看下依赖检查吧。

              

       

依赖检查

用于检查Bean定义的属性都注入数据了,不管是自动装配的还是配置方式注入的都能检查,如果没有注入数据将报错,从而提前发现注入错误,只检查具有setter方法的属性。

Spring3+也不推荐配置方式依赖检查了,建议采用Java5+ @Required注解方式,测试时请将XML schema降低为2.5版本的,和自动装配中“autodetect”配置方式的xsd一样。

       

       一、none:默认方式,表示不检查;

 

       二、objects

检查除基本类型外的依赖对象

       三、simple

对基本类型进行依赖检查,包括数组类型,其他依赖不报错

       四、all

对所以类型进行依赖检查

  

<bean id="bean"  class="cn.javass.spring.chapter3.bean.HelloApiDecorator"  

       dependency-check="objects">  

       <property name="message" value="Haha"/>  

</bean> 

 

 

===========================================================================

以下方法注入比较难懂,需要仔细分析:

方法注入

所谓方法注入其实就是通过配置方式覆盖或拦截指定的方法,通常通过代理模式实现Spring提供两种方法注入:查找方法注入和方法替换注入。

 

因为Spring是通过CGLIB动态代理方式实现方法注入,也就是通过动态修改类的字节码来实现的,本质就是生成需方法注入的类的子类方式实现。

在进行测试之前,我们需要确保将“com.springsource.cn.sf.cglib-2.2.0.jar”放到lib里并添加到“Java Build Path”中的Libararies中。否则报错,异常中包含nested exception is java.lang.NoClassDefFoundError: cn/sf/cglib/proxy/CallbackFilter

 

       传统方式和Spring容器管理方式唯一不同的是不需要我们手动生成子类,而是通过配置方式来实现;其中如果要替换createPrinter()方法的返回值就使用查找方法注入;如果想完全替换sayHello()方法体就使用方法替换注入。       接下来让我们看看具体实现吧。

 

一、查找方法注入:又称为Lookup方法注入,用于注入方法返回结果,也就是说能通过配置方式替换方法返回结果。使用<lookup-method name="方法名" bean="bean名字"/>配置;其中name属性指定方法名,bean属性指定方法需返回的Bean。

方法定义格式:访问级别必须是public或protected,保证能被子类重载,可以是抽象方法,必须有返回值,必须是无参数方法,查找方法的类和被重载的方法必须为非final:

<public|protected> [abstract] <return-type> theMethodName(no-arguments);

 

因为“singleton”Bean在容器中只有一个实例,而“prototype”Bean是每次获取容器都返回一个全新的实例,所以如果“singleton”Bean在使用“prototype” Bean情况时,那么“prototype”Bean由于是“singleton”Bean的一个字段属性,所以获取的这个“prototype”Bean就和它所在的“singleton”Bean具有同样的生命周期,所以不是我们所期待的结果。因此查找方法注入就是用于解决这个问题。

 

1)  首先定义我们需要的类,Printer类是一个有状态的类,counter字段记录访问次数:

 

java代码:
  1. package cn.javass.spring.chapter3.bean;  
  2. public class Printer {  
  3.     private int counter = 0;  
  4.     public void print(String type) {  
  5.         System.out.println(type + " printer: " + counter++);  
  6.     }  
  7. }  

 

       HelloImpl5类用于打印欢迎信息,其中包括setter注入和方法注入,此处特别需要注意的是该类是抽象的,充分说明了需要容器对其进行子类化处理,还定义了一个抽象方法createPrototypePrinter用于创建“prototype”Bean,createSingletonPrinter方法用于创建“singleton”Bean,此处注意方法会被Spring拦截,不会执行方法体代码:

 

java代码:
  1. package cn.javass.spring.chapter3;  
  2. import cn.javass.spring.chapter2.helloworld.HelloApi;  
  3. import cn.javass.spring.chapter3.bean.Printer;  
  4. public abstract class HelloImpl5 implements HelloApi {  
  5.     private Printer printer;  
  6.     public void sayHello() {  
  7.         printer.print("setter");  
  8.         createPrototypePrinter().print("prototype");  
  9.         createSingletonPrinter().print("singleton");
  10.     }  
  11.     public abstract Printer createPrototypePrinter();  
  12.     public Printer createSingletonPrinter() {  
  13.         System.out.println("该方法不会被执行,如果输出就错了");  
  14.         return new Printer();  
  15.     }  
  16.     public void setPrinter(Printer printer) {  
  17.         this.printer = printer;  
  18.     }  
  19. }  

 

2)  开始配置了,配置文件在(resources/chapter3/lookupMethodInject.xml),其中“prototypePrinter”是“prototype”Printer,“singletonPrinter”是“singleton”Printer,“helloApi1”是“singleton”Bean,而“helloApi2”注入了“prototype”Bean:

 

java代码:
  1. <bean id="prototypePrinter"  
  2. class="cn.javass.spring.chapter3.bean.Printer" scope="prototype"/>  
  3. <bean id="singletonPrinter"  
  4. class="cn.javass.spring.chapter3.bean.Printer" scope="singleton"/>  
  5. <bean id="helloApi1" class="cn.javass.spring.chapter3.HelloImpl5" scope="singleton">  
  6. <property name="printer" ref="prototypePrinter"/>  
  7. <lookup-method name="createPrototypePrinter" bean="prototypePrinter"/>  
  8. <lookup-method name="createSingletonPrinter" bean="singletonPrinter"/>  
  9. </bean>      
  10.       
  11. <bean id="helloApi2" class="cn.javass.spring.chapter3.HelloImpl5" scope="prototype">  
  12. <property name="printer" ref="prototypePrinter"/>  
  13. <lookup-method name="createPrototypePrinter" bean="prototypePrinter"/>  
  14. <lookup-method name="createSingletonPrinter" bean="singletonPrinter"/>  
  15. </bean>            

 (helloApi1此处helloApi1的printer好像是注入错了,应该是singletonPrinter吧

 

       3)测试代码如下:

 

java代码:
  1. package cn.javass.spring.chapter3;  
  2. import org.junit.Test;  
  3. import org.springframework.context.support.ClassPathXmlApplicationContext;  
  4. import cn.javass.spring.chapter2.helloworld.HelloApi;  
  5. public class MethodInjectTest {  
  6. @Test  
  7. public void testLookup() {  
  8. ClassPathXmlApplicationContext context =  
  9. new ClassPathXmlApplicationContext("chapter3/lookupMethodInject.xml");  
  10.         System.out.println("=======singleton sayHello======");  
  11.         HelloApi helloApi1 = context.getBean("helloApi1", HelloApi.class);  
  12.         helloApi1.sayHello();  
  13.         helloApi1 = context.getBean("helloApi1", HelloApi.class);  
  14.         helloApi1.sayHello();  
  15.         System.out.println("=======prototype sayHello======");  
  16.         HelloApi helloApi2 = context.getBean("helloApi2", HelloApi.class);  
  17.         helloApi2.sayHello();  
  18.         helloApi2 = context.getBean("helloApi2", HelloApi.class);  
  19.         helloApi2.sayHello();  
  20. }}  

 

       其中“helloApi1”测试中,其输出结果如下:

 

java代码:
  1. =======singleton sayHello======  
  2. setter printer: 0  
  3. prototype printer: 0  
  4. singleton printer: 0  
  5. setter printer: 1  
  6. prototype printer: 0  
  7. singleton printer: 1  

 

       首先“helloApi1”是“singleton”,通过setter注入的“printer”是“prototypePrinter”,所以它应该输出“setter printer:0”和“setter printer:1”;而“createPrototypePrinter”方法注入了“prototypePrinter”,所以应该输出两次“prototype printer:0”;而“createSingletonPrinter”注入了“singletonPrinter”,所以应该输出“singleton printer:0”和“singleton printer:1”。

       而“helloApi2”测试中,其输出结果如下:

 

java代码:
  1.       
  2. =======prototype sayHello======  
  3. setter printer: 0  
  4. prototype printer: 0  
  5. singleton printer: 2  
  6. setter printer: 0  
  7. prototype printer: 0  
  8. singleton printer: 3  
  9.    

 

       首先“helloApi2”是“prototype”,通过setter注入的“printer”是“prototypePrinter”,所以它应该输出两次“setter printer:0”;而“createPrototypePrinter”方法注入了“prototypePrinter”,所以应该输出两次“prototype printer:0”;而“createSingletonPrinter”注入了“singletonPrinter”,所以应该输出“singleton printer:2”和“singleton printer:3”。

       大家是否注意到“createSingletonPrinter”方法应该输出“该方法不会被执行,如果输出就错了”,而实际是没输出的,这说明Spring拦截了该方法并使用注入的Bean替换了返回结果。

方法注入主要用于处理“singleton”作用域的Bean需要其他作用域的Bean时,采用Spring查找方法注入方式无需修改任何代码即能获取需要的其他作用域的Bean。

 

       二、替换方法注入:也叫“MethodReplacer”注入,和查找注入方法不一样的是,他主要用来替换方法体。通过首先定义一个MethodReplacer接口实现,然后如下配置来实现:

 

java代码:
  1. <replaced-method name="方法名" replacer="MethodReplacer实现">  
  2. <arg-type>参数类型</arg-type>  
  3. </replaced-method>”  
  4.    

       1)首先定义MethodReplacer实现,完全替换掉被替换方法的方法体及返回值,其中reimplement方法重定义方法 功能,参数obj为被替换方法的对象,method为被替换方法,args为方法参数;最需要注意的是不能再 通过“method.invoke(obj, new String[]{"hehe"});” 反射形式再去调用原来方法,这样会产生循环调用;如果返回值类型为Void,请在实现中返回null:

 

java代码:
  1. package cn.javass.spring.chapter3.bean;  
  2. import java.lang.reflect.Method;  
  3. import org.springframework.beans.factory.support.MethodReplacer;  
  4. public class PrinterReplacer implements MethodReplacer {  
  5.     @Override  
  6.     public Object reimplement(Object obj, Method method, Object[] args)   throws Throwable {  
  7.         System.out.println("Print Replacer");  
  8.         //注意此处不能再通过反射调用了,否则会产生循环调用,知道内存溢出  
  9.         //method.invoke(obj, new String[]{"hehe"});  
  10.         return null;  
  11.     }  
  12. }  

 

       2)配置如下,首先定义MethodReplacer实现,使用< replaced-method >标签来指定要进行替换方法,属性name指定替换的方法名字,replacer指定该方法的重新实现者,子标签< arg-type >用来指定原来方法参数的类型,必须指定否则找不到原方法:

 

java代码:
  1. <bean id="replacer" class="cn.javass.spring.chapter3.bean.PrinterReplacer"/>  
  2. <bean id="printer" class="cn.javass.spring.chapter3.bean.Printer">  
  3. <replaced-method name="print" replacer="replacer">  
  4.         <arg-type>java.lang.String</arg-type>  
  5.     </replaced-method>  
  6. </bean>  
  7.    

 

       3)测试代码将输出“Print Replacer ”,说明方法体确实被替换了:

 

java代码:
  1. @Test  
  2. public void testMethodReplacer() {  
  3.     ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("chapter3/methodReplacerInject.xml");  
  4.     Printer printer = context.getBean("printer", Printer.class);  
  5.     printer.print("我将被替换");  
  6. }  

 

 

 

分享到:
评论

相关推荐

    CasADi软件应用指南

    CasADi是一款开源的数值优化软件框架,专为解决具有高度灵活性的优化问题而设计,尤其在处理受微分方程约束的优化问题,即最优控制问题时表现出强大的能力。这款软件工具比传统的代数建模语言,如AMPL、GAMS、JuMP或...

    NMPC_casadi.zip_matlab casadi_nmpc算法_nonlinear control_ropejqx_控

    在本压缩包中,`NMPC_casadi.zip` 包含了一个使用 MATLAB 和 Casadi 库实现的 NMPC 示例。 Casadi 是一个开源的数学软件库,专门用于解决非线性优化问题,尤其适合于实时应用。它提供了高效的符号运算和数值求解器...

    测试版本准出条件与DI值规则20230302

    测试版本准出条件与DI值规则 一、DI值定义 在软件测试中,DI值(Defect Index)是一种衡量软硬件质量高低的指标。DI值是根据测试活动发现的缺陷按照问题的严重程度分为四个等级,包括致命、严重、一般、轻微。通过...

    基于C++实现的casadi优化求解NMPC源码(带详细注释).zip

    基于C++实现的casadi优化求解NMPC源码(带详细注释).zip基于C++实现的casadi优化求解NMPC源码(带详细注释).zip基于C++实现的casadi优化求解NMPC源码(带详细注释).zip基于C++实现的casadi优化求解NMPC源码(带详细注释)...

    casadi说明文档简介

    CasADi是一个强大的开源软件工具,专为数值优化和算法微分设计而开发。它提供了一个灵活的符号框架,用于构建和求解各种数学问题,包括优化、动态系统建模和控制。以下是对CasADi关键知识点的详细说明: 1. **简介*...

    SAP B1 UI及DI文档

    《SAP B1 UI及DI文档》是一份深入解析SAP Business One (SAP B1)用户界面(UI)和数据集成(DI)组件的重要参考资料。这份文档详细介绍了SAP B1系统的各个层面,旨在帮助开发者和IT专业人员更好地理解和利用SAP的SDK...

    有n张防御卡Di,价值相应为wi,防御能力为di。

    1 一次大型的party最后节目是选取一位幸运人士,该人将获得组织者准备的一个...7 一个游戏:你有n张防御卡Di,价值相应为wi,防御能力为di。你的对手有进攻卡Aj,进攻能力为aj。如果Di与Aj相遇,且di时,防御卡就死掉。

    Delphi下最好用的XML/XSLT组件DIXML最新版本无需密码效率超高

    本文将深入探讨DIXML组件,它是专为Delphi开发者设计的一款高效且易用的XML和XSLT处理库。 DIXML组件以其无需密码的最新版本,为Delphi开发人员提供了一个强大而快速的解决方案,用于解析、操作和转换XML文档。DI...

    路由器DI-514中文说明书

    ### 路由器DI-514中文说明书知识点概览 #### 一、产品规格与特性 **硬件部分:** - **交换端口:** DI-514配备了4个10/100Mbps的自动交叉检测(Auto-MDI/MDIX)端口,支持自动识别直通线和平行线。 - **广域网端口...

    D-Link DI-624+A V3.13 固件

    【D-Link DI-624+A V3.13 固件】是针对D-Link公司的DI-624+A无线路由器的一款重要更新。固件,全称为Firmware,是设备的操作系统和控制程序,它负责管理硬件资源、提供基本服务、执行设备功能等。在DI-624+A这款...

    Delphi 12 控件之DIXml v6.3.1 for Delphi 11-12 Athens + CRACK.7z

    《Delphi 12 控件:DIXml v6.3.1 for Delphi 11-12 Athens 使用详解及破解指南》 在Delphi编程环境中,控件是构建用户界面的重要元素,它们提供了丰富的功能,使得开发者可以快速、高效地创建出美观且功能强大的...

    SAP DI_API的应用

    根据提供的文档信息,我们可以归纳出一系列与SAP DI_API相关的知识点。这些知识点主要涉及通过DI_API接口进行的各种操作,如创建、更新、删除等,并详细介绍了如何使用这些接口来管理和处理不同的业务对象。 ### ...

    casadi-3.5.0_hpp..//www35.5com_Casadi_

    Casadi是一个开源软件库,主要用于数学优化和动态系统的数值计算。在标题"Casadi-3.5.0_hpp..//www35.5com_Casadi_"中,我们可以推测这可能是指Casadi的一个特定版本——3.5.0,而“hpp”通常与C++中的头文件...

    FANUC机器人DI_DO信号如何扩容_增加数量?.docx

    在实际生产环境中,有时会遇到FANUC机器人输入输出(DI/DO)信号不足的问题,这限制了机器人的功能扩展。本文将详细解释如何对FANUC机器人的DI(数字输入)和DO(数字输出)信号进行扩容,以满足更多控制需求。 ...

    DI 详细介绍的书籍

    依赖注入(Dependency Injection,简称DI)是软件设计模式中的一种,它主要解决的是应用程序中的组件之间依赖关系的管理问题。这个概念在现代软件开发中,尤其是面向对象编程和微服务架构中扮演着至关重要的角色。这...

    ARM7DI Data Sheet

    ### ARM7DI 数据手册概述 本数据手册详细介绍了 ARM7DI 微处理器的相关技术细节,包括其架构、特性以及应用场景等。ARM7DI 是一款低功耗、通用的 32 位 RISC(精简指令集计算)微处理器,具有集成的调试支持功能。 ...

    Ioc, DI demo

    【标题】:“Ioc, DI demo” 【描述】:“Ioc, DI demo, IocPerformance-master”这个描述可能指的是一个示例项目,它演示了如何使用Inversion of Control (IoC)和Dependency Injection (DI)原则,特别是通过...

    oracle DI 技术白皮书

    ### Oracle DI 技术白皮书关键知识点解析 #### 一、概述 Oracle DI 技术白皮书中详细阐述了Oracle DI(数据集成)技术的基本原理及其应用过程。该文档对于理解Oracle DI如何帮助企业实现高效的数据管理和分析具有...

    DI资源库(由DI导出)

    标题中的“DI资源库(由DI导出)”指的是在数据集成(Data Integration,简称DI)环境中创建的一个资源库,这个资源库是通过特定版本——DI12,进行导出的。资源库在数据处理和集成项目中扮演着核心角色,它集合了各种...

    西门子G120变频器的的DI点ON、OFF设置

    ### 西门子G120变频器的DI点ON、OFF2设置及功能解析 #### 一、概述 本文旨在详细介绍西门子G120变频器的DI点(数字输入点)ON、OFF2功能设置方法及其对应的具体应用场景。通过对SINAMICS G120变频器的参数设置,...

Global site tag (gtag.js) - Google Analytics