Spring

Spring下载

Spring源码:https://github.com/WestieLee/spring-framework/releases

Spring文档:http://repo.spring.io/release/org/springframework/spring/

什么是IOC?

IOC亦称为“依赖倒置原理”,哪些方面的控制被反转了呢?依赖对象的获得被反转了。通过使用IOC容器,对象依赖关系的管理被反转了,转到IOC容器中来了,对象之间的相互依赖关系由IOC容器进行管理,并由IOC容器完成对象的注入。简而言之就是IOC容器来管理对象之间的依赖关系并完成对象的注入。

那具体什么是IOC容器呢?BeanFactory和ApplicationContext都可以看成是容器的具体表现形式。结合下文中的容器系列图举例说明:

      

BeanFactory就如上图顶层的瓶子它定义了IOC容器的最基本的功能规范,它也是一个容器;上图最底层的是一个个具体形状的瓶子就相当于FileSystemXmlApplicationContext、ClassPathXmlApplication等具体的容器,Spring为了去适配不同的场景而生产了这些容器。

SpringIOC容器系列

为了方便不同场景的使用,SpringIOC容器系列适配了多种应用场景,SpringIOC容器系列有两个主要容器系列:

① BeanFactory接口的简单容器系列,这系列容器只实现了容器的最基本功能

② ApplicationContext(应用上下文),ApplicationContext继承了BeanFactory,它是容器的高级形态,应用上下文在简单容器的基础上,增加了许多面向框架的特性,同时对应用环境作了许多适配。

“SpringIOC容器适配多种应用场景“是什么意思呢?比如在某个容器系列中可以看到读取不同配置信息的各种容器,从不同I/O源读取配置信息的各种容器设计,更加面向框架的容器应用上下文的容器设计等。这些就是SpringIOC容器适配不同的应用场景的设计。

                  

                  

BeanDefinition

对IOC容器来说, BeanDefinition就是对依赖反转模式中管理的对象依赖关系的数据抽象,也是容器实现依赖反转功能的核心数据结构,简单的说就是xml中定义的bean等信息最后会被解析成BeanDefinition对象,依赖反转功能都是围绕这个BeanDefinitiond的处理来完成的。


IOC容器初始化过程

ContextLoaderListener监听器负责完成IOC容器在Web容器中的初始化,IOC具体的载入过程是由ContextLoaderListener交由ContextLoader来完成的,ContextLoader是ContextLoaderListener的基类。

IOC容器的启动是由AbstractApplicationContext.refresh()方法启动的,这个启动过程包括BeanDefinition的Resource定位、载入、和注册三个基本过程。

① Resource定位指的是BeanDefinition的资源定位它由ResourceLoader通过统一的Resource接口来完成。

② BeanDefinition的载入,即把用户定义好的Bean解析成容器内部的数据结构BeanDefinition。

③ 向IOC容器注册BeanDefinition。IOC容器内部是将BeanDefinition注入到一个HashMap中。

④ 注意:这里谈的是IOC容器初始化过程,在这个过程中, 一般不包含Bean依赖注入的实现,在SpringIOC的设计中,Bean定义的载入和依赖注入是两个独立的过程。依赖注入一般发生在应用第一次通过getBean向容器索取Bean的时候(设置lazyinit除外,设置了该属性会在IOC初始化时就注入了)





2、注入方式:SET注入、构造器注入、接口注入

3、在Spring IOC容器的设计中,有两个主要的容器系列,一个是实现BeanFactory接口的简单容器系列,这系列容器只实现了容器的最基本功能;另一个是ApplicationContext应用上下文,它作为容器的高级形态而存在。应用上下文在简单容器的基础上,增加了许多面向框架的特性,同时对应用环境作了许多适配。

4、IOC容器由很多,但IOC核心就其中一个。我们通常所说的IOC容器,实际上代表着一系列功能各异的容器产品,只是容器的功能有大有小,有各自的特点。作为IOC容器,也需要为它的具体实现指定基本的功能规范,这个功能规范的设计表现为接口类BeanFactory

