组件就是普通的Bean(拿来重复使用)
使用IoC容器管理Bean
1.函数重用,类重用,组件重用(通过接口来使用?)
2 控制权(负责创建配置组件)发生了反转,从应用程序转移到了IoC容器.
在IoC容器中能被"装配",需有"注入"机制,使组件注到另一组件.
依赖注入:将组件配置和使用分离,并由IoC容器负责管理组件的生命周期.
3 依赖注入方式:构造方法注入,设置属性注入,接口注入.
4.Spring的IoC容器有:XmlBeanFactory,ApplicationContext(是实现了BeanFactory接口的可实例类)
XmlBeanFactory需一个xml,和一个Resource对象
eg.1 BeanFactory factory=new XmlBeanFactory(new FileSystemResource("c://test//config.xml"));
2.BeanFactory factory=new XmlBeanFactory(new classPathResource("config.xml"));
5.容器如何解析xml(即Bean的初始化流程)
1.容器根据XML配置文件中Bean的定义实例化一个Bean,并传入必要的构造方法参数.
2.容器根据XML配置文件使用依赖注入设置Bean的属性.
13如果Bean定义了init-method方法,调用这个方法执行一些初始化工作.
6.装配Bean(即在xml配置文件中对每个Bean节点进行正确配置,由Bean到xml的写法)
<bean id="exampleBean"
class="example.chapter3.ExampleBean"
init-method="init" >
<property name="size" value="10" />
<property name="size" ref="..." /> 引用类型
</bean>
注入各种类型
package example.chapter3;
import java.util.List;
public class ListBean {
public void setChildren(List children) {}
public void setPrices(List<Float> prices) {
for(Float f : prices) {
System.out.println(f);
}
}
public void setFibonacci(int[] fibonacci) {
for(int n : fibonacci) {
System.out.println(n);
}
}
}
<bean id="listBean" class="example.chapter3.ListBean">
<!-- 注入普通List -->
<property name="children">
<list>
<value>A String</value>
<ref bean="basicBean" />
</list>
</property>
<!-- 注入强类型的List<Float> -->
<property name="prices">
<list>
<value>12.54</value>
<value>82</value>
<value>27.9</value>
</list>
</property>
<!-- 注入int[]数组 -->
<property name="fibonacci">
<list>
<value>1</value>
<value>1</value>
<value>2</value>
<value>3</value>
<value>5</value>
</list>
</property>
</bean>
<!-- 配置setBean并注入Set -->
<bean id="setBean" class="example.chapter3.SetBean">
<property name="cups">
<set>
<value>spring</value>
<value>hibernate</value>
<value>hibernate</value>
<ref bean="listBean" />
</set>
</property>
</bean>
<!-- 配置mapBean并注入Map -->
<bean id="mapBean" class="example.chapter3.MapBean">
<property name="weekday">
<map>
<!-- 用String作为key -->
<entry key="Monday">
<value>do something</value>
</entry>
<entry key="Tuesday">
<ref bean="setBean" />
</entry>
<!-- 用Bean作为key -->
<entry key-ref="basicBean" value="basic" />
<entry key-ref="listBean" value-ref="setBean" />
</map>
</property>
</bean>
<!-- 配置propBean并注入Properties -->
<bean id="propBean" class="example.chapter3.PropBean">
<property name="env">
<props>
<prop key="target">1.5</prop>
<prop key="encoding">UTF-8</prop>
<prop key="debug">on</prop>
</props>
</property>
</bean>
<!-- 配置constructorBean并从构造方法中注入 -->
<bean id="constructorBean" class="example.chapter3.ConstructorBean">
<constructor-arg value="100" />
<constructor-arg value="200" />
</bean>
注入resource
<bean id="resourceBean" class="example.chapter3.ResourceBean">
<property name="urlResource" value="http://www.javaeedev.com/" />
<property name="classpathResource" value="classpath:config.xml" />
<property name="fileResource" value="C:/WINDOWS/NOTEPAD.EXE" />
</bean>
import java.io.IOException;
import org.springframework.core.io.Resource;
public class ResourceBean {
public void setUrlResource(Resource resource) throws IOException {
System.out.println(resource.getURL());
}
public void setClasspathResource(Resource resource) throws IOException {
System.out.println(resource.getFile());
}
public void setFileResource(Resource resource) throws IOException {
System.out.println(resource.getFile());
}
}
<bean id="resourceBean" class="example.chapter3.ResourceBean">
<property name="urlResource" value="http://www.javaeedev.com/" />
<property name="classpathResource" value="classpath:config.xml" />
<property name="fileResource" value="C:/WINDOWS/NOTEPAD.EXE" />
</bean>
1. UrlResource
UrlResource 封装了java.net.URL,它能够被用来访问任何通过URL可以获得的对象,例如:文件、HTTP对象、FTP对象等。所有的URL都有个标准的 String表示,这些标准前缀可以标识不同的URL类型,包括file:访问文件系统路径,http: 通过HTTP协议访问的资源,ftp: 通过FTP访问的资源等等。
UrlResource 对象可以在Java代码中显式地使用 UrlResource 构造函数来创建。但更多的是通过调用带表示路径的 String 参数的API函数隐式地创建。在后一种情况下,JavaBeans的 PropertyEditor 会最终决定哪种类型的 Resource 被创建。如果这个字符串包含一些众所周知的前缀,比如 classpath:,它就会创建一个对应的已串行化的 Resource。 然而,如果不能分辨出这个前缀,就会假定它是个标准的URL字符串,然后创建UrlResource。
2. ClassPathResource
这个类标识从classpath获得的资源。它会使用线程context的类加载器(class loader)、给定的类加载器或者用来载入资源的给定类。
如果类路径上的资源存在于文件系统里,这个 Resource 的实现会提供类似于java.io.File的功能。而如果资源是存在于还未解开(被servlet引擎或其它的环境解开)的jar包中,这些 Resource 实现会提供类似于java.net.URL 的功能。
ClassPathResource对象可以在Java代码中显式地使用ClassPathResource 构造函数来创建。但更多的是通过调用带表示路径的String参数的API函数隐式地创建。在后一种情况下,JavaBeans的 PropertyEditor 会分辨字符串中 classpath: 前缀,然后相应创建 ClassPathResource。
3. FileSystemResource
这是为处理 java.io.File 而准备的Resource实现。它既可以作为File提供,也可以作为URL。
4. ServletContextResource
这是为 ServletContext 资源提供的 Resource 实现,它负责解析相关web应用根目录中的相对路径。
它始终支持以流和URL的方式访问。 但是只有当web应用包被解开并且资源在文件系统的物理路径上时,才允许以 java.io.File 方式访问。是否解开并且在文件系统中访问,还是直接从JAR包访问或以其它方式访问如DB(这是可以想象的),仅取决于Servlet容器。
5. InputStreamResource
这是为给定的 InputStream 而准备的 Resource 实现。它只有在没有其它合适的 Resource 实现时才使用。而且,只要有可能就尽量使用 ByteArrayResource 或者其它基于文件的Resource 实现。
与其它 Resource 实现不同的是,这是个 已经 打开资源的描述符-因此 isOpen() 函数返回 true。 如果你需要在其它位置保持这个资源的描述符或者多次读取一个流,请不要使用它。
6. ByteArrayResource
这是为给定的byte数组准备的 Resource 实现。 它会为给定的byte数组构造一个 ByteArrayInputStream。
它在从任何给定的byte数组读取内容时很有用,因为不用转换成单一作用的 InputStreamResource。
表 Resource strings
前缀 例子 说明
classpath:
classpath:com/myapp/config.xml
从classpath中加载。
file:
file:/data/config.xml
作为 URL 从文件系统中加载。[a]
http:
http://myserver/logo.png
作为 URL 加载。
(none)
/data/config.xml
根据 ApplicationContext 进行判断。
7bean作用域:singleton(默认) 每次调用getBean()方法请求某一个Bean时,Spring总是返回相同的Bean实例.
prototype 每次返回Bean的新实例.
写法<bean id class scope="prototype">
<!-- 作用域为prototype的date -->
<bean id="date"
class="java.util.Date"
scope="prototype"
/>
8配置工厂Bean:静态工厂,实例工厂.
<!-- 配置静态工厂,可以修改random的作用域查看输出结果 -->
<bean id="random"
class="example.chapter3.StaticFactoryBean"
factory-method="createRandom"
scope="prototype"
/>
需要通过factory-method指定静态方法名称.
<!-- 配置实例工厂 -->
<bean id="instanceFactoryBean" class="example.chapter3.InstanceFactoryBean">
<property name="format" value="yyyy-MM-dd HH:mm:ss" />
</bean>
<bean id="currentTime"
factory-bean="instanceFactoryBean"
factory-method="createTime"
/>
定义实例工厂需要分别定义两个Bean.
9提问:属性什么时候可以省略写
package example.chapter3;
import java.net.URL;
public class BasicBean {
private String title;
public void setUseCache(boolean useCache) {}
public void setMaxSize(int size) {}
public String getTitle() { return title; }
public void setTitle(String title) {this.title = title;}
public void setFile(URL url) {
System.out.println(url);
}
}
名字一样,就可以省略set对应的属性吗?
初始化JNDI有什么作用?