您的位置:首页 > 编程语言 > Java开发

spring学习笔记——spring Hello world 普通java项目版 分析类的加载与装配

2013-11-11 13:49 661 查看
上一篇展示了spring的web版hello world,本篇来一个普通java项目中运用spring的demo,里面有对singleton与prototype的讨论,可以很清晰的看到spring对实体的注入策略。

因为是个demo,后来看工厂后处理器以及bean前、bean后处理器的时候加入了一个简单地BeanPostProcessorImpl实现类,在此一起展现。

项目结构:

建项目、导包、建立好目录结构后,我们来写bo.DoSth类,很简单的输出字符串。

注意此处在初始化的时候把字符串初始化为了“haha"

package bo;

public class DoSth {
private String text = null;
public DoSth(){
this.text = "haha";
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}

}

下面看上一层的view.OutputView,

package view;

import bo.DoSth;

public class OutputView {
private String viewText = null;
private DoSth doSth = null;

public OutputView() {
this.viewText = "haha";
}
public String outPut(){
return this.doSth.getText();
}
public DoSth getDoSth() {
return doSth;
}
public void setDoSth(DoSth doSth) {
this.doSth = doSth;
}
public String getViewText() {
return viewText;
}
public void setViewText(String viewText) {
this.viewText = viewText;
}

}

这个类有一个自己的私有字段。viewText我们也把它初始化为“haha”。

下面来写配置文件:

<?xml version="1.0" encoding="UTF-8"?>
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd"> 
<context:component-scan base-package="bo" />
	<bean id="doSth" class="bo.DoSth" p:text="hehe" />
<bean id="view" class="view.OutputView" p:doSth-ref="doSth" scope="prototype" /></beans>


文件头里有很多冗余的引用,太懒,没删掉。关于Spring的schema列表请移步【/article/11106600.html

配置有三条:注解扫描bo包;装配doSth对象;装配view对象;

在doSth装配时使用p命名空间指定了text属性的值,这样会覆盖掉构造方法中初始化操作。

Spring默认的对象作用域(为什么叫作用域?很不贴切啊)是Singleton。而view的配置中我们制定了其作用域为prototype。那么如果我们多次使用Spring获取view对象,会得到多个独立的veiw实例。然而doSth用了默认的Singleton,所以即使有多个view对象,这些对象中的doSth属性也都是指向同一个doSth实例。下面的例子可以很好地展示这个结构。

然后开始java普通项目调用Spring框架的关键,创建ApplicationContext接口对象,这里采用的是FileSystemXmlApplicationContext,用相对路径很方便的就能找到对应的配置文件。对于这个路径,spring提供了几种路径前缀,来适应不同类型资源的加载。查看列表请移步:/article/11106599.html

对于Spring的调用还有更底层的调用方法,即创建BeanFactory对象,奈何本人也是刚开始学习Spring对其方法不甚了解,而且大多数情况下ApplicationContext作为BeanFactory的高级形态可以满足绝大部分编程需求。

package main;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;

import view.OutputView;

public class HelloSpring {
public static void main(String []args){
ApplicationContext ctx = new FileSystemXmlApplicationContext("/src/applicationContext.xml");
OutputView view = (OutputView) ctx.getBean("view");
System.out.println("view.outPut: "+view.outPut());
System.out.println("view.viewText: "+view.getViewText());
view.setViewText("hehehe");
view.getDoSth().setText("hehehe");
OutputView view2 = (OutputView)ctx.getBean("view");
System.out.println("view2.outPut: "+view2.outPut());
System.out.println("view2.viewText: "+view2.getViewText());
}
}

在FileSystemXmlApplicationContext的构造方法中添加xml配置的url

向ApplicationContext索取OutPutView,底层的对象装配都有Spring自动完成了,拿来就可以用,

得到view后先输出其中doSth对象中的信息,又输出view自身的信息

修改view自身信息

修改doSth信息

重新获取一个新的view对象view2,后先输出其中doSth对象中的信息,又输出view2自身的信息

结果如下:

view.outPut: hehe

view.viewText: haha

view2.outPut: hehehe

view2.viewText: haha

由于对doSth的装配配置覆盖了其构造方法,doSth中text变成了hehe,view中的text仍是初始的haha,对view中的doSth更改为hehehe后,在view2中doSth也变为hehehe,这说明两个view中的doSth指向的是同一个实例,而view2自身的text值仍是初始化时的haha,说明view2是独立于view的新实例。

下面加入工厂后处理器和bean前、bean后处理器来观察spring创建对象的过程:

package bo;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.stereotype.Component;

@Component("beanPostPrcessorImpl")
public class BeanPostProcessorImpl implements BeanPostProcessor,BeanFactoryPostProcessor {

@Override
public Object postProcessAfterInitialization(Object bean, String beanName)
throws BeansException {
// TODO Auto-generated method stub
System.out.println(beanName+" bean后方法");
return bean;
}

@Override
public Object postProcessBeforeInitialization(Object bean, String beanName)
throws BeansException {
// TODO Auto-generated method stub
System.out.println(beanName+" bean前方法");
return bean;
}

@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory factory)
throws BeansException {
// TODO Auto-generated method stub
System.out.println("------工厂后处理器加载的类列表:------");
for(String s:factory.getBeanDefinitionNames()){
System.out.println(s);
}
System.out.println("----------------------:------");
}

}


处理器只需实现两个接口,并加上component注解就可以被Spring识别了,可插拔,非常方便。

再次运行程序结果:

------工厂后处理器加载的类列表:------

beanPostPrcessorImpl

org.springframework.context.annotation.internalConfigurationAnnotationProcessor

org.springframework.context.annotation.internalAutowiredAnnotationProcessor

org.springframework.context.annotation.internalRequiredAnnotationProcessor

org.springframework.context.annotation.internalCommonAnnotationProcessor

view

doSth

org.springframework.context.annotation.ConfigurationClassPostProcessor.importAwareProcessor

----------------------:------

2013-11-11 13:22:35 org.springframework.be....//日志信息...

doSth bean前方法

doSth bean后方法

view bean前方法

view bean后方法

view.outPut: hehe

view.viewText: haha

view bean前方法

view bean后方法

view2.outPut: hehehe

view2.viewText: haha

可以清晰到看到view、doSth先后被加载,在内存中开辟出空间以便注入属性信息;而doSth首先完成装配,接下来才是view。且view在两次getBean中装配了两遍,但doSth由于是单例模式,只有一次装配过程。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: