1. spring 工廠類
我們前邊的demo中用到的spring 工廠類是ClassPathXmlApplicationContext,從上圖可以看到他還有一個(gè)兄弟類FileSystemApplicationContext,這個(gè)類是加載非classpath路徑下的配置文件,本質(zhì)是一樣的。
從繼承關(guān)系圖中可以看到我們經(jīng)常看到的ApplicationContext,這個(gè)是新版本才引入的工廠類接口。在舊版本中是BeanFactory,是在舊版本的基礎(chǔ)上增加了幾個(gè)新功能,如國(guó)際化,resourceLoader等。還有一個(gè)區(qū)別就是加載bean的時(shí)機(jī)的區(qū)別,Beanfactory是在使用bean的時(shí)候創(chuàng)建的;ApplicationContext是在加載配置文件的時(shí)候就將所有非懶加載的單例創(chuàng)建出來(lái)了。
@Test
/**
* 使用beanFactory加載bean
*/
public void demo3() {// 老方式的工廠類,需要自己創(chuàng)建Resource對(duì)象進(jìn)行加載。BeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("application-context.xml"));// 通過(guò)工廠獲取類對(duì)象UserService userService = (UserService) beanFactory.getBean("userService");userService.sayHello();
}
2. spring bean管理 2.1 三種實(shí)例化Bean的方式 使用類構(gòu)造器實(shí)例化(默認(rèn)無(wú)參數(shù)) 使用靜態(tài)工廠方法實(shí)例化(簡(jiǎn)單工廠模式) 使用實(shí)例工廠模式實(shí)例化(工廠方法模式) 一般情況都是用第一種方式,只有類的構(gòu)造非常復(fù)雜的情況下才會(huì)用后邊的倆種。
2.1.1 使用類構(gòu)造器實(shí)例化 package com.ioc.demo2;/*** Bean實(shí)例化的三種方式:采用無(wú)參的構(gòu)造方法的方式*/
public class Bean1 {public Bean1() {System.out.println("Bean1 被實(shí)例化了。");}
}
<!-- 無(wú)參數(shù)構(gòu)造方法構(gòu)建 -->
<bean id="bean1" class="com.ioc.demo2.Bean1"></bean>
@Test
public void demo1() {ApplicationContext applicationContext = new ClassPathXmlApplicationContext("application-context.xml");Bean1 bean = (Bean1) applicationContext.getBean("bean1");
}
2.1.2 靜態(tài)工廠方法實(shí)例化 /*** Bean的實(shí)例化三種方式:靜態(tài)工廠實(shí)例化方式*/
public class Bean2 {
}
/*** Bean2的靜態(tài)工廠*/
public class Bean2Factory {public static Bean2 createBean2() {System.out.println("Bean2Factory 執(zhí)行了。");return new Bean2();}
}
<!-- 靜態(tài)工廠的方式 -->
<bean id="bean2" class="com.ioc.demo2.Bean2Factory" factory-method="createBean2"></bean>
@Test
public void demo2() {ApplicationContext applicationContext = new ClassPathXmlApplicationContext("application-context.xml");Bean2 bean = (Bean2) applicationContext.getBean("bean2");
}
2.1.3 使用實(shí)例工廠模式實(shí)例化 /*** 使用實(shí)例工廠模式實(shí)例化*/
public class Bean3 {
}
/*** Bean3的實(shí)例工廠*/
public class Bean3Factory {public Bean3 createBean3() {System.out.println("Bean3Factory 被調(diào)用了。");return new Bean3();}
}
<!-- 實(shí)例工廠的方式 -->
<bean id="bean3Factory" class="com.ioc.demo2.Bean3Factory"></bean>
<bean id="bean3" factory-bean="bean3Factory" factory-method="createBean3"></bean>
@Test
public void demo3() {ApplicationContext applicationContext = new ClassPathXmlApplicationContext("application-context.xml");Bean3 bean = (Bean3) applicationContext.getBean("bean3");
}
2.2 bean的常用配置 2.2.1 id和name 一般情況下,裝配一個(gè)Bean時(shí),通過(guò)指定一個(gè)id屬性作為Bean的名稱 id屬性在IOC容器中是唯一的 name其實(shí)也要是唯一的,同id的區(qū)別是可以存在特殊字符。這個(gè)應(yīng)該是有歷史原因的,不再贅述。 2.2.2 class 設(shè)置一個(gè)類的全路徑的名稱,主要作用是IOC容器生成類的實(shí)例 2.2.3 scope singleton(默認(rèn)) 在SpringIOC容器中僅存在一個(gè)Bean實(shí)例,Bean以單實(shí)例的方式存在 prototype 每次調(diào)用getBean()時(shí)都會(huì)返回一個(gè)新的實(shí)例 request 每個(gè)HTTP請(qǐng)求都會(huì)創(chuàng)建一個(gè)新的Bean,該作用域僅適用于WebApplicationContext環(huán)境 session 同一個(gè)HTTP session共享一個(gè)Bean,不同的HTTP session使用不同的Bean。該作用域僅適用于WebApplicationContext環(huán)境
2.3 spring容器中Bean的生命周期 spring初始化bean或銷毀bean時(shí),有時(shí)候需要做一些處理工作,因此spring可以在創(chuàng)建和銷毀bean的時(shí)候調(diào)用bean的聲明周期方法。
<bean id="xxx" class="...Yoo" init-method="init" destory-method="destory" />
當(dāng)bean在被載入到容器中時(shí)會(huì)調(diào)用init;當(dāng)bean從容器中刪除的時(shí)候調(diào)用destroy(scope=singleton有效)
2.3.1 instantiate bean對(duì)象實(shí)例化 即調(diào)用類的構(gòu)造方法。
2.3.2 populate properties封裝屬性 即調(diào)用類的屬性設(shè)置方法。
2.3.3 如果Bean實(shí)現(xiàn)BeanNameAware,則執(zhí)行setBeanName 即為該bean設(shè)置name的時(shí)候調(diào)用,可以想象為容器為map,name就是那個(gè)key。
2.3.4 如果Bean實(shí)現(xiàn)BeanFactoryAware或者ApplicationContextAware設(shè)置工廠,則執(zhí)行setBeanFactory或者上下文對(duì)象setApplicationContext 即為該bean設(shè)置容器的時(shí)候調(diào)用。
2.3.5 如果存在類實(shí)現(xiàn)BeanPostProcessor(后處理Bean),執(zhí)行postProcessBeforeInitialization 即在調(diào)用init-method之前調(diào)用。
2.3.6 如果bean實(shí)現(xiàn)InitializingBean,則實(shí)行afterPropertiesSet 屬性設(shè)置后調(diào)用。
2.3.7 調(diào)用<bean init-method="init">指定的初始化方法 執(zhí)行init方法。
2.3.8 如果存在類實(shí)現(xiàn)BeanPostProcessor(后處理Bean),執(zhí)行postProcessAfterInitialization 即在調(diào)用init-method之后調(diào)用。
2.3.9 執(zhí)行業(yè)務(wù)處理 即調(diào)用bean中的業(yè)務(wù)方法。
2.3.10 如果Bean實(shí)現(xiàn)DisposableBean,執(zhí)行destory方法 spring自身中的銷毀方法。
2.3.11調(diào)用<bean destory-method="teardown">指定的銷毀方法 執(zhí)行teardown方法。
2.3.12 相關(guān)代碼 package com.ioc.demo3;import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;public class Bean implements BeanNameAware, ApplicationContextAware, InitializingBean, DisposableBean{private String name;public Bean() {System.out.println("第一步:構(gòu)造方法");}public void setName(String name) {System.out.println("第二步:設(shè)置屬性");this.name = name;}public void setBeanName(String name) {System.out.println("第三步:設(shè)置bean的名稱:" + name);}public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {System.out.println("第四步:設(shè)置bean工廠");}public void afterPropertiesSet() throws Exception {System.out.println("第六步:屬性設(shè)置后");}public void init() {System.out.println("第七步:初始化方法");}public void run() {System.out.println("第九步:業(yè)務(wù)代碼");}public void destroy() throws Exception {System.out.println("第十步:spring自身的銷毀");}public void teardown() {System.out.println("第十一步:銷毀方法");}
}
package com.ioc.demo3;import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;public class MyBeanPostProcessor implements BeanPostProcessor {// 可以用beanName對(duì)要生效的bean做過(guò)濾操作public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {System.out.println("第四步:bean初始化前");return bean;}public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {System.out.println("第八步:bean初始化后方法");return bean;}}
<!-- Bean的聲明周期============================================ -->
<bean id="bean" class="com.ioc.demo3.Bean" init-method="init" destroy-method="teardown"><property name="name" value="xxx"></property>
</bean>
<!-- 注意這個(gè)配置是對(duì)所有的bean都生效的 -->
<bean class="com.ioc.demo3.MyBeanPostProcessor"></bean>
package com.ioc.demo3;import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;public class SpringDemo3 {@Testpublic void demo1() {// ApplicationContext接口沒(méi)有close方法,故直接使用了其實(shí)現(xiàn)類ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("application-context.xml");Bean bean = (Bean)context.getBean("bean");bean.run();context.close();}
}
第一步:構(gòu)造方法
第二步:設(shè)置屬性
第三步:設(shè)置bean的名稱:bean
第四步:設(shè)置bean工廠
第四步:bean初始化前
第六步:屬性設(shè)置后
第七步:初始化方法
第八步:bean初始化后方法
第九步:業(yè)務(wù)代碼
第十步:spring自身的銷毀
第十一步:銷毀方法
2.3.13 使用聲明周期中的BeanPostProcessor增強(qiáng)類中的方法 這個(gè)本質(zhì)上是可以對(duì)類中的方法做動(dòng)態(tài)代理,為后邊的AOP做鋪墊。
下邊舉個(gè)栗子:在delete方法前面加一個(gè)鑒權(quán)的功能,不更改具體的類方法 。
package com.ioc.demo3;public interface BeanDao {public void find();public void add();public void delete();public void update();}
package com.ioc.demo3;public class BeanDaoImpl implements BeanDao {public void find() {System.out.println("查詢");}public void add() {System.out.println("添加");}public void delete() {System.out.println("刪除");}public void update() {System.out.println("更新");}}
package com.ioc.demo3;import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;public class MyBeanPostProcessor implements BeanPostProcessor {public Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException {System.out.println("第四步:bean初始化前");return bean;}public Object postProcessAfterInitialization(final Object bean, String beanName) throws BeansException {System.out.println("第八步:bean初始化后方法");if (beanName.equals("beanDao")) {Object proxy = Proxy.newProxyInstance(bean.getClass().getClassLoader(), bean.getClass().getInterfaces(), new InvocationHandler() {public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {if (method.getName().equals("delete")) {System.out.println("鑒權(quán)是否是root用戶");return method.invoke(bean, args);}return method.invoke(bean, args);}});return proxy;}return bean;}}
<bean class="com.ioc.demo3.MyBeanPostProcessor"></bean>
<bean id="beanDao" class="com.ioc.demo3.BeanDaoImpl"></bean>
package com.ioc.demo3;import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;public class SpringDemo3 {@Testpublic void demo1() {ApplicationContext context = new ClassPathXmlApplicationContext("application-context.xml");BeanDao beanDao = (BeanDao)context.getBean("beanDao");beanDao.add();beanDao.delete();beanDao.find();beanDao.update();}
}
轉(zhuǎn)載于:https://www.cnblogs.com/xxxuwentao/p/9587969.html
總結(jié)
以上是生活随笔 為你收集整理的【一步一步学习spring】spring bean管理(上) 的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
如果覺(jué)得生活随笔 網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔 推薦給好友。