框架:spring总结

struts 是 web 框架 (jsp/action/actionfrom) 

hibernate 是 orm框架,处于持久层.

那么,什么是Spring?

spring 是容器框架,用于配置bean,并维护bean之间关系的框架 。

spring中非常重要的概念:bean,ioc,di


一个简单的spring入门项目.


spring实际上是一个容器框架,可以配置各种bean(action/service/domain/dao),并且可以维护bean与bean的关系,当我们需要使用某个bean的时候,我们可以getBean(id),使用即可.

什么是bean?

Bean在Spring和SpringMVC中无所不在,将这个概念内化很重要,下面分享一下我的想法:

一、Bean是啥

1、Java面向对象,对象有方法和属性,那么就需要对象实例来调用方法和属性(即实例化)

2、凡是有方法或属性的类都需要实例化,这样才能具象化去使用这些方法和属性;

3、规律:凡是子类及带有方法或属性的类都要加上 注册Bean到Spring IoC的注解

(@Component , @Repository , @ Controller , @Service , @Configration)

4、把Bean理解为类的代理或代言人(实际上确实是通过反射、代理来实现的),这样它就能代表类拥有该拥有的东西了

5、我们都在微博上@过某某,对方会优先看到这条信息,并给你反馈,那么在Spring中,你标识一个@符号,那么Spring就会来看看,并且从这里拿到一个Bean(注册)或者给出一个Bean(使用)

二、注解分为两类:

1、一类是使用Bean,即是把已经在xml文件中配置好的Bean拿来用,完成属性、方法的组装;

比如@Autowired , @Resource,可以通过byTYPE(@Autowired)、byNAME(@Resource)的方式获取Bean;

 

2、一类是注册Bean,@Component , @Repository , @ Controller , @Service , @Configration这些注解都是把你要实例化的对象转化成一个Bean,放在IoC容器中,等你要用的时候,它会和上面的@Autowired , @Resource配合到一起,把对象、属性、方法完美组装。

 

三、@Bean是啥?

 

1、原理是什么?先看下源码中的部分内容:

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

Indicates that a method produces a bean to be managed by the Spring container.

 

 <h3>Overview</h3>

 

 <p>The names and semantics of the attributes to this annotation are intentionally

 similar to those of the {@code <bean/>} element in the Spring XML schema. For

 example:

 

 <pre class="code">

     @Bean

     public MyBean myBean() {

         // instantiate and configure MyBean obj

         return obj;

    }</pre>

  意思是@Bean明确地指示了一种方法,什么方法呢——产生一个bean的方法,并且交给Spring容器管理从这我们就明白了为啥@Bean是放在方法的注释上了,因为它很明确地告诉被注释的方法,你给我产生一个Bean,然后交给Spring容器,剩下的你就别管了。

 2、记住,@Bean就放在方法上,就是产生一个Bean,那你是不是又糊涂了,因为已经在你定义的类上加了@Configration等注册Bean的注解了,为啥还要用@Bean呢?这个我也不知道,下面我给个例子,一起探讨一下吧:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

3

package com.edu.fruit;

  //定义一个接口

    public interface Fruit<T>{

        //没有方法

}

 

/*

*定义两个子类

*/

package com.edu.fruit;

     @Configuration

     public class Apple implements Fruit<Integer>{//将Apple类约束为Integer类型

 

}

 

package com.edu.fruit;

     @Configuration

     public class GinSeng implements Fruit<String>{//将GinSeng 类约束为String类型

 

}

/*

*业务逻辑类

*/

package com.edu.service;

       @Configuration

       public class FruitService {

          @Autowired

          private Apple apple;

          @Autowired

          private GinSeng ginseng;

    //定义一个产生Bean的方法

       @Bean(name="getApple")

       public Fruit<?> getApple(){

       System.out.println(apple.getClass().getName().hashCode());

         System.out.println(ginseng.getClass().getName().hashCode());

       return new Apple();

}

}

/*

*测试类

*/

@RunWith(BlockJUnit4ClassRunner.class)

public class Config {

    public Config(){

        super("classpath:spring-fruit.xml");

    }

    @Test

