Spring+Spring MVC+MyBatis应用开发学习笔记(2)--Spring 中的Bean

2.1 Bean 的配置

Spring 可以被看作是一个大型工厂,这个工厂的作用就是生产和管理Spring 容器中的Bean 。如果想要在项目中使用这个工厂,就需要开发者对Spring 的配置文件进行配置。
Spring 容器支持XMLProperties 两种格式的配置文件,在实际开发中,最常使用的就是XML 格式的配置方式。这种配置方式通过XML 文件来注册并管理Bean 之间的依赖关系。
在Spring 中, XML 配置文件的根元素是 , 中包含了多个 子元素,每一个子元素定义了一个Bean ,并描述了该Bean 如何被装配到Spring 容器中。
元素中同样包含了多个属性以及子元素,元素的常用属性及其子元素
Spring+Spring MVC+MyBatis应用开发学习笔记(2)--Spring 中的Bean_第1张图片
在配置文件中,通常一个普通的Bean 只需要定义id (或name) 和class 两个属性即可




< !一使用id 属性定义beanl ,其对应的实现类为com . itheima .Beanl 一〉
****
< !一使用name 属性定义bean2 ,其对应的实现类为com.itheima.Bean2 一〉
****


2.2 Bean 的实例化

在面向对象的程序中,想要使用某个对象,就需要先实例化这个对象。同样,在Spring 中,要想使用容器中的Bean ,也需要实例化Bean 。实例化Bean 有三种方式,分别为构造器实例化静态工厂方式实例化实例工厂方式实例化(其中最常用的是构造器实例化)。接下来将分别对这三种实例化Bean 的方式进行详细讲解。
2.2.1构造器实例化
构造器实例化是指Spring 容器通过Bean 对应类中默认的无参构造方法来实例化Bean 。下面通过一个案例来演示Spring 容器是如何通过构造器来实例化Bean 的。
( 1 )在Ecl ipse 中,创建一个名为c hapter02 的Web 项目,在该项目的lib 目录中加入Spring支持和依赖的JAR 包。
(2 )在chapter02 项目的src 目录下,创建一个com . itheima. instance. constructor 包,在该包中创建Bean1 类
Bean1.java

package com .itheima . instance . constructor;
public class Bean1 { }

(3 )在com . itheima. instance. constructor 包中,创建Spring 的配置文件beans1.xml ,在配置文件中定义一个id 为bean1 的Bean ,并通过class 属性指定其对应的实现类为Bean1
beans1.xml



****

( 4 ) 在com . itheima. instance. constructor 包中,创建测试类InstanceTest 1 ,来测试构造器
是否能实例化Bean
InstanceTest1.java

package com.itheima.instance.constructor ;
 import org . springframework . context . ApplicationContext ;
 import  org.springframework.context.support.C1assPathXmlApp1icationContext ;
 pub1ic class InstanceTest1 (
 public static void main(String[] args) (
// 定义配置文件路径
 String xmlPath = "com/itheima/instance/constructor/beans1.xml ";
// ApplicationContext 在加载配置文件时,对Bean 进行实例化
 ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath) ;
 Bean1 bean = (Bean1) applicationContext . getBean( "bean1 " );
 System.out . println(bean) ;
}
}

在加载时, Spring 容器会通过id 为bean1 的实现类Bean1 中默认的无参构造方法对Bean 进行实例化。执行程序后
Spring+Spring MVC+MyBatis应用开发学习笔记(2)--Spring 中的Bean_第2张图片
Spring 容器已经成功实例化了Bean 1 ,并输出了结果。

2.2.2 静态工厂万式实例化

使用静态工厂是实例化Bean 的另一种方式。该方式要求开发者创建一个静态工厂的方法来创建Bean 的实例,其Bean 配置中的class 属性所指定的不再是Bean 实例的实现类,而是静态工厂类,同时还需要使用factory-method 属性来指定所创建的静态工厂方法。下面通过一个案例来演示如何使用静态工厂方式实例化Bean 。
( 1 ) 在chapter02 项目的src 目录下, 创建一个com. itheima.instance.static_factory 包,在该包中创建一个Bean2 类,该类与Bean1 一样,不需添加任何方法。
( 2 )在com. itheima. instance. static_factory 包中,创建一个MyBean2Factory 类,并在类中创建一个静态方法createBeanO来返回Bean2 实例
MyBean2Factory. java

