前言
spring框架中的beanfactory接口和factorybean接口因為名稱相似,老是容易搞混淆,而且也是面試過程中經(jīng)常會碰到的一個問題。所以本文就專門給大家整理出來。
一、beanfactory接口
beanfactory接口是spring容器的核心接口,負(fù)責(zé):實例化、定位、配置應(yīng)用程序中的對象及建立這些對象間的依賴。
spring為我們提供了許多易用的beanfactory實現(xiàn),xmlbeanfactory就是常用的一個,該實現(xiàn)將以xml方式描述組成應(yīng)用的對象及對象間的依賴關(guān)系。xmlbeanfactory類將持有此xml配置元數(shù)據(jù),并用它來構(gòu)建一個完全可配置的系統(tǒng)或應(yīng)用。
1
2
3
|
beanfactory bf = new xmlbeanfactory( new classpathresource( "applicationcontext.xml" )); object bean = bf.getbean(iuserservice. class ); system.out.println(bean); |
接口中定義的方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
public interface beanfactory { string factory_bean_prefix = "&" ; object getbean(string name) throws beansexception; <t> t getbean(string name, class <t> requiredtype) throws beansexception; object getbean(string name, object... args) throws beansexception; <t> t getbean( class <t> requiredtype) throws beansexception; <t> t getbean( class <t> requiredtype, object... args) throws beansexception; boolean containsbean(string name); boolean issingleton(string name) throws nosuchbeandefinitionexception; boolean isprototype(string name) throws nosuchbeandefinitionexception; boolean istypematch(string name, resolvabletype typetomatch) throws nosuchbeandefinitionexception; boolean istypematch(string name, class <?> typetomatch) throws nosuchbeandefinitionexception; class <?> gettype(string name) throws nosuchbeandefinitionexception; string[] getaliases(string name); } |
二、factorybean接口
beanfactory接口是spring的核心接口。功能非常復(fù)雜,這個時候如果我們想要編寫一些比較復(fù)雜點兒的邏輯就會觸及到其他一些不必要的接口,不好實現(xiàn)。這時候使用factorybean就比較方便了。factorybean以bean結(jié)尾是個bean對象,不是工廠。接口中定義的方法如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
public interface factorybean<t> { /** * 返回對象的實例 */ t getobject() throws exception; /** * 返回對象的類型 */ class <?> getobjecttype(); /** * 是否是單例 */ boolean issingleton(); } |
1.簡單實現(xiàn)
接口和實現(xiàn)類
1
2
3
4
|
public interface iuserservice { public void dosome(); } |
1
2
3
4
5
6
7
8
9
10
|
public class userserviceimpl implements iuserservice { public userserviceimpl(){ system.out.println( "--被實例化了--" ); } @override public void dosome() { system.out.println( "userserviceimpl 。。。 被執(zhí)行了" ); } } |
自定義factorybean
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
public class myfactorybean implements factorybean<iuserservice>{ @override public iuserservice getobject() throws exception { system.out.println( "--iuserservice實例化之前---" ); iuserservice service = new userserviceimpl(); system.out.println( "--iuserservice實例化后---" ); return service; } @override public class <?> getobjecttype() { return iuserservice. class ; } @override public boolean issingleton() { return true ; } } |
配置文件
1
2
3
4
5
6
7
|
<?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= "myfactorybean" class = "com.dpb.factorybean.myfactorybean" /> </beans> |
測試--通過類型獲取
1
2
3
4
5
6
|
@test public void test1() { beanfactory bf = new xmlbeanfactory( new classpathresource( "applicationcontext.xml" )); object bean = bf.getbean(iuserservice. class ); system.out.println(bean); } |
輸出結(jié)果
--iuserservice實例化之前---
--被實例化了--
--iuserservice實例化后---
com.dpb.service.userserviceimpl@5315b42e
測試--通過id獲取
1
2
3
4
5
6
|
@test public void test1() { beanfactory bf = new xmlbeanfactory( new classpathresource( "applicationcontext.xml" )); object bean = bf.getbean( "myfactorybean" ); system.out.println(bean); } |
輸出結(jié)果
--iuserservice實例化之前---
--被實例化了--
--iuserservice實例化后---
com.dpb.service.userserviceimpl@783e6358
如果想要獲取factorybean對象 id前加 &就可以
1
2
3
4
5
6
|
@test public void test1() { beanfactory bf = new xmlbeanfactory( new classpathresource( "applicationcontext.xml" )); object bean = bf.getbean( "&myfactorybean" ); system.out.println(bean); } |
輸出結(jié)果
com.dpb.factorybean.myfactorybean@3b81a1bc
2.增強(qiáng)實現(xiàn)
通過factorybean創(chuàng)建一個代理類來增強(qiáng)目標(biāo)類,我們來看下效果
接口和實現(xiàn)類
1
2
3
4
|
public interface iuserservice { public void dosome(); } |
1
2
3
4
5
6
7
8
9
10
|
public class userserviceimpl implements iuserservice { public userserviceimpl(){ system.out.println( "--被實例化了--" ); } @override public void dosome() { system.out.println( "userserviceimpl 。。。 被執(zhí)行了" ); } } |
自定義factorybean
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
|
public class myfactorybean implements factorybean,initializingbean,disposablebean{ private object proxyobject; private object target; private string interfacename; @override public object getobject() throws exception { return proxyobject; } @override public class <?> getobjecttype() { return proxyobject.getclass()== null ?object. class :proxyobject.getclass(); } @override public boolean issingleton() { return true ; } /** * myfactorybean 對象銷毀的回調(diào)方法 * @throws exception */ @override public void destroy() throws exception { system.out.println( "destroy ...." ); } /** * myfactorybean 對象實例化的方法 */ @override public void afterpropertiesset() throws exception { system.out.println( "---afterpropertiesset---" ); proxyobject = proxy.newproxyinstance( this .getclass().getclassloader() , new class []{ class .forname(interfacename)} , new invocationhandler() { @override public object invoke(object proxy, method method, object[] args) throws throwable { system.out.println( "----代理方法執(zhí)行開始----" ); object obj = method.invoke(target, args); system.out.println( "----代理方法執(zhí)行結(jié)束----" ); return obj; } }); } public string getinterfacename() { return interfacename; } public void setinterfacename(string interfacename) { this .interfacename = interfacename; } public object gettarget() { return target; } public void settarget(object target) { this .target = target; } } |
配置文件
1
2
3
4
5
6
7
8
9
10
11
12
13
|
<?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"> <!-- 注冊目標(biāo)對象 --> <bean class = "com.dpb.service.userserviceimpl" id= "userserviceimpl" /> <!-- 注冊factorybean對象 --> <bean id= "myfactorybean" class = "com.dpb.factorybean.myfactorybean" > <property name= "interfacename" value= "com.dpb.service.iuserservice" /> <property name= "target" ref= "userserviceimpl" /> </bean> </beans> |
測試
1
2
3
4
5
6
7
8
|
@test public void test1() { applicationcontext ac = new classpathxmlapplicationcontext( "applicationcontext.xml" ); iuserservice bean = (iuserservice) ac.getbean( "myfactorybean" ); system.out.println( "****************" ); bean.dosome(); system.out.println(); } |
輸出結(jié)果:
--被實例化了--
---afterpropertiesset---
****************
----代理方法執(zhí)行開始----
userserviceimpl 。。。 被執(zhí)行了
----代理方法執(zhí)行結(jié)束----
小結(jié):通過輸出結(jié)果我們可以看到通過factorybean接口我們也可以實現(xiàn)beanfactory中某些接口提供的功能,而且會更加的靈活一些。
3.factorybean的實際使用案例
spring在整合mybatis框架的時候提供的sqlsessionfactorybean就是factorybean的很好的實現(xiàn)。
1
2
3
4
5
6
7
8
9
10
11
12
|
<!-- 整合mybatis --> <bean class = "org.mybatis.spring.sqlsessionfactorybean" id= "sqlsessionfactorybean" > <!-- 關(guān)聯(lián)數(shù)據(jù)源 --> <property name= "datasource" ref= "datasource" /> <!-- 關(guān)聯(lián)mybatis的配置文件 --> <property name= "configlocation" value= "classpath:mybatis-cfg.xml" /> <!-- 添加別名設(shè)置 --> <property name= "typealiasespackage" value= "com.sxt.model" /> <!-- 映射文件和接口文件不在同一個目錄下的時候,需要單獨指定映射文件的路徑 --> <property name= "mapperlocations" value= "classpath:mapper/*.xml" /> </bean> |
spring會調(diào)用sqlsessionfactorybean這個實現(xiàn)了factorybean的工廠bean 同時加載datasource,mapper文件的路徑,對sqlsessionfactory進(jìn)行初始化。
源代碼比較多就不一一貼出來。到了這兒可以自行跟蹤下源代碼。
核心方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
|
@override public void afterpropertiesset() throws exception { // 省略 this .sqlsessionfactory = buildsqlsessionfactory(); } protected sqlsessionfactory buildsqlsessionfactory() throws ioexception { configuration configuration; xmlconfigbuilder xmlconfigbuilder = null ; // 省略 return this .sqlsessionfactorybuilder.build(configuration); } /** * {@inheritdoc} */ @override public sqlsessionfactory getobject() throws exception { if ( this .sqlsessionfactory == null ) { afterpropertiesset(); } return this .sqlsessionfactory; } /** * {@inheritdoc} */ @override public class <? extends sqlsessionfactory> getobjecttype() { return this .sqlsessionfactory == null ? sqlsessionfactory. class : this .sqlsessionfactory.getclass(); } /** * {@inheritdoc} */ @override public boolean issingleton() { return true ; } |
maven坐標(biāo):
1
2
3
4
5
|
<dependency> <groupid>org.mybatis</groupid> <artifactid>mybatis-spring</artifactid> <version> 1.3 . 2 </version> </dependency> |
三、總結(jié)
- beanfactory是spring中ioc容器最核心的接口,遵循了ioc容器中所需的基本接口。例如我們很常見的:applicationcontext,xmlbeanfactory 等等都使用了beanfactory這個接口。
- factorybean是工廠類接口,當(dāng)你只是想簡單的去構(gòu)造bean,不希望實現(xiàn)原有大量的方法。它是一個bean,不過這個bean能夠做為工廠去創(chuàng)建bean,同時還能修飾對象的生成。
- factorybean比beanfactory在生產(chǎn)bean的時候靈活,還能修飾對象,帶有工廠模式和裝飾模式的意思在里面,不過它的存在還是以bean的形式存在。
好了,以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,謝謝大家對服務(wù)器之家的支持。
原文鏈接:https://www.cnblogs.com/dengpengbo/p/10493782.html