    public void test(){

        super.getBean("getApple");//这个Bean从哪来,从上面的@Bean下面的方法中来,返回

                                                          的是一个Apple类实例对象

         

    }

}

从上面的例子也印证了我上面的总结的内容:

1、凡是子类及带属性、方法的类都注册Bean到Spring中,交给它管理;

2、@Bean 用在方法上,告诉Spring容器,你可以从下面这个方法中拿到一个Bean


什么是IOC?

IOC,控制反转;所谓控制反转就是把创建对象和维护对象关系的权利转移到Spring容器(applicationContext.xml)中,而程序本身不在维护!

什么是DI?

依赖注入,容易维护好对象之间的依赖关系(引用等),就是当程序需要对象的时候,容器将对象注入到程序中,程序此时也依赖容器的对象注入。实际上di和ioc是同一个概念,spring设计者认为di更准确表示spring核心技术。


1.bean容器中获取bean对象的方法

1)从ApplicationContext应用上下文容器中获取

ApplicationContext applicationContext = new ClassPathXmlApplicationContext(".xml文件");

  三种获取上下文的方法:

    1.ClassPathXmlApplicationContext 从类路径加载

    2.FileSystemXmlApplicationContext  从文件系统中加载

    3.XmlWebApplicationContext   从web系统中加载 

2)从bean工厂中获取(BeanFactory) 

BeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource(".xml文件"));

两种方式的比较:

1)加载XML时,ApplicationContext实例化容器的时候,实例化所有对象。当我们要使用的时候,直接获取。即方便快捷,提前加载,但是浪费内存。(饿汉

2)加载XML时,BeanFactory实例化容器但不会实例化所配置的bean对象,只有当我们getBean的时候,才会创建。懒汉

在没有特殊要求的时候,一般使用ApplicationContext

Spring底层对象实例的创建是基于反射和HashMap机制

 


2.bean的scope

默认的生命周期是singleton 单例模式


3.配置bean ?如何给集合类型注入值.?

java中主要的集合有几种: map set list / 数组

Department类:

package com.hsp.collection;

import java.util.List;
import java.util.Map;
import java.util.Set;

public class Department {

	private String name;
        private String[] empName;
	private List<Employee> empList;
	private Set<Employee> empsets;
	private Map<String,Employee> empMaps;
        private properties pp;
	
