使用XML方式裝配Bean
1.實例化Bean的三種方式
- 使用構造方法實例化
在spring容器中配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:p="http://www.springframework.org/schema/p"
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.xsd">
<!-- 第一種方式 默認構造 -->
<bean id="demo1User" class="cn.spring.demo.User"></bean>
</beans>
測試
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
User user = (User)applicationContext.getBean("demo1User"); //相當於:User user = new User(); 直接創建實例
System.out.println(user);
}
- 使用靜態工程方法實例化
在spring容器中配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:p="http://www.springframework.org/schema/p"
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.xsd">
<!-- 第二種方式 靜態工廠方法 , 沒有工廠的實例對象-->
<bean id="demo2User" class="cn.spring.demo.Demo2BeanFactory" factory-method="getDemo2Bean"></bean>
</beans>
提供工廠類
public class Demo2BeanFactory {
public Demo2BeanFactory(){
System.out.println("demo2 不執行");
}
/**
* 必須提供 static方法
* @return
*/
public static User getDemo2Bean(){
return new User();
}
}
測試
public static void main(String[] args) {
ApplicationContext applicationContext =
new ClassPathXmlApplicationContext("applicationContext.xml");
User user = (User)applicationContext.getBean("demo2User");//相當於: User user = BeanFatory.getUserBean(); 通過工廠的靜態方法獲得需要的內容
System.out.println(user);
}
- 使用實例工廠方法
在Spring容器的配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:p="http://www.springframework.org/schema/p"
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.xsd">
<!-- 第三種方式 實例工廠方法
* 先實例工廠
* 通過實例工廠執行具體的方法
-->
<bean id="demo3BeanFactory" class="cn.spring.demo.Demo3BeanFactory"></bean>
<bean id="demo3User" factory-bean="demo3BeanFactory" factory-method="getDemo2Bean"></bean>
</beans>
提供工廠類
public class Demo3BeanFactory {
public Demo3BeanFactory(){
//System.out.println("demo3 執行");
}
/**
* 非靜態方法
* @return
*/
public User getDemo2Bean(){
return new User();
}
}
測試
public static void main(String[] args) {
ApplicationContext applicationContext =
new ClassPathXmlApplicationContext("applicationContext.xml");
User user = (User)applicationContext.getBean("demo3User");//相當於:BeanFactory factory = new BeanFactory();//先創建工廠 User user = factory.getUserBean();//在通過工廠的實例對象,執行非靜態方法獲得具體內容
System.out.println(user);
}
2.spring容器中bean元素id和name屬性的區別
在spring容器中添加以下配置:
<bean id="helloService" class="cn.spring.demo.HelloService">
bean節點中Id和name的區別:
區別一:
id:指定唯一實例引用
name:可以指定多個實例引用,例如name=“名稱1,名稱2”
區別二:
id :id的命名要滿足XML對ID屬性命名規範
例如:必須以字母開始,可以使用字母、數字、連字符、下劃線、句話、冒號
name:如果Bean的名稱中含有特殊字符,就需要使用name屬性
例如:<bean name="# boy " class="cn.spring.demo.Boy"/>
因爲name屬性可以相同,所以後出現Bean會覆蓋之前出現的同名的Bean
總結:項目開發的時候,強烈要求用id,因爲id可以表示惟一引用。
3.Bean的作用域
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:p="http://www.springframework.org/schema/p"
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.xsd">
<!--bean 作用域
* singleton 單例,只創建一個實例。默認值
* prototype 多例,每一次都創建實例
* request,request範圍,request.setAttribute
* session,session範圍,session.setAttribute
* globalSession , prolet 分佈式門戶,sso(單點登錄)將不同的應用的數據保存到globalSession中,達到數據共享
-->
<bean id="person" class="cn.spring.demo.Person" scope="prototype"></bean>
</beans>
4.Bean的生命週期
- 4.1生命週期詳情
instantiate bean對象實例化
populate properties 封裝屬性
如果Bean實現BeanNameAware 執行 setBeanName
如果Bean實現BeanFactoryAware 或者 ApplicationContextAware 設置工廠 setBeanFactory 或者上下文對象 setApplicationContext
如果存在類實現 BeanPostProcessor(後處理Bean) ,執行postProcessBeforeInitialization
如果Bean實現InitializingBean 執行 afterPropertiesSet
調用<bean init-method="init">
指定初始化方法 init
如果存在類實現 BeanPostProcessor(處理Bean) ,執行postProcessAfterInitialization
執行業務處理
如果Bean實現 DisposableBean 執行 destroy
調用<bean destroy-method="customerDestroy">
指定銷燬方法 customerDestroy
測試代碼,實現類:
public class User implements BeanNameAware ,ApplicationContextAware,InitializingBean ,DisposableBean {
public User() {
System.out.println("1.構造方法執行");
}
private String username;
private String password;
public String getUsername() {
return username;
}
public void setUsername(String username) {
System.out.println("2 裝載屬性,調用setter方法");
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public void setBeanName(String name) {
System.out.println("3.通過BeanNameAware接口,獲得配置文件id屬性的內容:" + name);
}
@Override
public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException {
System.out.println("4.通過ApplicationContextAware接口,獲得Spring容器," + applicationContext);
}
/** 5 在後處理bean MyBeanPostProcessor.java 處 */
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("6.通過InitializingBean,確定屬性設置完成之後執行");
}
public void userInit(){
System.out.println("7.配置init-method執行自定義初始化方法");
}
/** 8 在後處理bean MyBeanPostProcessor.java 處 */
@Override
public void destroy() throws Exception {
System.out.println("9.通過DisposableBean接口,不需要配置的銷燬方法");
}
public void userDestroy(){
System.out.println("10.配置destroy-method執行自定義銷燬方法");
}
}
Spring容器
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:p="http://www.springframework.org/schema/p"
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.xsd">
<!--lifecycle 生命週期
1.構造方法執行
2 裝載屬性,調用setter方法
3.通過BeanNameAware接口,獲得配置文件id屬性的內容:lifeUser
4.通過ApplicationContextAware接口,獲得Spring容器
5.實現BeanPostProcessor後處理,初始化前,執行postProcessBeforeInitialization方法
6.通過InitializingBean,確定屬性設置完成之後執行
7.配置init-method執行自定義初始化方法
8.實現BeanPostProcessor後處理,在自定義初始化之後,執行postProcessAfterInitialization方法
//執行操作
9.通過DisposableBean接口,不需要配置的銷燬方法
10.配置destroy-method執行自定義銷燬方法
-->
<bean id="lifeUser" class="cn.spring.demo.User" init-method="userInit" destroy-method="userDestroy">
<property name="username" value="jack"></property>
<property name="password" value="1234"></property>
</bean>
<!-- 5.1配置 後處理bean -->
<bean class="cn.spring.demo.MyBeanPostProcessor"></bean>
</beans>
測試類
public static void main(String[] args) {
ClassPathXmlApplicationContext applicationContext =
new ClassPathXmlApplicationContext("applicationContext.xml");
System.out.println("---->" + applicationContext);
User user = (User) applicationContext.getBean("lifeUser");
System.out.println(user); //業務執行
//必須手動執行關閉,纔可以進行之後銷燬的操作
applicationContext.close();
}
/**
* 後處理bean處理程序
* 需要註冊給Spring容器,統一處理所有的bean,只需要註冊
*/
public class MyBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName)
throws BeansException {
if("lifeUser".equals(beanName)){
System.out.println("5. 實現BeanPostProcessor後處理Bean,初始化前 : " + beanName + ",bean實例: " + bean);
}
return bean; //返回當前bean,不做任何處理,可以生產代理類
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName)
throws BeansException {
if("lifeUser".equals(beanName)){
System.out.println("8. 實現BeanPostProcessor後處理Bean,在自定義初始化之後 : " + beanName);
}
return bean;
}
}
5.依賴注入Bean屬性
- 手動裝配—構造方法
public class User {
private String username;
private int age;
private String password;
private int money;
public User(int money,String password) { //構造1
this.password = password;
this.money = money;
}
public User(String username, int age) { //構造2
this.username = username;
this.age = age;
}
@Override
public String toString() {
return "User [username=" + username + ", age=" + age + ", password="
+ password + ", money=" + money + "]";
}
}
Spring容器
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:p="http://www.springframework.org/schema/p"
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.xsd">
<!-- 構造方法注入 -->
<bean id="injectConstructorUser" class="cn.spring.demo.User">
<constructor-arg index="0" value="1111"></constructor-arg>
<constructor-arg index="1" value="123456"></constructor-arg>
</bean>
</beans>
測試類
public static void main(String[] args) {
ApplicationContext applicationContext =
new ClassPathXmlApplicationContext("applicationContext.xml");
User user = (User) applicationContext.getBean("injectConstructorUser");
System.out.println(user); //業務執行
}
運行結果:User [username=null, age=0, password=123456, money=1111]
<bean id="injectConstructorUser" class="cn.spring.demo.User">
<constructor-arg index="0" value="1111" type="int"></constructor-arg>
<constructor-arg index="1" value="123456" type="java.lang.String"></constructor-arg>
</bean>
注意:在開發中爲了指定執行的是那個構造方法,一般代用index屬性和type屬性結合的方式
- 手動裝配—setter方法
public class User {
private String userName;
private String password;
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString() {
return "User [userName=" + userName + ", password=" + password + "]";
}
}
Spring容器
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:p="http://www.springframework.org/schema/p"
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.xsd">
<!-- setter方法 普通字段-->
<bean id="propertyInjectUser" class="cn.spring.demo.User">
<property name="userName" value="rose"></property>
<property name="password" value="5555"></property>
</bean>
</beans>
測試類
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
User user = (User) applicationContext.getBean("propertyInjectUser");
System.out.println(user); //業務執行
}
- 手動裝配—接口注入
將已有的方法增強,如何將一個prototype(多例) bean注入給singleton(單例) Bean
public class UserService {
private Dao dao = new UserMySqlDao();
public Dao getDao() {
return dao;
}
public void find(){
getDao().find();
}
}
public interface Dao {
public void find();
}
public class UserMySqlDao implements Dao {
public void find(){
System.out.println("mysql 查詢");
}
}
public class UserOracleDao implements Dao{
public void find(){
System.out.println("oracle 查詢");
}
}
Spring容器
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:p="http://www.springframework.org/schema/p"
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.xsd">
<!-- 不修改UserService原有代碼的前提下,擴展service -->
<bean id="methodUserService" class="cn.spring.demo.UserService">
<lookup-method name="getDao" bean="methodOracleDao"/>
</bean>
<bean id="methodOracleDao" class="cn.spring.demo.UserOracleDao"></bean>
</beans>
測試
public class TestService {
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
UserService userService = (UserService) applicationContext.getBean("methodUserService");
userService.find();
}
}
- 手動裝配—p命名空間
public class User {
private String userName;
private String password;
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString() {
return "User [userName=" + userName + ", password=" + password + "]";
}
}
Spring容器
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:p="http://www.springframework.org/schema/p"
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.xsd">
<!-- p命名空間 -->
<bean id="pInjectUser" class="cn.spring.demo.User" p:userName="tom" p:password="9999"></bean>
</beans>
- 手動裝配—集合屬性
List/Array集合
public class User {
private List<String> loves;
private String[] interest;
public List<String> getLoves() {
return loves;
}
public void setLoves(List<String> loves) {
this.loves = loves;
}
@Override
public String toString() {
return "User [loves=" + loves + "]";
}
public String[] getInterest() {
return interest;
}
public void setInterest(String[] interest) {
this.interest = interest;
}
}
Spring 容器
<?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.xsd">
<bean id="user" class="cn.spring.demo.User">
<property name="loves">
<list>
<value>小龍女</value>
<value>鳳兒</value>
</list>
</property>
<property name="interest">
<array>
<value>葵花</value>
<value>菊花</value>
</array>
</property>
</bean>
</beans>
測試
public class App {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("classpath:config/beans.xml");
User user = (User) context.getBean("user");
System.out.println(user.getLoves());
System.out.println(Arrays.toString(user.getInterest()));
}
}
結果:[小龍女, 鳳兒],[葵花, 菊花]
Set集合
public class User {
private Set<String> loves;
public Set<String> getLoves() {
return loves;
}
public void setLoves(Set<String> loves) {
this.loves = loves;
}
}
Spring容器
<?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.xsd">
<bean id="user" class="cn.spring.demo.User">
<property name="loves">
<set>
<value>小龍女</value>
<value>鳳兒</value>
</set>
</property>
</bean>
</beans>
測試
public class App {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("classpath:config/beans.xml");
User user = (User) context.getBean("user");
System.out.println(user.getLoves());
}
}
運行結果:[小龍女, 鳳兒]
Map集合
public class Book {
}
public class User {
private Map<String,Book> data;
public Map<String, Book> getData() {
return data;
}
public void setData(Map<String, Book> data) {
this.data = data;
}
}
Spring 容器
<?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.xsd">
<bean id="bookId" class="cn.spring.demo.Book"></bean>
<bean id="user" class="cn.spring.demo.User">
<property name="data">
<map>
<!-- 第一種寫法 -->
<entry key="b001" value-ref="bookId">
</entry>
<!-- 第二種寫法 -->
<entry>
<key >
<value>b002</value>
</key>
<ref bean="bookId"/>
</entry>
</map>
</property>
</bean>
</beans>
測試
public class App {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("classpath:config/beans.xml");
User user = (User) context.getBean("user");
System.out.println(user.getData());
}
}
結果:{b001=cn.spring.demo.Book@15e7bc4, b002=cn.spring.demo.Book@15e7bc4}
Properties對象
public class User {
private Properties properties;
public Properties getProperties() {
return properties;
}
public void setProperties(Properties properties) {
this.properties = properties;
}
}
Spring容器
<?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.xsd">
<bean id="user" class="cn.spring.demo.User">
<property name="properties">
<props>
<prop key="1">男</prop>
<prop key="2">女</prop>
</props>
</property>
</bean>
</beans>
測試
public class App {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("classpath:config/beans.xml");
User user = (User) context.getBean("user");
System.out.println(user.getProperties());
}
}
結果:{2=女, 1=男}
使用註解方式裝配Bean
測試類
public class App {
public static void main(String[] args) {
/* @Component 衍生了以下三個註解,用於標識不同的層次
* @Controller 用於配置表示層web
* @Service 用於配置業務邏輯層service
* @Repository 用於配置數據訪問層dao
*/
ApplicationContext context = new ClassPathXmlApplicationContext("classpath:config/beans.xml");
Web web = (Web)context.getBean("myweb");
web.save();
}
}
Web層
@Controller("myweb")
public class Web {
@Autowired
private Service service;
public void save(){
service.save();
System.out.println("web save");
}
}
Service層
@Service
public class Service {
@Autowired
@Qualifier("myDao")
private Dao dao;
public void save(){
dao.save();
System.out.println("service save");
}
}
Dao層
@Repository("myDao")
public class Dao {
public void save(){
System.out.println("dao save");
}
}
Spring容器
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
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.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 確定使用註解 -->
<context:annotation-config></context:annotation-config>
<!-- 自動掃描指定的包 -->
<context:component-scan base-package="cn.spring.demo"></context:component-scan>
</beans>
結果:
dao save
service save
web save
Bean初始化和銷燬
public class App {
public static void main(String[] args) {
/*
* @PostConstruct
* public void init(){ 等價於 init-method="init"
*
* @PreDestroy
* public void destory(){ 等價於 destroy-method="destory"
*/
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath:config/beans.xml");
Book book = (Book)context.getBean("book");
context.close();
}
}
@Component("book")
public class Book {
@PostConstruct
public void init(){
System.out.println("初始化");
}
@PreDestroy
public void destory(){
System.out.println("銷燬");
}
}
Spring 容器
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
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.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 確定使用註解 -->
<context:annotation-config></context:annotation-config>
<!-- 自動掃描指定的包 -->
<context:component-scan base-package="cn.spring.demo"></context:component-scan>
<!-- xml配置
<bean id="book" class="cn.spring.demo.Book"
init-method="init" destroy-method="destory">
</bean>
-->
</beans>
Bean作用範圍
public class App {
public static void main(String[] args) {
/*
* @Scope("singleton") 給當前bean配置範圍,取值:singleton、prototype等
*/
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath:config/beans.xml");
Book book = (Book)context.getBean("book");
System.out.println(book);
Book book2 = (Book)context.getBean("book");
System.out.println(book2);
context.close();
}
}
Bean對象
@Component("book")
@Scope("singleton")
public class Book {
}
Spring容器
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
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.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 確定使用註解 -->
<context:annotation-config></context:annotation-config>
<!-- 自動掃描指定的包 -->
<context:component-scan base-package="cn.spring.demo"></context:component-scan>
</beans>
結果:
@Scope("singleton")
cn.spring.demo.Book@f8fae4
cn.spring.demo.Book@f8fae4
@Scope("prototype")
cn.spring.demo.Book@f8fae4
cn.spring.demo.Book@1fc493