-
Bean屬性繼承
應(yīng)用場景:
場景一:ParentClass(屬性1,屬性2,屬性3,get和set方法)
子類1(屬性4,屬性5)?
子類2(屬性6,屬性7)
場景2:子類1和子類2沒有父類,而是有一些相同的屬性。
類1:(屬性1,屬性2,屬性3,屬性4,屬性5)
類2:(屬性1,屬性2,屬性3,屬性6,屬性7)
這兩個(gè)場景下,通過Spring注入類1和類2的所有屬性,一般如下:
?
abstract="true":設(shè)置<bean>標(biāo)簽只是定義性的,不會(huì)對(duì)它進(jìn)行實(shí)例化操作。
parent屬性:在Bean的子類bean標(biāo)簽添加,值為父類的Id。
Spring配置代碼:
? <!-- 如果Class1和Class2屬性1、2、3相同 -->
步驟1:?<bean id="bean" class="main.java.com.Bean繼承屬性.ParentClass" abstract="true">
? ? ? ? ? ? ?<property name="attribute1" value="attribute1"></property>
? ? ? ? ? ? ?<property name="attribute2" value="attribute2"></property>?
? ? ? ? ? ? ?<property name="attribute3" value="attribute3"></property>
? ? ? ? ? ? ?</bean>
?步驟2: ? ?<bean id="bean1" class="main.java.com.Bean繼承屬性.Class1" parent="bean">
? ? ? ? ? ? ? ? ?<property name="attribute4" value="attribute4"></property>
? ? ? ? ? ? ? ? ?<property name="attribute5" value="attribute5"></property>
? ? ? ? ? ? ? ? ?</bean> ??
? ? ? ? ? ? ? ? ?
<bean id="bean2" class="main.java.com.Bean繼承屬性.Class2" parent="bean">
? ? ? ? <property name="attribute6" value="attribute6"></property>
? ? ? ? <property name="attribute7" value="attribute7"></property>
? ? ? ? </bean>
? ? ? ?
測試:
@Test
public void test(){
ApplicationContext ac=new ClassPathXmlApplicationContext("spring-extends.xml");
Class1 c1=ac.getBean("bean1", Class1.class);
Class2 c2=ac.getBean("bean2",Class2.class);
System.out.println(c1);
System.out.println(c2);
}
結(jié)果:
Class1 [attribute1=attribute1, attribute2=attribute2, attribute3=attribute3, attribute4=attribute4, attribute5=attribute5]
Class1 [attribute1=attribute1, attribute2=attribute2, attribute3=attribute3, attribute6=attribute6, attribute7=attribute7]
應(yīng)用場景2:類1和類2不繼承某一父類,只是存在相同屬性。
spring配置:
?<!-- 如果Class1和Class2屬性1、2、3相同 -->
? ? ?步驟1: ? <bean id="bean" abstract="true">
? ? ? ? ?<property name="attribute1" value="attribute1"></property>
? ? ? ? <property name="attribute2" value="attribute2"></property>?
? ? ? ? <property name="attribute3" value="attribute3"></property>
? ? ? ? </bean>
? ? ? 步驟2: ?<bean id="bean1" class="main.java.com.Bean繼承屬性.Class1" parent="bean">
? ? ? ? <property name="attribute4" value="attribute4"></property>
? ? ? ? <property name="attribute5" value="attribute5"></property>
? ? ? ? </bean> ??
? ? ? ? <bean id="bean2" class="main.java.com.Bean繼承屬性.Class2" parent="bean">
? ? ? ? <property name="attribute6" value="attribute6"></property>
? ? ? ? <property name="attribute7" value="attribute7"></property>
? ? ? ? </bean> ? ? ? ?
查看全部 -
ioc,控制反轉(zhuǎn)查看全部
-
Bean初始化及銷毀邏輯處理(在singleton作用域上進(jìn)行講解)
Bean初始化——如果需要在Bean實(shí)例化時(shí)執(zhí)行一些邏輯,Spring提供了兩種方法:(有一個(gè)javaBean,該Bean作用,連接數(shù)據(jù)庫,例如session,斷開數(shù)據(jù)庫連接,該Bean被創(chuàng)建之后,執(zhí)行數(shù)據(jù)庫連接的過程)
方法1:bean標(biāo)簽里的init-method屬性,該值為Bean的某一方法,Spring實(shí)例化時(shí),會(huì)調(diào)用Bean的該方法。
方法2:讓Bean實(shí)現(xiàn)InitializingBean接口,Spring在實(shí)例化該Bean時(shí),檢測到Bean實(shí)現(xiàn)了該接口,就會(huì)調(diào)用該接口所定義的相應(yīng)方法。
Bean銷毀——如果需要在Bean銷毀之前執(zhí)行一些邏輯,有兩種方法。
方法1:bean標(biāo)簽里的destory-method屬性,該值為Bean的某一方法,Spring銷毀該Bean時(shí),會(huì)調(diào)用Bean的該方法。
方法2:讓Bean實(shí)現(xiàn)DisposableBean接口,Spring在銷毀該Bean時(shí),檢測到Bean實(shí)現(xiàn)了該接口,就會(huì)調(diào)用該接口所定義的相應(yīng)方法。
案例1:通過bean標(biāo)簽的init-method和destory-method屬性來指定Bean初始化邏輯和銷毀邏輯。
代碼:
public class Bean {
public void onInit(){
System.out.println("Bean的初始化邏輯方法被執(zhí)行了");
}
public void onDestory(){
System.out.println("Bean的銷毀邏輯方法被執(zhí)行了");
}
}
測試代碼:
@Test
public void test(){
ApplicationContext ac=new ClassPathXmlApplicationContext("spring-initAnddestory.xml");
Bean bean=ac.getBean("bean", Bean.class);
System.out.println(bean);
}
結(jié)果:bean的銷毀方法沒執(zhí)行,因?yàn)楫?dāng)前是單例模式,所以Bean的初始化是在Spring上下文實(shí)例化完成的,Bean的銷毀是在Spring上下文的銷毀過程中執(zhí)行Bean的銷毀。(Spring上下文的銷毀定義到AbstractApplicationContext中)
Bean的初始化邏輯方法被執(zhí)行了
main.java.com.Bean初始化及銷毀.Bean@b8a1063
spring配置:
<bean class="main.java.com.Bean初始化及銷毀.Bean" id="bean" init-method="onInit" destroy-method="onDestory">
改進(jìn):
@Test
public void test(){
AbstractApplicationContext ac=new ClassPathXmlApplicationContext("spring-initAnddestory.xml");
Bean bean=ac.getBean("bean", Bean.class);
System.out.println(bean);
ac.close();
}
注意:如果所有的Bean都有相同名稱的初始化方法和相同名稱的銷毀方法,可以在<beans default-init-method="onInit" ? default-destory-method="onDestory">,含義:所有的bean都有初始化方法和銷毀方法。
案例2:實(shí)現(xiàn)相應(yīng)接口,并實(shí)現(xiàn)相應(yīng)方法
代碼:
public class Bean implements InitializingBean,DisposableBean{
@Override
public void destroy() throws Exception {
System.out.println("Bean的銷毀邏輯方法被執(zhí)行了");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("Bean的初始化邏輯方法被執(zhí)行了");
}
}
spring配置:
<bean class="main.java.com.Bean初始化及銷毀.Bean" id="bean"></bean>
測試:
@Test
public void test(){
AbstractApplicationContext ac=new ClassPathXmlApplicationContext("spring-initAnddestory.xml");
Bean bean=ac.getBean("bean", Bean.class);
System.out.println(bean);
ac.close();
}
查看全部 -
Bean的懶加載
測試:
@Test
public void test(){
ApplicationContext ac=new ClassPathXmlApplicationContext("spring_lanjiazai.xml");
System.out.println("context被創(chuàng)建了");
Bean bean=ac.getBean("bean", Bean.class);
System.out.println(bean);
結(jié)果:
Bean被創(chuàng)建了
context被創(chuàng)建了
main.java.com.Bean懶加載.Bean@b8a1063
證明:當(dāng)Spring上下文初始化時(shí),作用域?yàn)閟ingleton的Bean就已經(jīng)被創(chuàng)建好了,而不是通過Spring上下文獲取時(shí)才去創(chuàng)建。
Bean懶加載概念:
Spring容器會(huì)在創(chuàng)建容器時(shí)提前初始化Singleton作用域的bean,但是如果Bean被標(biāo)注了lazy-init=“true”,則該Bean只有在其被需要的時(shí)候才會(huì)被初始化。(只對(duì)singleton作用域的bean有效)
代碼:
<bean id="bean" class="main.java.com.Bean懶加載.Bean" scope="singleton" lazy-init="true"></bean>
解決多個(gè)bean使用懶加載問題:
<beans標(biāo)簽里添加default-lazy-init=“true”>:表示spring配置文件里所有bean都是懶加載模式。
使用場景:
如果某個(gè)Bean在程序整個(gè)運(yùn)行周期都可能不會(huì)被使用,那么可考慮設(shè)定該Bean為懶加載。
優(yōu)點(diǎn):盡可能的節(jié)省了資源。
缺點(diǎn):可能會(huì)導(dǎo)致某個(gè)操作相應(yīng)操作時(shí)間增加。
查看全部 -
scope 的web 作用域
查看全部 -
代碼回顧
javabean 的作用域是request 每次請(qǐng)求都會(huì)創(chuàng)建一個(gè)新的實(shí)例
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?session? 在一次回話中都是同一個(gè)實(shí)例,重開瀏覽器會(huì)有不同的實(shí)例
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?appliction 是同一個(gè)服務(wù)內(nèi)都是同一個(gè)實(shí)例,重啟服務(wù)會(huì)產(chǎn)生不同的實(shí)例
查看全部 -
三個(gè)類對(duì)應(yīng)的配置文件
查看全部 -
application session? request? 三個(gè)測試類
查看全部 -
spring web 上下文環(huán)境配置
查看全部 -
springweb 上下文環(huán)境
查看全部 -
課程內(nèi)容:注入bean的課程內(nèi)容
查看全部 -
spring通過xml實(shí)現(xiàn)自定義作用域(自定義雙例模式作用域)
SimpleThreadScope:Spring內(nèi)置作用域。
編寫自定義作用域:
步驟1:實(shí)現(xiàn)Scope接口(org.springframework.beans.factory.config),主要關(guān)注實(shí)現(xiàn)的get方法和remove方法。
get方法:按照name參數(shù),按照我們自己定義的規(guī)則,去返回一個(gè)Bean,如果我們定義的規(guī)則里,Bean不存在,那么將通過objectFactory去創(chuàng)建一個(gè)Bean。
雙例模式:一個(gè)bean的Id對(duì)應(yīng)兩個(gè)實(shí)例,實(shí)現(xiàn)雙例模式,需要兩個(gè)Map集合,Map<String,Object> map1=new HashMap<String,Object>();Map<String,Object> map2=new HashMap<String,Object>();。
get方法:
public Object get(String name, ObjectFactory<?> objectFactory) {
if(!map1.containsKey(name)){ ? //判斷map1是否包含名為name的Bean實(shí)例
Object o=objectFactory.getObject();//如果不存在則創(chuàng)建一個(gè)ObjectFactory規(guī)則Bean
map1.put(name, o); ? //并把這個(gè)Bean放入集合,并命名為name
return o;
}
if(!map2.containsKey(name)){ ? //map2同map1操作
Object o=objectFactory.getObject();?
map2.put(name, o); ?
return o;
}
//如果map1和map2都包含這個(gè)Bean,也就是說Spring上下文通過Id獲取有兩個(gè)實(shí)例,則返回一個(gè)0或1
int i=new Random().nextInt(2);
if(i==0){
return map1.get(name);//如果是0,則返回對(duì)象1
}else{
return map2.get(name);//如果是0,則返回對(duì)象2
}
}
remove方法:和get方法相反,按照name參數(shù),去移除一個(gè)Bean。
public Object remove(String name) {
if(map1.containsKey(name)){
Object o=map1.get(name);
map1.remove(name);
return o;
}
if(map2.containsKey(name)){
Object o=map2.get(name);
map2.remove(name);
return o;
}
return null; ? ?//說明沒拿到任何實(shí)例
}
xml配置:
<bean id="myScope" class="main.java.com.自定義作用域.MyScope" ?>
</bean>
<bean ?class="org.springframework.beans.factory.config.CustomScopeConfigurer">
<property name="scopes">
<map>
<entry key="myscope" value-ref="myScope"></entry>
</map>
</property>
</bean>
測試代碼:
@Test
public void testBean(){
ApplicationContext ac=new ClassPathXmlApplicationContext("spring-zidingyi.xml");
for(int i=0;i<10;i++){
Bean bean=ac.getBean(“myScope”", Bean.class);
System.out.println(bean);
}
}
Spring提供的另外一個(gè)作用域:SimpleThreadScope(同一線程,Spring上下文會(huì)分配同一實(shí)例,不同線程,則獲得不同實(shí)例。
srping配置:
<bean id="myScope" class="main.java.com.自定義作用域.MyScope" ></bean>
<bean id="simpleThreadScope" class="org.springframework.context.support.SimpleThreadScope"></bean>
<bean class="org.springframework.beans.factory.config.CustomScopeConfigurer">
<property name="scopes">
<map>
<entry key="myscope" value-ref="myScope"></entry>
<entry key="simpleThreadScope" value-ref="simpleThreadScope"></entry>
</map>
</property>
</bean>
<bean id="bean11" class="main.java.com.自定義作用域.Bean" scope="simpleThreadScope"></bean>
測試代碼:
public void testBean(){
final ApplicationContext ac=new ClassPathXmlApplicationContext("spring-zidingyi.xml");
for(int i=0;i<10;i++){
new Thread(new Runnable(){
@Override
public void run() {
Bean bean=ac.getBean("bean11", Bean.class);
System.out.println(bean);
}
}).start();
}
}
}
查看全部 -
代碼內(nèi)容回顧
查看全部 -
課程內(nèi)容回顧
查看全部 -
Web環(huán)境相關(guān)作用域
1、request作用域
bean標(biāo)簽的scope作用域設(shè)置為request后,每次請(qǐng)求,spring都會(huì)重新創(chuàng)建一個(gè)新的Bean。
2、session作用域
bean標(biāo)簽的scope作用域設(shè)置為session后,每個(gè)session都會(huì)被創(chuàng)建一個(gè)單獨(dú)的實(shí)例。
3、application作用域
bean標(biāo)簽的scope作用域設(shè)置為application后,每個(gè)servletContext都會(huì)被創(chuàng)建一個(gè)單獨(dú)的實(shí)例。
4、(不帶傳入)websocket作用域,使用很少,暫時(shí)忽略
bean標(biāo)簽的scope作用域設(shè)置為websocket后,每次請(qǐng)求,spring都會(huì)重新創(chuàng)建一個(gè)新的Bean。
因?yàn)槭莣eb應(yīng)用作用域,所以程序應(yīng)處于SpringWeb上下文環(huán)境,SpringMVC中就使用到了SpringWeb上下文環(huán)境。
建立SpringWeb上下文環(huán)境方式:
方式一:使用DispathcherServlet,不需要增加其他任何配置,因?yàn)檫@就是SpringWeb標(biāo)準(zhǔn)的上下文環(huán)境。
代碼:
?<servlet-name>SpringWebContext</servlet-name>
? <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
? <init-param>
? <param-name>contextConfigLocation</param-name>
? <param-value>classpath:spring.xml</param-value>
? </init-param>
? </servlet>
? <servlet-mapping>
? <servlet-name>SpringWebContext</servlet-name>
? <url-pattern>/*</url-pattern>
? </servlet-mapping>
方式二:不使用DispatcherServlet,那么需要增加listener或filter,取決于Servlet版本是2.4以上還是2.4以下。
(1)Servlet2.4以上
listener用處:在Web應(yīng)用啟動(dòng)初始化過程中,加載一個(gè)SpringWeb的上下文。
代碼:
<listener>
<listener-class>org.springframework.web.context.request.RequestContextListener
</listener-class>
</listener>
(2)Servlet2.4以下
filter作用:為每一個(gè)請(qǐng)求覆蓋一個(gè)SpringWeb上下文。
代碼:
<filter>
<filter-name>requestContextFilter</filter-name>
<filter-class>org.springframework.web.filter.RequestContextFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>requestContextFilter</filter-name>
<url-pattern>/*</url-pattern>
<filter-mapping>
代碼演示:這里用到了另外兩個(gè)包——spring-web和spring-webmvc
步驟1:配置web.xml
@RequestMapping:在瀏覽器上通過URL路徑去訪問這個(gè)方法。
@ResponseBody:該注解下的方法返回值在瀏覽器上進(jìn)行顯示。
@Controller:放置在類上,spring可以通過它來找到該類。
代碼:
@Controller
public class RequestScope {
@RequestMapping("testRequest")
@ResponseBody
public String test(){
return this.toString();
}
}
訪問地址:http://localhost:8080/SpringWeb/testRequest,每次刷新都是會(huì)變化的。
查看全部
舉報(bào)