	public Set<Employee> getEmpsets() {
		return empsets;
	}
	public void setEmpsets(Set<Employee> empsets) {
		this.empsets = empsets;
	}
	public String[] getEmpName() {
		return empName;
	}
	public void setEmpName(String[] empName) {
		this.empName = empName;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public List<Employee> getEmpList() {
		return empList;
	}
	public void setEmpList(List<Employee> empList) {
		this.empList = empList;
	}
	public Map<String, Employee> getEmpMaps() {
		return empMaps;
	}
	public void setEmpMaps(Map<String, Employee> empMaps) {
		this.empMaps = empMaps;
	}

}

Employeel类

package com.hsp.collection;
public class Employee {
	private String name;
	private int id;
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
}

beans.xml配置文件:

<?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:context="http://www.springframework.org/schema/context"
		xmlns:tx="http://www.springframework.org/schema/tx"
		xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
				http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
				http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">

<bean id="department" class="com.hsp.collection.Department">
<property name="name" value="财务部"/>

<!-- 给数组注入值 -->
<property name="empName">
	<list>
		<value>小明</value>
		<value>小明小明</value>
		<value>小明小明小明小明</value>
	</list>
</property>

<!-- 给list注入值 list 中可以有相当的对象 -->
<property name="empList">
	<list>
		<ref bean="emp2" />
		<ref bean="emp1"/>
		<ref bean="emp1"/>
		<ref bean="emp1"/>
		<ref bean="emp1"/>
		<ref bean="emp1"/>
		<ref bean="emp1"/>
	</list>
</property>

<!-- 给set注入值 set不能有相同的对象 -->
<property name="empsets">
	<set>
		<ref bean="emp1" />
		<ref bean="emp2"/>
		<ref bean="emp2"/>
		<ref bean="emp2"/>
		<ref bean="emp2"/>
	</set>
</property>

<!-- 给map注入值 map只有key不一样,就可以装配value -->
<property name="empMaps">
	<map>
		<entry key="11" value-ref="emp1" /> 
		<entry key="22" value-ref="emp2"/>
		<entry key="33" value-ref="emp1"/>
	</map>
</property>


<!-- 给属性集合配置 【点http协议 referer 】-->
<property name="pp">
	<props>
		<prop key="pp1">abcd</prop>
		<prop key="pp2">hello</prop>
	</props>
</property>
</bean>

<bean id="emp1" class="com.hsp.collection.Employee">
<property name="name" value="北京"/>
<property name="id" value="1"/>
</bean>

<bean id="emp2" class="com.hsp.collection.Employee">
<property name="name" value="天津"/>
<property name="id" value="2"/>
</bean>

</beans>

4.内部bean,也就是bean的嵌套

<bean id=”foo” class=”....Foo”>
	<property name=”属性”>
	<!—第一方法引用-->
	<ref bean=’bean对象名’/>
	<!—内部bean-->
	<bean> 
	<properyt></property>
</bean>
</property>
</bean>

5.继承配置

public class Student

public class Gradate extends Student

在beans.xml文件中体现配置

<!-- 配置一个学生对象 -->
<bean id="student" class="com.hsp.inherit.Student">
	<property name="name" value="顺平" />
	<property name="age" value="30"/>
</bean>

<!-- 配置Grdate对象 -->
<bean id="grdate" parent="student" class="com.hsp.inherit.Gradate">
	<!-- 如果自己配置属性name,age,则会替换从父对象继承的数据  -->
	<property name="name" value="小明"/>
	<property name="degree" value="学士"/>
</bean>

6.通过properties取数据(接上面的例子)

properties pp = department.getPp();
for(Entry<Object,Object>entry:pp.entrySet()){
    System.out.println(entry.getKey().toString()+" "+entry.getValue());}

7.按照构造函数方法注入bean   (类中必须要有构造函数)

beans.xml 关键代码:

<!-- 配置一个雇员对象 -->
<bean id="employee" class="com.hsp.constructor.Employee">
<!-- 通过构造函数来注入属性值 -->	
<constructor-arg index="0" type="java.lang.String" value="大明" />
</bean>

8.自动装配

1.byName

<!-- 配置一个master对象 -->
<bean id="master" class="com.hsp.autowire.Master" autowire="byName">
<property name="name">
<value>顺平</value>
</property>
</bean>
<!-- 配置dog对象 -->
<bean id="dog" class="com.hsp.autowire.Dog">
<property name="name" value="小黄"/>
<property name="age" value="3"/>
</bean>

2.byType: byType:寻找和属性类型相同的bean,找不到,装不上,找到多个抛异常。

3.constructor: autowire="constructor"   查找和bean的构造参数一致的一个或多个bean,若找不到或找到多个,抛异常。

按照参数的类型装配  。

4. autodetect   (3)和(2)之间选一个方式。不确定性的处理与(3)和(2)一致。 (construct优先级要高)

5.default

这个需要在<beans defualt-autorwire=“指定” />

当你在<beans >指定了 default-atuowrite后, 所有的bean的 默认的autowire就是 指定的装配方法;

如果没有在<beans defualt-autorwire=“指定” /> 没有  defualt-autorwire=“指定” ,则默认是

defualt-autorwire=”no”

6.no  不自动装配


9.使用spring的特殊bean,完成分散配置

    创建properties文件,将所有的属性值按照key-value的形式放入文件中。

<context:property-placeholder location=".properties文件路径"/>
<!-- 配置一DBUtil对象 $占位符号 -->
<bean id="dbutil" class="com.hsp.dispatch.DBUtil">
<property name="name" value="${name}" />
<property name="drivername" value="${drivername}" />
<property name="url" value="${url}" />
<property name="pwd" value="${pwd}" />
</bean>

<!-- 配置一DBUtil对象 -->
<bean id="dbutil2" class="com.hsp.dispatch.DBUtil">
<property name="name" value="${db2.name}" />
<property name="drivername" value="${db2.drivername}" />
<property name="url" value="${db2.url}" />
<property name="pwd" value="${db2.pwd}" />
</bean>

db.properties:

name=scott
drivername=oracle:jdbc:driver:OracleDirver
url=jdbc:oracle:thin:@127.0.0.1:1521:hsp
pwd=tiger

启用类中的注解

<context:annotation-config/>


Bean的作用域