package com . itheima . instance . static factory ;
public class MyBean2Factory{
//使自己的工广创建Bean2 实例
public static Bean2 createBean(){
return new Bean2();
}
}

(3 ) 在com. ithei ma. instance. static_factory 包中,创建Spring 配置文件beans2.xml





由于使用的是静态工厂方法,所以需要通过class 属性指定其对应的工厂实现类为MyBean2Factory 。由于这种方式配置Bean 后, Spring 容器不知道哪个是所需要的工厂方法,所以增加了factory-method 属性来告诉Spring 容器,其方法名称为createBean 。
(4 ) 在com . itheima. instance. static_factory 包中,创建一个测试类
InstanceTest2 ,来测试使用静态工厂方式是否能实例化Bean

package com . itheima.instance . static_factory;
import org . springframework . context . ApplicationContext ;
import org . springframework . context.support . ClassPathXmlApplicationContext;
public class InstanceTest2 {
public static void main(String[] args)
//定义配百文件路径
String xmlPath ="com/itheima/instance/static factory/beans2 . xml ";
/ / Applicat 工onContext 在加载配置文件时,对Bean 进行实例化
ApplicationContext applicationContext =new ClassPathXmlApplicationContext(xmlPath) ;
System . out . println (applicationContext.getBean ("bean2") ) ;
}
}

Spring+Spring MVC+MyBatis应用开发学习笔记(2)--Spring 中的Bean_第3张图片
2.2.3 实例工厂方式实例化
· 还有一种实例化Bean 的方式就是采用实例工厂。此种方式的工厂类中,不再使用静态方法创建Bean 实例,而是采用直接创建Bean 实例的方式。同时,在配置文件中,需要实例化的Bean也不是通过class 属性直接指向的实例化类,而是通过factory- bean 属性指向配置的实例工厂,然后使用factory- method 属性确定使用工厂中的哪个方法。下面通过一个案例来演示实例工厂方式的使用。
( 1 )在chapter02 项目的src 目录下,创建一个com.itheima.instance . factory 包,在该包中创建Bean3 类,该类与Bean1 一样,不需添加任何方法。
(2 )在com . itheima.instance.factory 包中,创建工厂类MyBean3Factory ,在类中使用默认无参构造方法输出"bean3 工厂实例化中"语句,并使用createBeanO方法创建Bean3 对象,
MyBean3Factory.java

package com.itheima.instance.factory;
 public class MyBean3Factory {
 public MyBean3Factory() {
 System.out .prin tln( " bean3 工厂实例化中") ;
}
 / /创建Bean3 实例的方法
 public Bean3 createBean(){
 return new Bean3();
}
 }

(3 )在com . itheima. instance. factory 包中,创建Spring 配置文件beans3. x ml ,设置相关配置后
beans3.xml

 
  
 
 **** 
 
 **** 
 

(4 )在 com itheima.instance.factory 的包中,创建测试类 InstanceTest3 ,来测试实例工厂方式能否实例化 Bean
InstanceTest3.java

package com.itheima:instance.factory; 
 import org.springframework.context.ApplicationContext; 
 import  org.springframework.context.support.ClassPathXmlApplicationContext; 
 public class InstanceTest3 ( 
 public static void main(String[] args) { 
 //指定配置文件路径
 String xmlPath = "com/itheima/instance/factory/beans3.xml"; 
 // ApplicationContext 在加载配置文件时,对 Bean 进行实例化
 ApplicationContext applicationContext = 
 new ClassPathXmlApplicationContext(xmlPath); 
 System.out.println (applicationContext.getBean ("bean3") ); 
} 
}

执行程序后,控制台的输出结果
Spring+Spring MVC+MyBatis应用开发学习笔记(2)--Spring 中的Bean_第4张图片

2.3 Bean 的作用域

通过 Spring 容器创建一个 Bean 的实例时,不仅可以完成 Bean 的实例化,还可以为 Bean指定特定的作用域。

2.3.1 作用域的种类

Spring 4.3 中为 Bean 的实例定义了 种作用域

