测试2中的例子
package pojo;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Text {
public static void main(String arg[]){
ApplicationContext ac = new ClassPathXmlApplicationContext( "applicationContext.xml" );
Person xiao = (XiaoMing)ac.getBean( "xiaoming" );
xiao.eat();
}
}
Spring构造器注入
很快晓峰已经工作一年了,每天重复干着简单的工作很是无聊啊.不过社会总是在不断进步的。Roh Johnosn这个Spring国里著名的科学家有发明了一种机器。他能在孩子喊没有出生时就能知道这个孩子的一些基本需要。
晓峰听说现在这种机器很快就要装配到他们这里了,在这里工作一年了,因为还记着在地球的三国厚黑学,所以晓峰的人缘在这里还是很不错的.很早便打了报告希望到这个正在组建的“构造注入”部门工作.
今天晓峰接到通知,他可以去“构造注入”这个新部门了。晓峰明天就要去医院的接生部上班了.
晓峰拿到仪器到了预备接生部,给每一位即将出生的孩子进行预测
比如现在这个即将出生的孩子,他以后长大后会是一个很好的语言学家。晓峰要做到就是写封邮件发回总部。公务员会给他准备好各种语言类的图书
现在我们用java描述一下这件事情
Public class Baby {
Public Language lang;
Public Baby(Languange lang){
This.lang = lang;
}
Public void sayLanguage(){
System.out.println("say"+lang.getname);
}
}
Public class Languange{
Public String name="英语";
Public Language(){}
Public String getName(){
Return name;
}
}
Xml文件如下
<beans>
<bean id="baby" class="Baby">
<constructor-arg ref="language" />---->构造注入
</bean>
<bean id="language" class="Language"/>
</beans>
测试文件
Test.java文件
Public class Test{
Public static void mian(String[] args){
ApplicationContext ac =
new ClassPathXmlApplicationContext("bean.xml");
Baby b = (Baby)ac.getBean("baby");
b.sayLanguage();
}
}
结果是:say英语
其中xml文件描述的内容相当于下面的程序
Language lang = new Language();
Baby b = new Baby(lang);
两种注入方式的比较
这两种注入方式无所谓好与坏
值注入就相当于下面的样子
Person p = new Person();
p.setName("小花");
p.setAge("12");
一样。
构造注入就相当于下面的样子
Person p= new Person("小花","12");一样,主要是看你 的习惯和程序要求了,当然他们还是有一些不同的。但是大家了解一下就可以了
比如:值注入
1. 程序开发人员更容易理解和接受。通过setter方法设定的依赖关系显得更加直观自然。
2. 对于复杂的依赖关系,如果采用构造注入,会导致构造器过于臃肿
3. 尤其是默写属性可选的情况下,多参数的构造器就更麻烦的
我个人很喜欢用值注入的方式,因为配置文件出错很容易找到
1. 构造注入可以在构造器中决定依赖关系注入的顺序
2. 对于依赖关系无须变化的Bean,构造注入更有用处.
3. 依赖关系只能在构造器中设定。因而只有组件的创建者才能改变组件的依赖关系。
下面我们来了解一下Spring是怎样实现这样的管理的
在Spring的国度里有一个最高的统治者BeanFactory 主席,他的下面还有一个副主席ApplicationContext。其中ApplicationContext也将是以后BeanFactory的继任者(拿Java语言来描述他们的关系就是:ApplicationContext是BeanFactory的子类)。所以他们也代表了整个Spring政府。
Spring是产生Bean的工厂,同时也管理着Spring世界里的所有Bean。Bean的说法就相当于我们现实世界里的人和物的统称。
我们要在Spring世界里很好的生活下去我们就要必须了解BeanFactory他的性格是什么,他的权力范围在哪里 这样我们才能有更好的漏洞去钻,赚更多的资本。活的更好
其中晓峰也是这样想的。所以,他通过自己的不断的盯梢、摸底得到了下面的BeanFactory的全部资料.
package org.springframework.beans.factory;
主席的家庭地址:BeanFactory住在org市springframework区beans街factory栋
作用:主席住的地方
import org.springframework.beans.BeansException;
主席的家庭别院在:org市springframework区beans街BeansExeption
作用:主席用来处理Spring国度里发生重大错误的时候使用的地方,只要主席去了,就一 定有大事发生。这里要重点注意
public interface BeanFactory {
姓名:BeanFactory
String FACTORY_BEAN_PREFIX = "&";
如果要想得到主席的名字,就要进行转义,用Spring世界中的java语言来描述就是『
//这里是对FactoryBean的转义定义,因为如果使用bean的名字检索FactoryBean得到的对象是工厂生成的对象, // 如果需要得到工厂本身,需要转义
|
』
Object getBean(String name) throws BeansException;
主席的权利一:通过各种Bean的名字找到这个bean,就相当于现实世界的警察,知 道你的DNA就能找到你的人一样,因为在Spring世界中是不能重名 的。当然有时也是会出错的比如这个Bean已经去世了。
Object getBean(String name, Class requiredType)
throws BeansException;
主席的权利二:通过Bean的名字和Bean的类型来找到这个bean,相当于我们通过一 个人的DNA和他是那一个省的人来找到这个人一样.当然他也是有可能 出错的
boolean containsBean(String name);
主席的权利三:通过Bean的名字来找他在Spring国度里是否存在
boolean isSingleton(String name)
throws NoSuchBeanDefinitionException;
主席的权利四:通过Bean的名字找到这个Bean。看看他是不是在Spring中不能缺少的 重要人才.相当于我们现在的某某主席找到一个人的人名就可以知道他是 干什么的,是不是在我们国家内某个领域不可或缺的人才一样。 BranFactory就是通过这个权限来检查这个Bean是不是只要处理某一件事 情就只有他一个人才能完成别的人都不行。用java语言来描述就是所他 是不是单例的
boolean isPrototype(String name)
throws NoSuchBeanDefinitionException;
通过Bean的名字来判断他的作用域是不是Prototype
boolean isTypeMatch(String name, Class targetType)
throws NoSuchBeanDefinitionException;
通过Bean的名字来判断他的作用域是不是TypeMatch
Class getType(String name) throws NoSuchBeanDefinitionException;
主席的权利五:通过Bean的名字知道他是那里的人,用Java语言描述就是,通过Bean 的名字知道Bean的类型
String[] getAliases(String name);
主席特权利六:通过Bean的名字知道他还有没有什么别的名字
}
现在晓峰发现他只有找人和判断一个Bean能在那里工作的权利。嗯,权利很小啊!!!
BeanFactory有很多的孩子(也就是他有多个实现类),用来具体的执行它的这些权利。
我们经常能看到的是org.springframework.beans.xml.XmlBeanFactory
但是,Spring的国民通常是不去麻烦他们的,毕竟人家的地位最高么。因此直接管理spring国度的就只有主席的副手ApplicationContext了(ApplicationContext是BeanFactory的子接口)。
晓峰收集到的ApplicationContext的详细信息如下:
package org.springframework.context;
居住地:org市springframework区.context街(因为他比较有实权)
import org.springframework.beans.factory.HierarchicalBeanFactory;
import org.springframework.beans.factory.ListableBeanFactory;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.core.io.support.ResourcePatternResolver;
public interface ApplicationContext extends ListableBeanFactory, HierarchicalBeanFactory,
MessageSource, ApplicationEventPublisher, ResourcePatternResolver {
//姓名:ApplicationContext
ApplicationContext getParent();
//返回他管理的bean的父亲,如果这个bean是孤儿的话,就返回空(null)
AutowireCapableBeanFactory getAutowireCapableBeanFactory()
throws IllegalStateException;
//给管理Bean一个 自动装配协作对象的接口,有五种方式
String getDisplayName();
//得到管理该bean的管理类的实例
(如:
org.springframework.context.support.ClassPathXmlApplicationContext@1d05c81 )
long getStartupDate();
//第一次管理该Bean时,得到的当时的时间(Long型毫秒数)
}
ApplicationContext的权限也不大,但是他的孩子们可是很厉害的,很有实权。
比如他最常见的两个孩子是(ApplicationContext的实现类)
1. FileSystemXmlApplicationContext
2. ClassPathXmlApplicationContext
我们看看他的两个孩子的详细信息
package org.springframework.context.support;
FileSystemXmlApplicationContext的住址:
Org市.springframework区.context街.support栋
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource;
import org.springframework.util.StringUtils;
public class FileSystemXmlApplicationContext extends AbstractXmlApplicationContext {
//姓名:FileSystemXmlApplicationContext
//地位:ApplicationContext的孩子(实现类)
private String[] configLocations;
public FileSystemXmlApplicationContext(String configLocation) throws BeansException {
this(new String[] {configLocation}, true, null);
}
//从xml文件中载入信息.创建一个新的FileSystemXmlApplicationContext类(Bean),configLocations是xml的名字
public FileSystemXmlApplicationContext(String[] configLocations) throws BeansException {
this(configLocations, true, null);
}
//从多个xml文件中载入信息.创建一个新的FileSystemXmlApplicationContext类(Bean),configLocations是xml的名字
public FileSystemXmlApplicationContext(String[] configLocations, ApplicationContext parent) throws BeansException {
this(configLocations, true, parent);
}
//从多个xml文件和ApplicationContext中载入信息
.创建一个新的FileSystemXmlApplicationContext类(Bean),configLocations是xml的名字
public FileSystemXmlApplicationContext(String[] configLocations, boolean refresh) throws BeansException {
this(configLocations, refresh, null);
}
//传入多个xml文件,是否自动更新上下文.返回新的FileSystemXmlApplicationContext类(Bean)
public FileSystemXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
throws BeansException {
super(parent);
this.configLocations = StringUtils.trimArrayElements(configLocations);
if (refresh) {
refresh();
}
}
//需要多个xml文件、需要知道是否更新上下文、需要得到一个上下文。才能创建一个新的
FileSystemXmlApplicationContext
protected String[] getConfigLocations() {
return this.configLocations;
}
//得到该FileSystemXmlApplicationContext中管理的描述Bean文件(全部xml文件)
protected Resource getResourceByPath(String path) {
if (path != null && path.startsWith("/")) {
path = path.substring(1);
}
return new FileSystemResource(path);
}
}
//得到resource 。resource用于访问XML配置文件资源
我们再来看看他的第二孩子的信息
ClassPathXmlApplicationContext
/**
* 住址:org市.springframework区.context街.support栋(他和他的兄弟
* FileSystemXmlApplicationContex他住在一起)
*/
package org.springframework.context.support;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
//姓名:ClassPathXmlApplicationContext
//他的基因来自AbstractXmlApplicationContext
public class ClassPathXmlApplicationContext extends AbstractXmlApplicationContext {
private Resource[] configResources;
private String[] configLocations;
//需要XML来创建一个新的ClassPathXmlApplicationContext
public ClassPathXmlApplicationContext(String configLocation) throws BeansException {
this(new String[] {configLocation}, true, null);
}
//需要一组XML的文件名来创建一个新的ClassPathXmlApplicationContext
public ClassPathXmlApplicationContext(String[] configLocations) throws BeansException {
this(configLocations, true, null);
}
public ClassPathXmlApplicationContext(String[] configLocations, ApplicationContext parent) throws BeansException {
this(configLocations, true, parent);
}
public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh) throws BeansException {
this(configLocations, refresh, null);
}
public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
throws BeansException {
super(parent);
this.configLocations = StringUtils.trimArrayElements(configLocations);
if (refresh) {
refresh();
}
}
public ClassPathXmlApplicationContext(String path, Class clazz) throws BeansException {
this(new String[] {path}, clazz);
}
public ClassPathXmlApplicationContext(String[] paths, Class clazz) throws BeansException {
this(paths, clazz, null);
}
public ClassPathXmlApplicationContext(String[] paths, Class clazz, ApplicationContext parent)
throws BeansException {
super(parent);
Assert.notNull(paths, "Path array must not be null");
Assert.notNull(clazz, "Class argument must not be null");
this.configResources = new Resource[paths.length];
for (int i = 0; i < paths.length; i++) {
this.configResources[i] = new ClassPathResource(paths[i], clazz);
}
refresh();
}
protected Resource[] getConfigResources() {
return this.configResources;
}
protected String[] getConfigLocations() {
return this.configLocations;
}
}
我们可以看到他们兄弟俩完成的工作几乎就是一样的,那么他们有没有区别呢
FileSystemXmlApplication是以制定路径的Xml配置文件创立的ApplicationContext
ClassPathXmlApplicationContext是以CLASSPATH路径下的Xml配置文件创建
ApplicationContext