 Spring3中为Bean定义了5中作用域,

分别为singleton(单例)、prototype(原型)、request、session和global session,5种作用域说明如下:

1.    singleton:单例模式,Spring IoC容器中只会存在一个共享的Bean实例,无论有多少个Bean引用它,始终指向同一对象。Singleton作用域是Spring中的缺省作用域,也可以显示的将Bean定义为singleton模式,配置为:

·        <bean id="userDao"class="com.ioc.UserDaoImpl" scope="singleton"/>

2.    prototype:原型模式,每次通过Spring容器获取prototype定义的bean时,容器都将创建一个新的Bean实例,每个Bean实例都有自己的属性和状态,而singleton全局只有一个对象。

根据经验,对有状态的bean使用prototype作用域,而对无状态的bean使用singleton作用域。

3.    request:在一次Http请求中,容器会返回该Bean的同一实例。而对不同的Http请求则会产生新的Bean,而且该bean仅在当前Http Request内有效。

·        <bean id="loginAction" class="com.cnblogs.Login "scope="request"/>,针对每一次Http请求,Spring容器根据该bean的定义创建一个全新的实例,且该实例仅在当前Http请求内有效,而其它请求无法看到当前请求中状态的变化,当当前Http请求结束,该bean实例也将会被销毁。

4.    session:在一次Http Session中,容器会返回该Bean的同一实例。而对不同的Session请求则会创建新的实例,该bean实例仅在当前Session内有效。

·        <beanid="userPreference" class="com.ioc.UserPreference"scope="session"/>,同Http请求相同,每一次session请求创建新的实例,而不同的实例之间不共享属性,且实例仅在自己的session请求内有效,请求结束,则实例将被销毁。

5.    global Session:在一个全局的Http Session中,容器会返回该Bean的同一个实例,仅在使用portlet context时有效。


 Bean的生命周期

经过如上对Bean作用域的介绍,接下来将在Bean作用域的基础上讲解Bean的生命周期