Spring+Spring MVC+MyBatis应用开发学习笔记(2)--Spring 中的Bean_第5张图片
Spring+Spring MVC+MyBatis应用开发学习笔记(2)--Spring 中的Bean_第6张图片
singleton、 prototype 是最常用的两种

2.3.2 singleton 作用域
singleton是Spring 容器默认的作用域,当 Bean 的作用域为 singleton 肘, Spring 容器就只会存在一个共享的 Bean 实例,并且所有对 Bean 的请求,只要 id 与该 Bean id 属性相匹配,就会返回同一个 Bean 实例 singleton 作用域对于无会话状态的Bean (如 ao 组件、 Service组件)来说,是最理想的选择。
Spring 配置文件中, Bean 的作用域是通过 元素的 scope 属性来指定的,该属性值可以设置为 singleton prototype request session globalSession application websocket七个值,

在项目 chapter02 中,创建一个 com.itheima.scope 包,在包中创建 Scope 类,该类不需要写任何方法 然后在该包中创建一个配置文件 beans4.xml ,将上述示例代码写入配置文件中最后在包中创建测试类 ScopeTest ,来测试 singleton 作用域。
ScopeTest.java

package com.itheima.scope ; 
 import org.springframework . context.ApplicationContext; 
 import  org . springframework . context . support .ClassPathXmlApplicationContext; 
 public class ScopeTest { 
 public stat void main{String[) args) { 
// 定义配置文件路径
 String xmlPath = "com/itheima/scope/beans4.xml "; 
// 加载配置文件
 ApplicationContext appl cationContext = 
 new ClassPathXmlAppl cationContext(xmlPath)
// 输出获得实例
 System . out . println (applicationContext.getBean ("scope") ); 
 System . out . println(applicationContext.getBean( " scope "));
}
}

执行程序后,控制台的输出结果
Spring+Spring MVC+MyBatis应用开发学习笔记(2)--Spring 中的Bean_第7张图片
2.3.3 prototype 作用域

对需要保持会话状态的 Bean (如 Struts2 Action 类)应该使用 prototype 作用域 在使prototype 作用域时, Spr ng 容器会为每个对该 Bean 的请求都创建一个新的实例要将 Bean 定义为 prototype 作用域,只需在配置文件中将 元素的 scope 属性值设置为 prototype 即可

再次运行测试类 ScopeTest ,控制台的输出结果
Spring+Spring MVC+MyBatis应用开发学习笔记(2)--Spring 中的Bean_第8张图片

2.4 Bean 的生命周期

Spring 容器可以管理 singleton 作用域的 Bean 的生命周期,在此作用域下, Spring 能够精确地知道该 Bean 何时被创建,何时初始化完成以及何时被销毁 对于 prototype 作用域的Bean , Spring 只负责创建,当容器创建了 Bean 实例后, Bean 的实例就交给客户端代码来管理,Spring 容器将不再跟踪其生命周期 每次客户端请求 prototype 作用域的 Bean 时, Spring 容器都会创建一个新的实例,并且不会管那些被配置成 prototype 作用域的 Bean 的生命周期。了解 Bean 的生命周期的意义就在,可以在某个 Bean 生命周期的某些指定时刻完成一些相关操作 这种时刻可能有很多,但在一般情况下,常会在 Bean的 postinitiation (初始化后)和predestruction (销毁前)执行一些相关操作Spring 中, Bean 生命周期的执行是一个很复杂的过程,读者可以利用 Spring 提供的方法来定制 Bean 的创建过程 当一个 Bean 被加载到 Spring 容器时,它就具有了生命,而 Spring
容器在保证一个 Bean 能够使用之前,会做很多工作 。

