您好,登錄后才能下訂單哦!
本文源碼:GitHub·點(diǎn)這里 || GitEE·點(diǎn)這里
Bean的概念:Spring框架管理的應(yīng)用程序中,由Spring容器負(fù)責(zé)創(chuàng)建,裝配,設(shè)置屬性,進(jìn)而管理整個(gè)生命周期的對(duì)象,稱為Bean對(duì)象。
Spring最傳統(tǒng)的Bean的管理方式。
<bean id="userInfo" class="com.spring.mvc.entity.UserInfo">
<property name="name" value="cicada" />
</bean>
ApplicationContext context01 = new ClassPathXmlApplicationContext("/bean-scan-02.xml");
UserInfo userInfo = (UserInfo)context01.getBean("userInfo") ;
System.out.println(userInfo.getName());
在實(shí)際開(kāi)發(fā)中:通常使用注解 取代 xml配置文件。
@Component <==> <bean class="Class">
@Component("id") <==> <bean id="id" class="Class">
@Repository :Mvc架構(gòu)中Dao層Bean的注解
@Service:Mvc架構(gòu)中Service層Bean的注解
@Controller:Mvc架構(gòu)中Controller層Bean的注解
// 1、注解代碼塊
@Component("infoService")
public class InfoServiceImpl implements InfoService {
@Override
public void printName(String name) {
System.out.println("Name:"+name);
}
}
// 2、配置代碼塊
@ComponentScan // 組件掃描注解
public class BeanConfig {
}
@RunWith(SpringJUnit4Cla***unner.class)
@ContextConfiguration(classes = BeanConfig.class)
public class Test01 {
@Autowired
private InfoService infoService ;
@Test
public void test1 (){
infoService.printName("cicada");
System.out.println(infoService==infoService);
}
}
上面使用 ComponentScan 注解,也可在配置文件進(jìn)行統(tǒng)一的配置,效果相同,還簡(jiǎn)化代碼。
<context:component-scan base-package="com.spring.mvc" />
這種基于Configuration注解,管理Bean的創(chuàng)建,在SpringBoot和SpringCloud的框架中,十分常見(jiàn)。
@Configuration // 配置類注解
public class UserConfig {
@Bean
public UserInfo userInfo (){
System.out.println("userInfo...");
return new UserInfo() ;
}
}
@RunWith(SpringJUnit4Cla***unner.class)
@ContextConfiguration(classes = UserConfig.class)
public class Test03 {
@Autowired
private UserInfo userInfo ;
@Autowired
private UserInfo userInfo1 ;
@Test
public void test1 (){
/*
* userInfo...
* true
*/
System.out.println(userInfo==userInfo1);
}
}
上面是Bean的裝配幾種常見(jiàn)方式,下面來(lái)看看Bean屬性值設(shè)置,這里就基于Xml配置的方式。
<!-- 配置Employee公共屬性 -->
<bean id="emp1" class="com.spring.mvc.entity.Employee">
<property name="name" value="cicada" />
<property name="id" value="1" />
</bean>
<bean id="emp2" class="com.spring.mvc.entity.Employee">
<property name="name" value="smile" />
<property name="id" value="2" />
</bean>
<!-- 配置Department屬性 -->
<bean id="department" class="com.spring.mvc.entity.Department">
<!-- 普通屬性值的注入 -->
<property name="name" value="IT部門" />
<!-- 給數(shù)組注入值 -->
<property name="empName">
<list>
<value>empName1</value>
<value>empName2</value>
<value>empName3</value>
</list>
</property>
<!-- 給List注入值:可以存放相同的值 -->
<property name="empList">
<list>
<ref bean="emp1"/>
<ref bean="emp2"/>
<ref bean="emp1"/>
</list>
</property>
<!-- 配置Set屬性,相同的對(duì)象會(huì)被覆蓋 -->
<property name="empSet">
<set>
<ref bean="emp1"/>
<ref bean="emp2"/>
<ref bean="emp1"/>
</set>
</property>
<!-- 配置Map屬性,key相同的話,后面的值會(huì)覆蓋前面的 -->
<property name="empMap">
<map>
<entry key="1" value-ref="emp1" />
<entry key="2" value-ref="emp2" />
<entry key="2" value-ref="emp1" />
</map>
</property>
<!-- 配置屬性集合 -->
<property name="pp">
<props>
<prop key="pp1">Hello</prop>
<prop key="pp2">World</prop>
</props>
</property>
</bean>
public class Test05 {
@Test
public void test01 (){
ApplicationContext context = new ClassPathXmlApplicationContext("/bean-value-03.xml");
Department department = (Department) context.getBean("department");
System.out.println(department.getName());
System.out.println("--------------------->String數(shù)組");
for (String str : department.getEmpName()){
System.out.println(str);
}
System.out.println("--------------------->List集合");
for (Employee smp : department.getEmpList()){
System.out.println(smp.getId()+":"+smp.getName());
}
System.out.println("--------------------->Set集合");
for (Employee emp : department.getEmpSet()){
System.out.println(emp.getId()+":"+emp.getName());
}
System.out.println("--------------------->Map集合");
for (Map.Entry<String, Employee> entry : department.getEmpMap().entrySet()){
System.out.println(entry.getKey()+":"+entry.getValue().getName());
}
System.out.println("--------------------->Properties");
Properties pp = department.getPp();
System.out.println(pp.get("pp1"));
System.out.println(pp.get("pp2"));
}
}
根據(jù)配置的參數(shù)個(gè)數(shù)和類型,去映射并加載Bean的構(gòu)造方法。
<!-- 這里配置2個(gè)參數(shù),所有調(diào)用2個(gè)參數(shù)的構(gòu)造函數(shù) -->
<bean id="employee" class="com.spring.mvc.entity.Employee">
<constructor-arg index="0" type="java.lang.String" value="cicada"/>
<constructor-arg index="1" type="int" value="1"/>
</bean>
public class Test06 {
@Test
public void test01 (){
ApplicationContext context = new ClassPathXmlApplicationContext("/bean-value-04.xml");
Employee employee = (Employee) context.getBean("employee");
System.out.println(employee.getId()+":"+employee.getName());
}
}
<!-- 配置父類信息 -->
<bean id="student" class="com.spring.mvc.entity.Student">
<property name="name" value="Spring" />
<property name="age" value="22" />
</bean>
<!-- 配置子類信息 -->
<bean id="grade" class="com.spring.mvc.entity.Grade">
<!-- 覆蓋 -->
<property name="name" value="Summer" />
<property name="degree" value="大學(xué)" />
</bean>
public class Test07 {
@Test
public void test01 (){
ApplicationContext context = new ClassPathXmlApplicationContext("/bean-value-05.xml");
Grade grade = (Grade) context.getBean("grade");
/* Summer;0;大學(xué) */
System.out.println(grade.getName()+";"+grade.getAge()+";"+grade.getDegree());
}
}
作用域:用于確定spring創(chuàng)建bean實(shí)例個(gè)數(shù),比如單例Bean,原型Bean,等等。
類型 | 說(shuō)明 |
---|---|
singleton | IOC容器僅創(chuàng)建一個(gè)Bean實(shí)例,IOC容器每次返回的是同一個(gè)單例Bean實(shí)例,默認(rèn)配置。 |
prototype | IOC容器可以創(chuàng)建多個(gè)Bean實(shí)例,每次返回的Bean都是新的實(shí)例。 |
request | 每次HTTP請(qǐng)求都會(huì)創(chuàng)建一個(gè)新的Bean,適用于WebApplicationContext環(huán)境。 |
session | 同一個(gè)HTTP Session共享一個(gè)Bean實(shí)例。不同HTTP Session使用不同的實(shí)例。 |
global-session | 同session作用域不同的是,所有的Session共享一個(gè)Bean實(shí)例。 |
在Spring框架中Bean的生命周期非常復(fù)雜,過(guò)程大致如下:實(shí)例化,屬性加載,初始化前后管理,銷毀等。下面基于一個(gè)案例配置,會(huì)更加的清楚。
public class BeanLife implements BeanNameAware {
private String name ;
public String getName() {
return name;
}
public void setName(String name) {
System.out.println("設(shè)置名稱:"+name);
this.name = name;
}
@Override
public void setBeanName(String value) {
System.out.println("BeanNameAware..SetName:"+value);
}
public void initBean() {
System.out.println("初始化Bean..");
}
public void destroyBean() {
System.out.println("銷毀Bean..");
}
public void useBean() {
System.out.println("使用Bean..");
}
@Override
public String toString() {
return "BeanLife [name = " + name + "]";
}
}
實(shí)現(xiàn)BeanPostProcessor接口。
public class BeanLifePostProcessor implements BeanPostProcessor {
// 初始化之前對(duì)bean進(jìn)行增強(qiáng)處理
@Override
public Object postProcessBeforeInitialization(Object obj, String beanName) throws BeansException {
System.out.println("初始化之前..."+beanName);
return obj ;
}
// 初始化之后對(duì)bean進(jìn)行增強(qiáng)處理
@Override
public Object postProcessAfterInitialization(Object obj, String beanName) throws BeansException {
System.out.println("初始化之后..."+beanName);
// 改寫B(tài)ean的名稱
if (obj instanceof BeanLife){
BeanLife beanLife = (BeanLife)obj ;
beanLife.setBeanName("myBeanLifeTwo");
return beanLife ;
}
return obj ;
}
}
<!-- 加載Bean的處理器 -->
<bean class="com.spring.mvc.BeanLifePostProcessor" />
<!-- 指定初始化和銷毀方法 -->
<bean id="beanLife" class="com.spring.mvc.entity.BeanLife"
init-method="initBean" destroy-method="destroyBean">
<property name="name" value="myBeanLifeOne" />
</bean>
測(cè)試代碼
public class Test08 {
@Test
public void test01 (){
ApplicationContext context = new ClassPathXmlApplicationContext("/bean-value-06.xml");
BeanLife beanLife = (BeanLife) context.getBean("beanLife");
System.out.println("測(cè)試結(jié)果BeanLife:"+beanLife.getName()) ;
beanLife.useBean();
// 關(guān)閉容器
((AbstractApplicationContext) context).close();
}
}
1、設(shè)置名稱:myBeanLifeOne
2、BeanNameAware..SetName:beanLife
3、初始化之前...beanLife
4、初始化Bean..
5、初始化之后...beanLife
6、BeanNameAware..SetName:myBeanLifeTwo
7、測(cè)試結(jié)果BeanLife:myBeanLifeOne
8、使用Bean..
9、銷毀Bean..
這里梳理Bean的生命周期,過(guò)程十分清晰。
GitHub·地址
https://github.com/cicadasmile/spring-mvc-parent
GitEE·地址
https://gitee.com/cicadasmile/spring-mvc-parent
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。