本文源碼:GitHub·點這里 || GitEE·點這里
一、裝配方式
Bean的概念:Spring框架管理的應用程序中,由Spring容器負責創建,裝配,設置屬性,進而管理整個生命周期的對象,稱為Bean對象。
1、XML格式裝配
Spring最傳統的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());
2、注解掃描
在實際開發中:通常使用注解 取代 xml配置文件。
@Component <==> <bean class="Class">
@Component("id") <==> <bean id="id" class="Class">
@Repository :Mvc架構中Dao層Bean的注解
@Service:Mvc架構中Service層Bean的注解
@Controller:Mvc架構中Controller層Bean的注解
// 1、注解代碼塊
@Component("infoService")
public class InfoServiceImpl implements InfoService {@Overridepublic void printName(String name) {System.out.println("Name:"+name);}
}// 2、配置代碼塊
@ComponentScan // 組件掃描注解
public class BeanConfig {}
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = BeanConfig.class)
public class Test01 {@Autowiredprivate InfoService infoService ;@Testpublic void test1 (){infoService.printName("cicada");System.out.println(infoService==infoService);}
}
3、XML配置掃描
上面使用 ComponentScan 注解,也可在配置文件進行統一的配置,效果相同,還簡化代碼。
<context:component-scan base-package="com.spring.mvc" />
4、Java代碼裝配
這種基于Configuration注解,管理Bean的創建,在SpringBoot和SpringCloud的框架中,十分常見。
@Configuration // 配置類注解
public class UserConfig {@Beanpublic UserInfo userInfo (){System.out.println("userInfo...");return new UserInfo() ;}
}
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = UserConfig.class)
public class Test03 {@Autowiredprivate UserInfo userInfo ;@Autowiredprivate UserInfo userInfo1 ;@Testpublic void test1 (){/** userInfo...* true*/System.out.println(userInfo==userInfo1);}
}
二、屬性值設置
上面是Bean的裝配幾種常見方式,下面來看看Bean屬性值設置,這里就基于Xml配置的方式。
1、基礎類型和集合
<!-- 配置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部門" /><!-- 給數組注入值 --><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屬性,相同的對象會被覆蓋 --><property name="empSet"><set><ref bean="emp1"/><ref bean="emp2"/><ref bean="emp1"/></set></property><!-- 配置Map屬性,key相同的話,后面的值會覆蓋前面的 --><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 {@Testpublic 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數組");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"));}
}
2、配置構造函數
根據配置的參數個數和類型,去映射并加載Bean的構造方法。
<!-- 這里配置2個參數,所有調用2個參數的構造函數 -->
<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 {@Testpublic void test01 (){ApplicationContext context = new ClassPathXmlApplicationContext("/bean-value-04.xml");Employee employee = (Employee) context.getBean("employee");System.out.println(employee.getId()+":"+employee.getName());}
}
3、配置繼承關系
<!-- 配置父類信息 -->
<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="大學" />
</bean>
public class Test07 {@Testpublic void test01 (){ApplicationContext context = new ClassPathXmlApplicationContext("/bean-value-05.xml");Grade grade = (Grade) context.getBean("grade");/* Summer;0;大學 */System.out.println(grade.getName()+";"+grade.getAge()+";"+grade.getDegree());}
}
三、作用域
作用域:用于確定spring創建bean實例個數,比如單例Bean,原型Bean,等等。
類型說明
| singleton | IOC容器僅創建一個Bean實例,IOC容器每次返回的是同一個單例Bean實例,默認配置。 |
| prototype | IOC容器可以創建多個Bean實例,每次返回的Bean都是新的實例。 |
| request | 每次HTTP請求都會創建一個新的Bean,適用于WebApplicationContext環境。 |
| session | 同一個HTTP Session共享一個Bean實例。不同HTTP Session使用不同的實例。 |
| global-session | 同session作用域不同的是,所有的Session共享一個Bean實例。 |
四、生命周期
在Spring框架中Bean的生命周期非常復雜,過程大致如下:實例化,屬性加載,初始化前后管理,銷毀等。下面基于一個案例配置,會更加的清楚。
1、編寫BeanLife類
public class BeanLife implements BeanNameAware {private String name ;public String getName() {return name;}public void setName(String name) {System.out.println("設置名稱:"+name);this.name = name;}@Overridepublic 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..");}@Overridepublic String toString() {return "BeanLife [name = " + name + "]";}
}
2、定制加載過程
實現BeanPostProcessor接口。
public class BeanLifePostProcessor implements BeanPostProcessor {// 初始化之前對bean進行增強處理@Overridepublic Object postProcessBeforeInitialization(Object obj, String beanName) throws BeansException {System.out.println("初始化之前..."+beanName);return obj ;}// 初始化之后對bean進行增強處理@Overridepublic Object postProcessAfterInitialization(Object obj, String beanName) throws BeansException {System.out.println("初始化之后..."+beanName);// 改寫Bean的名稱if (obj instanceof BeanLife){BeanLife beanLife = (BeanLife)obj ;beanLife.setBeanName("myBeanLifeTwo");return beanLife ;}return obj ;}
}
3、配置文件
<!-- 加載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>
4、測試過程
public class Test08 {@Testpublic void test01 (){ApplicationContext context = new ClassPathXmlApplicationContext("/bean-value-06.xml");BeanLife beanLife = (BeanLife) context.getBean("beanLife");System.out.println("測試結果BeanLife:"+beanLife.getName()) ;beanLife.useBean();// 關閉容器((AbstractApplicationContext) context).close();}
}
1、設置名稱:myBeanLifeOne
2、BeanNameAware..SetName:beanLife
3、初始化之前...beanLife
4、初始化Bean..
5、初始化之后...beanLife
6、BeanNameAware..SetName:myBeanLifeTwo
7、測試結果BeanLife:myBeanLifeOne
8、使用Bean..
9、銷毀Bean..
這里梳理Bean的生命周期,過程十分清晰。
五、源代碼地址
GitHub·地址
https://github.com/cicadasmile/spring-mvc-parent
GitEE·地址
https://gitee.com/cicadasmile/spring-mvc-parent
總結
以上是生活随笔為你收集整理的Spring 框架基础(02):Bean的生命周期,作用域,装配总结的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。