Spring+Spring MVC+MyBatis应用开发学习笔记(2)--Spring 中的Bean_第9张图片
Bean 的生命周期的整个执行过程描述如下
( 1 )根据配置情况调用 Bean 构造方法或工厂方法实例化 Bean
(2 )利用依赖注入完成 Bean 中所有属性值的配置注入
(3 )如果 Bean 实现了 BeanNameAware 接口,则 Spring 调用 Bean setBeanName()法传入当前 Bean id
(4 )如果 Bean 实现了 Bean Factory Aware 接口,则 Spring 调用 setBeanFactoryO 方法传入当前工厂实例的引用
(5 )如果 Bean 实现了 ApplicationContextAware 接口,贝IJ Spring 调用 setA pplicationContextO方法传入当前 ApplicationContext 实例的引用
(6 )如果 Bean PostProcessor Bean 关联,则 Spring 将调用该接口的预初始化方法postProcessBeforel n itialzationO Bean 进行加工操作,这个非常重要, Spring AOP 就是用它实现的
(7 )如果 Bean 另见了 InitializingBean 接口,则 Spring 将调用 afterPropertiesSet() 方法。
(8 )如果在配置文件中通过 init-method 属性指定了初始化方法,则调用该初始化方法
(9 )如果有 Bean PostProcessor Bean 关联,贝IJ Spring 将调用该接口的初始化方法 postProcessAfterlnitialization() 此时, Bean 已经可以被应用系统使用了
( 10 )如果在 中指定了该 Bean 的作用范围为 scope=“singleton” ,则将该 BeanSpring loC 的缓存池中,将触发 Spring 对该 Bean 的生命周期管理;如果在 中指定了Bean 的作用范围为 scope=“prototype” ,贝IJ 将该 Bean 交给调用者,调用者管理该 Bean 的生命周期, Spring 不再管理该 Bean
( 11 )如果 Bean 实现了 DisposableBean 接口,贝IJ Spring 会调用 destory() 方法将 Spring中的 Bean 销毁;如果在配置文件中通过 destory-method 属性指定了 Bean 的销毁方法,则Spring 将调用该方法进行销毁Spring Bean 提供了细致全面的生命周期过程,通过实现特定的接口或通过 的属性设置,都可以对 Bean 的生命周期过程产生影响 我们可以随意地配置 的属性,但是在这里建议不要过多地使用 Bean 实现接口,因为这样会使代码和 Spring 聚合比较紧密。

2.5 Bean 的装配方式