  Spring容器可以管理singleton作用域下Bean的生命周期,在此作用域下,Spring能够精确地知道Bean何时被创建,何时初始化完成,以及何时被销毁。而对于prototype作用域的Bean,Spring只负责创建,当容器创建了Bean的实例后,Bean的实例就交给了客户端的代码管理,Spring容器将不再跟踪其生命周期,并且不会管理那些被配置成prototype作用域的Bean的生命周期。Spring中Bean的生命周期的执行是一个很复杂的过程,读者可以利用Spring提供的方法来定制Bean的创建过程Spring容器在保证一个bean实例能够使用之前会做很多工作:

1.Spring对Bean进行实例化(相当于程序中的new Xx())

2.Spring将值和Bean的引用注入进Bean对应的属性中,也就是IOC注入

3.如果Bean实现了BeanNameAware接口,Spring将Bean的ID传递给setBeanName()方法
(实现BeanNameAware主要是为了通过Bean的引用来获得Bean的ID,一般业务中是很少有用到Bean的ID的

4.如果Bean实现了BeanFactoryAware接口,Spring将调用setBeanDactory(BeanFactory)方法并把BeanFactory容器实例作为参数传入。
(实现BeanFactoryAware 主要目的是为了获取Spring容器(为了获得容器,从而调用容器里的东西),如Bean通过Spring容器发布事件等)
传递的是Spring工厂本身(可以用这个方法获取到其他Bean)

5.(可以用这个方法获取到其他Bean,项目中用到了,传回class)如果Bean实现了ApplicationContextAwaer接口,Spring容器将调用setApplicationContext(ApplicationContext)方法, (作用与BeanFactory类似都是为了获取Spring容器,如Bean通过Spring容器发布事件等,项目是调用容器里为Handler的bean。applicationContext.getBeansOfType(EventHandler.class);

取得所有的事件处理的classbean做进一步的消费者事件处理2),不同的是Spring容器在调用setApplicationContext方法时会把它自己作为setApplicationContext 的参数传入,而Spring容器在调用setBeanDactory前需要程序员自己指定(注入)setBeanDactory里的参数BeanFactory )传入Spring上下文,该方式同样可以实现步骤4,但比4更好,因为ApplicationContext是BeanFactory的子接口,有更多的实现方法.(如果应用Spring的工厂也就是BeanFactory的话去掉这一步就Ok了

 )

 

6.如果Bean实现了BeanPostProcess接口,Spring将调用它们的postProcessBeforeInitialization(预初始化)方法
(作用是在Bean实例创建成功后对进行增强处理,如对Bean进行修改,增加某个功能)

7.如果Bean实现了InitializingBean接口,Spring将调用它们的afterPropertiesSet方法,作用与在配置文件中对Bean使用init-method声明初始化的作用一样,都是在Bean的全部属性设置成功后执行的初始化方法

8.如果Bean实现了BeanPostProcess接口,Spring将调用它们的postProcessAfterInitialization(后初始化)方法
(作用与6的一样,只不过6是在Bean初始化前执行的,而这个是在Bean初始化后执行的,时机不同 )

9.经过以上的工作后,Bean准备就绪,将一直驻留在应用上下文中给应用使用,直到应用上下文被销毁.

 

当Bean不再需要时,会经过清理阶段。

10.如果Bean实现了DispostbleBean接口,Spring将调用它的destory方法,

11.如果在配置文件中对Bean使用destory-method属性,作用跟10是都一样,都是在Bean实例销毁前执行的方法。

1. 实例化Bean

对于BeanFactory容器,当客户向容器请求一个尚未初始化的bean时,或初始化bean的时候需要注入另一个尚未初始化的依赖时,容器就会调用createBean进行实例化。
对于ApplicationContext容器,当容器启动结束后,便实例化所有的bean。
容器通过获取BeanDefinition对象中的信息进行实例化。并且这一步仅仅是简单的实例化,并未进行依赖注入。
实例化对象被包装在BeanWrapper对象中,BeanWrapper提供了设置对象属性的接口,从而避免了使用反射机制设置属性。

2. 设置对象属性(依赖注入)

实例化后的对象被封装在BeanWrapper对象中,并且此时对象仍然是一个原生的状态,并没有进行依赖注入。
紧接着,Spring根据BeanDefinition中的信息进行依赖注入。
并且通过BeanWrapper提供的设置属性的接口完成依赖注入。

3. 注入Aware接口

紧接着,Spring会检测该对象是否实现了xxxAware接口,并将相关的xxxAware实例注入给bean。(自动装配过程)

4. BeanPostProcessor

当经过上述几个步骤后,bean对象已经被正确构造,但如果你想要对象被使用前再进行一些自定义的处理,就可以通过BeanPostProcessor接口实现
该接口提供了两个函数:

  • postProcessBeforeInitialzation( Object bean, String beanName )
    当前正在初始化的bean对象会被传递进来,我们就可以对这个bean作任何处理。
    这个函数会先于InitialzationBean执行,因此称为前置处理。
    所有Aware接口的注入就是在这一步完成的。
  • postProcessAfterInitialzation( Object bean, String beanName )
    当前正在初始化的bean对象会被传递进来,我们就可以对这个bean作任何处理。
    这个函数会在InitialzationBean完成后执行,因此称为后置处理。

5. InitializingBean与init-method

当BeanPostProcessor的前置处理完成后就会进入本阶段。
InitializingBean接口只有一个函数:

