文章目录
- 1、Bean的配置
- 1.1、配置方式
- 2、Bean的实例化
- 2.1、构造器实例化
- 2.2、静态工厂方式实例化
- 2.3、实例工厂方式实例化
- 3、Bean的作用域
- 3.1、作用域的种类
- 4、Bean的生命周期
- 5、Bean的装配方式
- 5.1、基于XML的装配
- 5.2、基于Annotation的装配
- 5.3、自动装配
1、Bean的配置
1.1、配置方式
- 基于xml文件
- Properties文件
在实际开发中,最常使用的是XMl格式的配置方式!
2、Bean的实例化
实例化Bean的方式有三种:
- 构造器实例化
- 静态工厂实例化
- 实例工厂实例化
2.1、构造器实例化
构造器实例化是指Spring容器通过Bean对应类中默认的无参构造方法来实例化Bean。
默认的无参构造方法来实例化Bean
package com.nynu.qdy.instance.constructor;
public class Bean1 {
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd"><bean id="bean1" class="com.nynu.qdy.instance.constructor.Bean1" /></beans>
2.2、静态工厂方式实例化
使用静态工厂要求创建一个静态工厂的方法来创建Bean的实例,其Bean配置中的class属性所指定的不再是Bean实例的实现类,而是静态工厂类,同时还需要使用factory-method属性来指定所创建的静态工厂方法。
建一个静态工厂的方法来创建Bean的实例
package com.nynu.qdy.instance.static_factory;public class MyBean2Factory {// 使用自己的工厂建立Bean2实例public static Bean2 createBean() {return new Bean2();}
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd"><!-- 静态工厂方式实例化Bean:class:指向静态工厂的全类名factory-method:需要调用的静态工厂方法名--><bean id="bean2"class="com.nynu.qdy.instance.static_factory.MyBean2Factory"factory-method="createBean" ></bean></beans>
2.3、实例工厂方式实例化
此种方式的工厂类中,不再使用静态方法创建Bean实例,而是采用直接创建Bean实例的方式。同时,在配置文件中,需要实例化的Bean也不是通过class属性直接指向的实例化类,而是通过factory-bean属性指向配置的实例化工厂,然后使用factory-bean属性确定使用工厂中的哪个方法。
通过factory-bean属性指向配置的实例化工厂
package com.nynu.qdy.instance.factory;public class MyBean3Factory {public MyBean3Factory() {System.out.println("bean3工厂实例化");}// 创建Bean3实例的方法public Bean3 createBean() {return new Bean3();}
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd"><!-- 配置工厂 --><bean id="myBean3Factory"class="com.nynu.qdy.instance.factory.MyBean3Factory"></bean><!-- 使用factory-bean属性指向配置的实例工厂, 使用factory-method属性确定使用工厂中的哪个方法 --><bean id="bean3" factory-bean="myBean3Factory"factory-method="createBean"></bean></beans>
3、Bean的作用域
3.1、作用域的种类
通过Spring容器创建一个Bean的实例时,不仅可以完成Bean的实例化,还可以为Bean指定特定的作用域。bean的作用域默认都是单例的,但是可以通过scope[作用域]来设置。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd">
<!-- scope:作用域--><bean id="scope" class="com.nynu.qdy.scope.Scope"scope="singleton"></bean><bean id="scope1" class="com.nynu.qdy.scope.Scope"scope="prototype"></bean></beans>
4、Bean的生命周期
Spring IOC容器对bean的生命周期的管理过程是:
- 通过构造器或者工厂方法创建Bean实例
- 设置Bean的属性 调用Bean的初始化方法
- 使用Bean
- 关闭容器,调用Bean的销毁方法
5、Bean的装配方式
Bean的装配方式:
- 基于XML的装配、
- 基于注解的装配(Annotation)、
- 自动装配、
5.1、基于XML的装配
基于xml的装配方式:
- 设值注入(Setter Injection)
- 构造注入(Constructor Injection)
在Spring实例化Bean的过程中,Spring首先会调用Bean的默认构造方法来实例化Bean对象, 然后通过反射的方式调用setter方法来注入属性值。因此,设值注入要求一一个 Bean必须满足以下两点要求。
- Bean类必须提供一个默认的无参构造方法。
- Bean类必须为需要注入的属性提供对应的setter方法
使用设值注入时, 在Spring配置文件中,需要使用元素的子元素来为每个属性注入值;而使用构造注入时,在配置文件里,需要使用元素的子元素 来定义构造方法的参数,可以使用其value 属性(或子元素)来设置该参数的值。
下面通过一个案例来演示基于XML方式的Bean的装配:
1.编写JavaBean
package com.nynu.qdy.assemble;import java.util.List;public class User {private String username;private Integer password;private List<String> list;/*
*由于使用构造注入,需要有其有参和无参的构造方法。同时,为了输出时能够看到结果,还重写了其属性的toString方法
*//** 1.使用构造注入 1.1提供带所有参数的有参构造方法*/public User(String username, Integer password, List<String> list) {super();this.username = username;this.password = password;this.list = list;}/** 2.使用设值注入 2.1提供默认构造参数 2.2为所有属性提供setter方法*/public User() {super();}public void setUsername(String username) {this.username = username;}public void setPassword(Integer password) {this.password = password;}public void setList(List<String> list) {this.list = list;}@Overridepublic String toString() {return "User [username=" + username + ", password=" + password + ", list=" + list + "]";}
}
2.编写配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd"><!-- 1.使用构造注入方式装配User实例:constructor-arg:用于定义构造方法的参数,index属性:表示索引(从0开始)value属性:用于设置注入的值list子元素:用于User来中对应的list集合属性注入值--><bean id="user1" class="com.nynu.qdy.assemble.User"><constructor-arg index="0" value="tom"></constructor-arg><constructor-arg index="1" value="123456"></constructor-arg><constructor-arg index="2"><list><value>"constructorvalue1"</value><value>"constructorvalue2"</value></list></constructor-arg></bean><!-- 2.使用设值注入方式装配User实例:property元素:用于调用Bean实例中的setter方法完成属性赋值从而完成依赖注入lsit子元素:用于User来中对应的list集合属性注入值--><bean id="user2" class="com.nynu.qdy.assemble.User"><property name="username" value="张三"></property><property name="password" value="654321"></property><!-- 注入list集合 --><property name="list"><list><value>"setlistvalue1"</value><value>"setlistvalue2"</value></list></property></bean>
</beans>
3.测试
package com.nynu.qdy.assemble;import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;public class XmlBeanAssembleTest {@SuppressWarnings("resource")public static void main(String[] args) {// 定义配置文件路径String xmlPath = "com/nynu/qdy/assemble/beans5.xml";// ApplicationContext在加载配置文件时,对Bean进行实例化ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath);// 构造方式输出结果System.out.println(applicationContext.getBean("user1"));// 设值方式输出结果System.out.println(applicationContext.getBean("user2"));}
}
4.结果
User [username=tom, password=123456, list=["constructorvalue1", "constructorvalue2"]]
User [username=张三, password=654321, list=["setlistvalue1", "setlistvalue2"]]
5.2、基于Annotation的装配
Spring中定义了一系列的注解,常用的注解如下所示。
- @Component: 可以使用此注解描述Sping中的Ban.但它是个泛化的概念,仅仅表示一个组件(Bean),并且可以作用在任何层次。使用时只需将该注解标注在相应类上即可 。
- @Repository:用于将数据访问层(Dao层)的类表识为Spring中的Bean,其功能与@Component相同。
- @Service:通常作用在业务层( Semice层),用于将业务层的类标识为Spring中的Bean,其功能与@Component相同。
- @ Controller:通常作用在控制层(如Spring MVC的Controller).用于将控制层的类标识为Spring中的Bean,其功能与@Component相同。
- @Autowired:用于对Bean的属性变量、属性的stter方法及构造方法进行标注,配合对应的注解处理器完成Been的自动配置工作。默认按照Bean的类型进行装配。
- @Resource:其作用与@Autowited-一样。 其区别在于@Autowired默认按照Bean类型装配,而@Resource默认按照Bean实例名称进行装配。@Resource 中有两个重要属性: name和type。Spring将name属性解析为Bean实例名称,type属性解析为Bean实例类型。如果指定name属性,则按实例名称进行装配;如果指定type属性,则按Bean类型进行装配;如果都不指定,则先按Bean实例名称装配,如果不能匹配,再按照Bean类型进行装配;如果都无法匹配,则抛出NoSuchBeanDefintionException异常。
- @Qulifier: 与@Autowired注解配合使用,会将默认的按Bean类型装配修改为按Bean 的实例名称装配,Bean的实例名称由@Qualifer注解的参数指定。
下面通一个案例来演示如何通过这些注解来装配Bean
1.UserDao 接口
package com.nynu.qdy.annotation;public interface UserDao {public void save();
}
2.接口实现类
package com.nynu.qdy.annotation;import org.springframework.stereotype.Repository;/** @Reposrtory:将UserDaoImpl类表示为Spring中的Bean* 相当于<bean id="userDao" class="com.nynu.qdy.annotation.UserDaoImpl"/>*/
@Repository("userDao")
public class UserDaolmpl implements UserDao {public void save() {System.out.println("userdao...save....");}
}
3.UserService 接口
package com.nynu.qdy.annotation;public interface UserService {public void save();
}
4.UserServiceImpl实现类
package com.nynu.qdy.annotation;import javax.annotation.Resource;
import org.springframework.stereotype.Service;/** @Reposrtory:将UserServiceImpl类表示为Spring中的Bean* 相当于<bean id="UserService" * class="com.nynu.qdy.annotation.UserDaoServiceImpl"/>* @Resource:相当于配置文件中<property name="userDao" ref="userDao"/>*/
@Service("userService")
public class UserServicelmpl implements UserService {@Resource(name = "userDao") private UserDao userDao;public void save() {// 调用userDao中的save方法this.userDao.save();System.out.println("userservice....save....");}
}
5.控制器类
package com.nynu.qdy.annotation;import javax.annotation.Resource;
import org.springframework.stereotype.Controller;/** @Controller:相当于在配置文件中编写<bean id="userController"* class="com.nynu.qdy.annotation.UserController"/>* @Resource:相当于配置文件中编写<property name="userService" ref="userService"/>*/
@Controller("userController")
public class UserController {@Resource(name = "userService")private UserService userService;public void save() {this.userService.save();System.out.println("UserService...save....");}}
6.配置文件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"xsi:schemaLocation="http://www.springframework.org/schema/beanshttps://www.springframework.org/schema/beans/spring-beans-4.3.xsdhttp://www.springframework.org/schema/contexthttps://www.springframework.org/schema/context/spring-context-4.3.xsd"><!-- 使用context命名空间,在配置文件中开启相应的注解处理器 --><context:annotation-config /><!-- 分别定义3个Bean实例 --><bean id="userDao" class="com.nynu.qdy.annotation.UserDaolmpl" /><bean id="userService"class="com.nynu.qdy.annotation.UserServicelmpl" /><bean id="userController"class="com.nynu.qdy.annotation.UserController" /><!-- 使用context命名空间,通知Spring扫描指定包下的所有Bean类,进行注解解析 --><context:component-scanbase-package="com.nynu.qdy.annotation" />
</beans>
7.测试类
package com.nynu.qdy.annotation;import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;public class AnnotationAssembleTest {@SuppressWarnings("resource")public static void main(String[] args) {// 定义配置文件路径String xmlPath = "com/nynu/qdy/annotation/beans6.xml";// 加载配置文件ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath);// 获取UserControllerUserController userController = (UserController) applicationContext.getBean("userController");// 调用UserController中save()方法userController.save();}}
8.结果
userdao...save....
userController....save....
UserService...save....
9.提示
上述案例中如果使用@Autowire注解替换@Resource注解,也可以达到同样的效果。
5.3、自动装配
Spring可以通过设置aotowrie的属性来自动装配Bean,所谓自动装配,就是将一个Bean自动地装配到其他Bean的Property中。
名称 | 说明 |
---|---|
byName | 根据 Property 的 name 自动装配,如果一个 Bean 的 name 和另一个 Bean 中的 Property 的 name 相同,则自动装配这个 Bean 到 Property 中。 |
byType | 根据 Property 的数据类型(Type)自动装配,如果一个 Bean 的数据类型兼容另一个 Bean 中 Property 的数据类型,则自动装配。 |
constructor | 根据构造方法的参数的数据类型,进行 byType 模式的自动装配。 |
autodetect | 如果发现默认的构造方法,则用 constructor 模式,否则用 byType 模式。 |
no | 默认情况下,不使用自动装配,Bean 依赖必须通过 ref 元素定义。 |
下面通过修改案例来演示使用自动装配
1.修改UserServiceImpl文件和UserController文件,分别在文件中增加类属性的setter方法。
2.修改beans.xml文件,添加autowire属性
<?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"xsi:schemaLocation="http://www.springframework.org/schema/beanshttps://www.springframework.org/schema/beans/spring-beans-4.3.xsdhttp://www.springframework.org/schema/contexthttps://www.springframework.org/schema/context/spring-context-4.3.xsd"><!-- 使用context命名空间,在配置文件中开启相应的注解处理器 --><context:annotation-config /><!-- 分别定义3个Bean实例 --><bean id="userDao" class="com.nynu.qdy.annotation.UserDaolmpl" /><bean id="userService"class="com.nynu.qdy.annotation.UserServicelmpl" autowire="byName"/><bean id="userController"class="com.nynu.qdy.annotation.UserController" autowire="byName"/><!-- 使用context命名空间,通知Spring扫描指定包下的所有Bean类,进行注解解析 --><context:component-scanbase-package="com.nynu.qdy.annotation" />
</beans>
3.结果
userdao...save....
userController....save....
UserService...save....
4.提示
使用 @Autowired 注解自动装配Bean,使用@Autowired注解自动装配具有类型兼容的单个Bean属性。可以在构造器、普通字段、一切具有参数的方法上使用 @Autowired 注解。
- @Autowired也可以用在数组上,Spring会将所有匹配的Bean自动装配进数组。
- @Autowired也可以用在集合上,Spring会判断该集合的类型,然后自动装配所有类型兼容的Bean。
- @Autowired也可以用在Map上,若key为String类型,Spring将Bean的名称作为key,Bean本身作为值自动装配所有类型兼容的的Bean。
也可以使用 @Resource 或 @Inject 自动装配Bean,功能与 @Autowired 类似,建议使用@Autowired注解。