5、用户使用容器时,可以使用转义符“&”来得到FactoryBean本身,用来区分通过容器来获取FactoryBean产生的对象和获取FactoryBean本身。举例来说,如果myJndiObject是一个FactoryBean,那么使用&FactoryBean得到的是FactoryBean,而不是myJndiObject这个FactoryBean产生出来的对象。




一、读取配置文件applicationContext.xml (获得Spring容器对象的两种方式)

// 方法一:ApplicationContext
	ApplicationContext applicationContext 
		= new ClassPathXmlApplicationContext("cn/test/spring/b_springhelloworld/applicationContext.xml");
//	ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext_dao.xml", this.getClass());	
	// 从中取出配置的Bean
	User user = (User) applicationContext.getBean("user");
// 方法二:Resource
	//获取配置文件
        Resource resource = new ClassPathResource("cn/test/spring/b_springhelloworld/applicationContext.xml");
        //工厂需要从配置文件中获取相应的信息
        BeanFactory beanFactory = new XmlBeanFactory(resource);
	// 从中取出配置的Bean
	User user = (User) beanFactory.getBean("user");

ApplcationContext是BeanFactory的子接口,BeanFactory通常称为Bean容器,ApplicationContext通常称为应用上下文。ApplicationContext的功能要多于BeanFactory,如它可以加载外部的资源文件、可以自动进行AOP切面、可以识别自动代理的类、可以识别用于监听Bean创建的类等。

ApplicationContext的常用方法:

// 一次加载多个配置文件
ApplicationContext ac = new ClassPathXmlApplicationContext(new String[] {"aaa.xml","bbb.xml"});
//获取配置文件中定义的bean的数量
ac.getBeanDefinitionCount();
//获取配置文件中定义的bean的所有名字,返回的是一个String数组
ac.getBeanDefinitionNames();
// 获取属于指定类型的bean的名称
String[] names = ac.getBeanNamesForType(User.class);
// 获取属于指定类型的bean的信息(key是名称,value是对象实例)
Map<String, Object> map = ac.getBeansOfType(UserDao.class);
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" scope="singleton" lazy-init="default" init-method="init" destroy-method="destroy">

scope属性:用于指定bean的生命周期
          singleton:单例的,每次ac.getBean()返回的都是同一个实例.
          prototype:多例的,第次ac.getBean()返回的都是一个新的实例. 默认为singleton。

          init-method:初始化方法,单例和多例都会调用该方法,但必须关闭ApplicationContext,由于ApplicationContext没有close方法,要想调用必须转换成子类

          destroy-method:多例时不会调用,单例可以调用
lazy-init属性:用于指定在什么时候初始化单例的对象
          false:表示在创建ApplicationContext时就初始化本单例的对象。
          true:表示在第一次调用getBean()获取本对象时才初始化。 默认为default.

          如果想要所有的bean都是懒初始化,可以在<beans  default-lazy-init=”true”>在<bean lazy-inti=”default”> 

Bean的继承

<span style="font-family:Microsoft YaHei;">	<!-- 
		配置dao,如果这个bean只是用于抽取出的多个bean的公共配置,则加上abstract="true", 这时就不需要写class属性。
	 -->
	<bean id="baseDao" abstract="true">
		<property name="dataSource" value="myDataSource"></property>
	</bean>
	<!-- 在其他bean中,可以指定parent属性,表示要从哪个父bean继承过来一些公共的配置 -->
	<bean id="myUserDao" parent="baseDao" class="cn.itcast.spring.h_beanproperty.UserDao"></bean>
	<bean id="myRoleDao" parent="baseDao" class="cn.itcast.spring.h_beanproperty.RoleDao"></bean></span>

二、Resource

           1)ClassPathResource是从classpath中读取

           2)FileSystemResource 从文件系统中读取

           3)UrlResource 从指定URL中读取

           4)ServletContextResource 必须要在web环境下使用

 

 

使用特定格式的字符串表示各种类型的Resource,格式如下:

三、依赖注入

(1)Set注入