  • afterPropertiesSet()//项目中用到这个。则在注册bean时,同时执行

这一阶段也可以在bean正式构造完成前增加我们自定义的逻辑,但它与前置处理不同,由于该函数并不会把当前bean对象传进来,因此在这一步没办法处理对象本身,只能增加一些额外的逻辑。
若要使用它,我们需要让bean实现该接口,并把要增加的逻辑写在该函数中。然后Spring会在前置处理完成后检测当前bean是否实现了该接口,并执行afterPropertiesSet函数。

当然,Spring为了降低对客户代码的侵入性,给bean的配置提供了init-method属性,该属性指定了在这一阶段需要执行的函数名。Spring便会在初始化阶段执行我们设置的函数。init-method本质上仍然使用了InitializingBean接口(执行的初始化方法)。

6. DisposableBean和destroy-method

和init-method一样,通过给destroy-method指定函数,就可以在bean销毁前执行指定的逻辑。


Spring的单例实现

下面我们来看看Spring中的单例实现,当我们试图从Spring容器中取得某个类的实例时,默认情况下,Spring会才用单例模式进行创建。

<bean id="date" class="java.util.Date"/>

<bean id="date" class="java.util.Date" scope="singleton"/> (仅为Spring2.0支持)

<bean id="date" class="java.util.Date" singleton="true"/>

以上三种创建对象的方式是完全相同的,容器都会向客户返回Date类的单例引用。那么如果我不想使用默认的单例模式,每次请求我都希望获得一个新的对象怎么办呢?很简单,将scope属性值设置为prototype(原型)就可以了

<bean id="date" class="java.util.Date" scope="prototype"/>

通过以上配置信息,Spring就会每次给客户端返回一个新的对象实例。


那么Spring对单例的底层实现,到底是饿汉式单例还是懒汉式单例呢?

Spring框架对单例的支持是采用单例注册表的方式进行实现的,源码如下:

1.  public abstract class AbstractBeanFactory implements ConfigurableBeanFactory{    

2.     /**  

3.      * 充当了Bean实例的缓存,实现方式和单例注册表相同  

4.      */    

5.     private final Map singletonCache=new HashMap();    

6.     public Object getBean(String name)throws BeansException{    

7.         return getBean(name,null,null);    

8.     }    

9.  ...    

10.    public Object getBean(String name,Class requiredType,Object[] args)throws BeansException{    

11.       //对传入的Bean name稍做处理,防止传入的Bean name名有非法字符(或则做转码)    

12.       String beanName=transformedBeanName(name);    

13.       Object bean=null;    

14.       //手工检测单例注册表    

15.       Object sharedInstance=null;    

16.       //使用了代码锁定同步块,原理和同步方法相似,但是这种写法效率更高    

17.       synchronized(this.singletonCache){    

18.          sharedInstance=this.singletonCache.get(beanName);    

19.        }    

20.       if(sharedInstance!=null){    

21.          ...    

22.          //返回合适的缓存Bean实例    

23.          bean=getObjectForSharedInstance(name,sharedInstance);    

24.       }else{    

25.         ...    

26.         //取得Bean的定义    

27.         RootBeanDefinition mergedBeanDefinition=getMergedBeanDefinition(beanName,false);    

28.          ...    

29.         //根据Bean定义判断,此判断依据通常来自于组件配置文件的单例属性开关    

30.         //<bean id="date" class="java.util.Date" scope="singleton"/>    

31.         //如果是单例,做如下处理    

32.         if(mergedBeanDefinition.isSingleton()){    

33.            synchronized(this.singletonCache){    

34.             //再次检测单例注册表    

35.              sharedInstance=this.singletonCache.get(beanName);    

36.              if(sharedInstance==null){    

37.                 ...    

38.                try {    

39.                   //真正创建Bean实例    

40.                   sharedInstance=createBean(beanName,mergedBeanDefinition,args);    

41.                   //向单例注册表注册Bean实例    

42.                    addSingleton(beanName,sharedInstance);    

43.                }catch (Exception ex) {    

44.                   ...    

45.                }finally{    

46.                   ...    

47.               }    

48.              }    

49.            }    

50.           bean=getObjectForSharedInstance(name,sharedInstance);    

51.         }    

52.        //如果是非单例,即prototpye,每次都要新创建一个Bean实例    

53.        //<bean id="date" class="java.util.Date" scope="prototype"/>    

54.        else{    

55.           bean=createBean(beanName,mergedBeanDefinition,args);    

56.        }    

57. }    

58. ...    

59.    return bean;    

60. }    

61. }     

刚才的源码中,大家真正要记住的是Spring对bean实例的创建是采用单例注册表的方式进行实现的,而这个注册表的缓存是HashMap对象,如果配置文件中的配置信息不要求使用单例,Spring会采用新建实例的方式返回对象实例.

后面一段是判定是否为socpe为singleton,是的话执行单例模式的过程,只创建一个新的对象,否的话则可以创建多个对象。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值