Spring源码学习(零) 动机

  学习Spring源码的动机是一次偶然的单元测试, 之前对注入 ,控制反转比较熟悉,先回顾一下当时测试 :

目的:

 测试SpringMvc项目中的model层(俗称Service层)  

 以下的例子均采用注解注入模式,没有在spring.xml中定义bean .

UserModel的代码:

package com.younchen.model;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;


@Service("personModel")
public class PersonModel {

	
	@Autowired
	private Person person;
	
	public Person getPerson(){
		return person;
	}
	
	public void setPerson(Person person) {
		this.person = person;
	}
	
	public void showPersonName(){
		//
		System.out.println("姓名:"+person.getName());
	}
	
}

  userModel(  可以理解为userService ) ,该model中注入了person实体, 所以不能在测试类中以 UserModel userModel = new UserModel() 的方式进行 showPersonName()方法的测试  (推荐mockito 测试框架),  注入需要spring 框架的支持,否则报空指针异常,于是Spring 容器上下文ApplicationContext登场了.

SpringUtil类:

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class SpringUtil {

		private static ApplicationContext context = null;
		
		public static ApplicationContext getApplicationContext() {
			if (context == null) {
				context = new ClassPathXmlApplicationContext("spring.xml");
			}
			return context;
		}

		public static ApplicationContext getApplicationContext(String path) {
			return new ClassPathXmlApplicationContext(path);
		}

		public static ApplicationContext getAnnotationConfigApplicationContext(String basePackages) {
			return new AnnotationConfigApplicationContext(basePackages);
		}
}

 

这个工具类的作用是返回Spring上下文的实例,这样一来可以通过上下文获取spring中配置的bean对象 .

先看一下person类:

package com.younchen.model;

import javax.inject.Named;

@Named("person")
public class Person {

	private String name;

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
}


Person类中的@Name的作用与spring配置文件中定义<bean name="preson" class="com.younchen.model.person"> 的作用是一样的,前提是spring.xml中定义包扫描器

<context:component-scan base-package="com.younchen.*" />


现在看一下测试类:

package com.younchen.test;

import com.younchen.model.PersonModel;
import com.younchen.util.SpringUtil;

public class ApplicationContext {

	public static void main(String[] args){
		//获取application Context
	  PersonModel personModel =  (PersonModel) SpringUtil.getApplicationContext().getBean("personModel");
	  personModel.getPerson().setName("黑猫");
	  personModel.showPersonName();
	}
}


运行结果:

2014-7-8 16:08:46 org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@b749757: startup date [Tue Jul 08 16:08:46 CST 2014]; root of context hierarchy
2014-7-8 16:08:46 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from class path resource [spring.xml]
2014-7-8 16:08:46 org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor <init>
信息: JSR-330 'javax.inject.Inject' annotation found and supported for autowiring
姓名:黑猫

 

   依赖注入: 本例中的 Person 类, 无论是 在spring.xml中配置的方式,还是用注解的方式,它都是由spring容器实例化的,不是人为的去new 了一个对象。

   控制反转: 本例中不明显, 主程序只是负责调用模块的方法而不去管这个模块的具体实现,经常以工厂模式出现。

  依赖注入也是控制反转的一种特殊形态,这里举个例子, 有些时候在userModel中注入的Person 可以是Person的子类(这里可以参考一下 注解方式 同一个实体的不同注解方式 )而userModel的showPersonName方法不管Person的实例具体是哪个类,只负责执行Person的getName方法.

  由此对Spring源码产生了兴趣(待续) 

  


你可能感兴趣的:(Spring源码学习(零) 动机)