<span style="font-family:Microsoft YaHei;"><bean name="user3" class="cn.test.spring.h_beanproperty.User">
		<!-- 1、通常设置 -->
		<property name="name" value="张三"></property>
		<!-- 2、给name设置空值 -->
		<property name="name" >
			<null />
		</property>
		<!-- 3、 Set集合(String型)
				Set集合(Integer型) 如果指定强类型,如Set<Integer>,则配置时可以不指定type,Spring能自动转换。
				如果没有指定类型,默认当成String处理。这时指定明确的指定了类型,Spring才可以进行转换
		 -->
		<property name="addressSet">
			<set>
				<value>棠东东路</value>
				<value>御富科贸园</value>
			</set>
		</property>
		<property name="numberSet">
			<set>
				<value type="java.lang.Integer">10</value>
				<value type="java.lang.Integer">20</value>
			</set>
		</property>
		<!-- 4、List集合 -->
		<property name="addressList">
			<list>
				<value>棠东东路</value>
				<value>御富科贸园</value>
				<value>御富科贸园</value>
			</list>
		</property>

		<!-- 5、数组,与List集合的配置一样 -->
		<property name="addressArray">
			<list>
				<value>棠东东路</value>
				<value>御富科贸园</value>
				<value>御富科贸园</value>
			</list>
		</property>
		<!-- 6、Map集合 -->
		<property name="addressMap">
			<map>
				<entry key="地址1" value="棠东东路"></entry>
				<entry key="地址2" value="御富科贸园"></entry>
			</map>
		</property>
		<!-- 7、Properties集合 -->
		<property name="properties">
			<props>
				<prop key="pageSize">20</prop>
				<prop key="maxFileSize">1000K</prop>
			</props>
		</property>
	</bean></span>

(2)构造放注入

<span style="font-family:Microsoft YaHei;"><!-- 通过构造方法注入 -->
<bean name="user2" class="cn.itcast.spring.h_beanproperty.User">
	<constructor-arg value="2"></constructor-arg>
	<constructor-arg value="李四"></constructor-arg>
</bean></span>

(3)注解注入。注解不能提供所有的注入,主要是定义Bean与Bean之间的依赖关系

        // 使用@Component注解可以定义一个bean,bean的名称可以不写,默认为类的简单名称且第1个字母小写。
        以下几个注解的作用一样,只是名称不一样,是为了区分bean的作用。
       @Component    泛指组件,当组件不好归类的时候,我们可以使用这个注解进行标注。   

       @Controller用于标注控制层组件(如struts中的action
       @Service用于标注业务层组件
       @Repository用于标注数据访问组件,即DAO组件。

       @Resource是用于注入依赖的bean:
           可以通过name属性指定所需要的bean的名称,如果找不着,则抛异常。
           或可以通过type属性指定所需要的bean的类型,
           如果只有一个bean匹配这个类型,则就是他.
           如果有多个bean匹配这个类型,则使用名称与字段或属性相同的,如果名称都不与当前属性或字段名相同,则抛异常。
           或可以什么都不指定,默认是先按当前字段或属性的名称查找,如果找不到,再按类型查找,就抛异常。
@Scope注解用于指定bean的生命周期。@Scope("prototype")多例

 

(4)配置自动扫描,如果有多个包可以用逗号隔开

<span style="font-family:Microsoft YaHei;"> <context:component-scan base-package="com.cyqg.os"></context:component-scan></span>

四、控制反转

IOC控制反转:就是应用程序不再创建和维护对象了,它只负责使用对象【可以通过注入等方式传递进来】,所有的创建与维护都转移到了外部容器,控制权都交给外部容器。

五、读取外部的配置文件

<span style="font-family:Microsoft YaHei;"><!-- 加载外部的properties配置文件 -->
	<context:property-placeholder location="classpath:jdbc.properties" />
	<!-- 配置数据库连接池(c3p0) -->
	<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
		<!-- 基本信息 -->
		<property name="jdbcUrl" value="${jdbcUrl}"></property>
		<property name="driverClass" value="${driverClass}"></property>
		<property name="user" value="${username}"></property>
		<property name="password" value="${password}"></property></span>


六、Spring远程调用(RMI)

实体需implements Serializable


ioc,是将对象,放至缓存
spring aop做的并不全

转载于:https://my.oschina.net/weslie/blog/471997

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值