Bean 的装配可以理解为依赖关系注入, Bean 的装配方式即 Bean 依赖注入的方式 Spring容器支持多种形式的 Bean 的装配方式,如基于 XML 的装配、基于注解( Annotation )的装配和自动装配等(其中最常用的是基于注解的装自己) 。
2.5.1 基于 XML 的装配
Spring 提供了两种基于 XML 的装配方式:设值注入( Setter Injection )和构造注入( Constructor Injection 。
Spring 实例化 Bean 的过程中, Spring 首先会调用 Bean 的默认构造方法来实例化 Bean对象,然后通过反射的方式调用 setter 方法来注入属性值 因此,设值注入要求一个 Bean 必须满足以下两点要求
• Bean 类必须提供一个默认的无参构造方法
• Bean 类必须为需要注入的属性提供对应的 setter 方法使用设值注入时,在 Spring 配置文件中,需要使用 元素的子元素 来为每个属性注入值;而使用构造注入时,在配置文件里,需要使用 元素的子元素 来定义构造方法的参数,可以使用其 value 属性(或子元素)来设置该参数的值 下面通过一个案例来演示基于 XML 方式的 Bean 的装配
( 1 )在项目 chapter02 src 目录下,创建一个 com. itheima. assem b le 包,在该包中创建User 类,并在类中定义 username password和 list 集合三个属性及其对应的 setter 方法,
User.java

package com.itheima.assemble; 
import java.util.List;
pub1ic c1ass User { 
private String user ame
private Integer password; 
private List list; 
/** 
* 1.使用构造注入
* 1. 提供带所有参数的有参构造方法。
*/ 
public User(String username , Integer password, List 1ist){
super() ; 
this . username = username ; 
this . password = password; 
this . list = 1ist; 
/*使用设值注入
* 提供默认空参构造方法;
* 为所有属性提供 setter 方法。
*/ 
public User () 
super(); 
* 
1
,,,,, 
} 
public void setUsername(String username) 
this. username = username ; 
public void setPassword(Integer password) 
this . password = password; 
pub1ic void setList(List 1ist) 
this . 1ist = list; 
password=" + password + 
Override
public String toString() { 
return "User [username=" + user ame + ", 
", list=" + list + "1";
}}

( 2 com.itheima.assemble 包中,创建配置文件 beans5.xml ,在配置文件中通过构造注入和设值注入的方式装配 User 类的实例
beans5.xml

 
 
< 一!.使用构造沌入厅式装配 User 实例一〉
  
  
  
  
  
 " nstructorvaluel" 
 "construct。凹alue2"
  
  
  

  
 
  
< !一 注入 list 集合-->
  
  
 "setlistvaluel" 
 "setlistvalue2" 
  
  
  
 

( 3 coithe ma.assemb 包中,创建测试类 Xm lB ean ssembleTest ,在类中分别获取
并输出配置文件 user1和 user2 例,
XmlBeanAssembl eTest.java

 package com . itheima . assemb1e ; 
 import org springframework context Applicatio Context;
 import  org .springframework . context . support . ClassPathXmlApplicationContext ; 
 public class XmlBeanAssembleTest ( 
 public static void main (String[) args) ( 
 //定义配置文件路径
 String xmlPath = " com/itheima/assemble/beans5 . xml "; 
 //加载配置文件
 ApplicationContext applicationContext = 
 new ClassPathXmlApplicationContext (xmlPath ); 
/ /构造方式输出结果
 System. out . println (applicationContext . getBean (" user1 " ) ) ; 
 //设值方式输出结果
 System. out . println(applicationContext . getBean( "user2 " )) ;
}}

执行程序后,控制台的输出结果
Spring+Spring MVC+MyBatis应用开发学习笔记(2)--Spring 中的Bean_第10张图片
2.5.2 基于Annotation 的装配
Spring 中,尽管使用 XML 配置文件可以实现 Bean 的装配工作,但如果应用中有很多 Bean时,会导致 XML 配置文件过于庸肿,给后续的维护和升级工作带来一定的困难 为此, Spring 提供了对 Annotation (注解)技术的全面支持Spring 中定义了一系列的注解,常用的注解如下所示
• @Component: 可以使用此注解描述 Spring 中的 Bean ,但它是一个泛化的概念,仅仅表示一个组件 (Bean ,并且可以作用在任何层次 使用时只需将该注解标注在相应类上即可
• @Repository: 用于将数据访问层( DAO 层)的类标识为 Spring 中的 Bean ,其功能与@Component 相同
• @Service: 通常作用在业务层( Service ,用于将业务层的类标识为 Spring 中的 Bean其功能与@Component 相同
• @Controller: 通常作用在控制层(如 Spring MVC Controller ,用于将控制层的类标识Spring 中的 Bean ,其功能与@Component 相同
• @Autowired: 用于对 Bean 的属性变量、属性的 setter 方法及构造方法进行标注,配合对应的注解处理器完成 Bean 的自动配置工作 默认按照 Bean 的类型进行装配
• @Resource: 其作用与 Autowired 一样 其区别在于@Autowired 默认按照 Bean 类型装配,而@Resource 默认按照 Bean 实例名称进行装配 @Resource 中有两个重要属性: name、 type。 Spring name 属性解析为 Bean 实例名称, type 属性解析为 Bean 实例类型 如果指定 name 属性,贝IJ 按实例名称进行装配;如果指定 type 属性,则按 Bean 类型进行装配;如果都不指定,则先按 Bean 实例名称装配,如果不能匹配,再按照 Bean 类型进行装自己;如果都无法匹配,则抛出 NoSuchBeanDefinitionException 异常
• @Qualifier: @Autowired 注解配合使用,会将默认的按 Bean 类型装配修改为接 Bean的实例名称装配, Bean 的实例名称由 @Qualifier 注解的参数指定
在上面几个注解中,虽然@Repository @Service @Controller 功能与@Component 注解的功能相同,但为了使标注类本身用途更加清晰,建议在实际开发中使用@Repository @Service@Controller 分别对实现类进行标注。
通过一个案例来演示如何通过这些注解来装配 Bean
( 1 )在 chapter02 项目的 src 目录下,创建一个 com itheima.annotation 包,在该包中创建接口 UserDao ,并在接口中定义一个 saveO 方法
UserDao.java

package com .itheima.annotation; 
public interface UserDao { 
public void save(); }

(2 )在 com. itheima. annotation 包中,创建 UserDao 接口的实现类 UserDaolmpl ,该类需要实现接口中的 saveO 方法。
UserDaolmpl.java

package com.itheima.annotation; 
import org.springframework.stereotype.Repository; 
@Repository ("userDao" ) 
public class UserDaolmpl implements UserDao{ 
public void save() { 
System.out.println("userdao...save..."); }}

(3 )在 com.itheima .annotation 包中,创建接 UserService ,在接口中同样定义一个 saveO
方法,
UserService.java

package com.itheima.annotation; 
public interface UserService { 
public void save(); }
(4 )在 com itheima.annotation 包中,创建 UserService 接口的实现类 UserServicelmpl该类需要实现接口中的 saveO 方法
 UserServicelmpl.java 
package com.itheima.annotation; 
import javax.annotation.Resource; 
import org.springframework.stereotype.Service; 
@Service("userService") 
public class UserServicelmpl implements UserService{ 
@Resource(name="userDao") 
private UserDao userDao; 
public void save() { 
//调用 userDao 中的 save 方法
i8.usarDao.save();
System. out. println ("userservice. . . . save. . . ") ;
}
}

(5 )在 com itheima.annotation 包中,创建控制器类 UserControler
UserController.java

package com.itheima.annotation; 
 import javax.annotation.Resource; 
 import org.springframework.stereotype.Controller; 
 @Controller("userController") 
 public class UserController { 
 @Resource(næ ="userService")
 private UserService userService; 
 public void save() { 
 this.userService.sa鸭();
 System. out. println ("userController. . . save. . . ") ; 
 }
}

(6 )在 com. itheima.annotation 包中,创建配置文件 beans6.xml ,在配置文件中编写基于Annotation 装配的代码
beans6.xml

 
  
< !一使用 context 命名空间,在配置文件中开启相应的注解处理器一〉
  
< !一分别定义 Bean 实例 -->
  
 
 
 

(7 )com.itheima .annotation 包中,创建测试类 AnnotationA sse mbleT est ,在类中编写测试方法并定义配置文件的路径,然后通过 Sp ring 容器加载配置文件并获取 serController例,最后调用实例中的 saveO 方法
AnnotationAssemble Test.java

package com . itheima.annotation ; 
 irnport org .springfrarnework . context .ApplicationContext ; 
 irnport 4 org . springfrarnework . context . support.ClassPathXrnlApplicationCöntext ; 
 public class AnnotationAssernbleTest { 
 public static void rnain(String[] args) { 
 / /定义配置文件路径
 String xmlPath = "com/itheirna/annotation/beans6.xrnl "; 
 / /加载配置文件
 ApplicationContext applicationContext = 
 pew ClassPathXmlApplicatioηContext(xrnlPath) ; 
 //获取 UserController 实例
 UserController userController = 
 (UserController) applicationContext . getBean( "userController "); 
 //调用 UserController 中的 save () 方法
 userController . save( ); 
}}

执行程序后,控制台的输出结果
Spring+Spring MVC+MyBatis应用开发学习笔记(2)--Spring 中的Bean_第11张图片
2.5.3 自动装配
虽然使用注解的方式装配 Bean ,在一定程度上减少了配置文件中的代码量,但是也有企业项目中,是没有使用注解方式开发的,那么有没有什么办法既可以减少代码量,又能够实现 Bean 的装配呢?答案是肯定的, Spring 元素中包含一个 autowire 属性,我们可以通过设置autowire 的属性值来自动装配 Bean 所谓自动装配,就是将一个 Bean 自动地注入到其他 Bean和Property中。autowíre 属性有5 个值,
Spring+Spring MVC+MyBatis应用开发学习笔记(2)--Spring 中的Bean_第12张图片
( 1 )修改前面的文件 UserServicelmpl 和文件 2-18 UserControler,分别在文件中增加类属性的 setter 方法
(2 )修改配置文件 beans6.xml ,将配置文件修改成自动装配形式

 
 
  
  
  
 

执行程序后,控制台的输出结果如Spring+Spring MVC+MyBatis应用开发学习笔记(2)--Spring 中的Bean_第13张图片

你可能感兴趣的:(SSM)