Java | Spring框架學習筆記--(1)工廠
Spring筆記(1) 工廠
什麼是Spring
Spring是⼀個輕量級的JavaEE解決⽅案,整合眾多優秀的設計模式 。
- 輕量級:
- 對於執行環境是沒有額外要求的。
可以在開源的tomcat resion jetty裡執行,也可以在收費的weblogic websphere裡執行。 - 程式碼移植性高:不需要事先額外的介面。
- JavaEE解決方案:
- 整合設計模式(工廠、代理等)
設計模式
- ⼴義概念
⾯向物件設計中,解決特定問題的經典程式碼 - 狹義概念
GOF4⼈幫定義的23種設計模式:⼯⼚、介面卡、裝飾器、⻔⾯、代理、模板…
工廠設計模式
-
概念:通過⼯⼚類,建立物件,不提倡通過直接new的方法的建立物件
User user = new User(); UserDAO userDAO = new UserDAOImpl();
-
好處:解耦合
耦合:指定是程式碼間的強關聯關係,⼀⽅的改變會影響到另⼀⽅
問題:不利於程式碼維護
簡單:把接⼝的實現類,硬編碼在程式中UserService userService = new UserServiceImpl();
比如說我們目前使用UserServiceImpl
作為UserService
的一個實現類,當突然有一天我們需要升級或者其他說明原因,需要把實現類改成UserServiceImpl2
,就還需要再改動一次程式碼,就還需要重新編譯一次。
public static void main(String[] args) {
UserService userService = new UserServiceImpl();
userService.login("abcabc","123456");
}
一個比較好的解決方法就是使用工廠來建立物件
public static void main(String[] args) {
UserService userService = Factory.getUserService();
userService.login("abcabc","123456");
}
總結:
Spring本質:⼯⼚ ApplicationContext (applicationContext.xml)
第一個Spring
環境搭建
jar包
在maven的中心倉庫,搜尋spring,匯入相應的依賴,這裡選擇spring context
<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.0</version>
</dependency>
配置檔案
配置檔案放置的位置:任意位置
配置檔案的命名:沒有硬性要求,建議applicationContext.xml
以後使用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">
</beans>
核心API
ApplicationContext:Spring提供的一個工廠物件,用於物件的建立。好處:解耦合。
ApplicationContext是一個介面型別,遮蔽實現的差異。
在非web環境下,主要使用ClassPathXmlApplicationContext
實現類,在web環境下主要使用XmlWebApplicationContext
實現類
ApplicationContext工廠物件需要佔用大量的記憶體(重量級),所以我們不會頻繁地建立這個物件(一個應用智慧建立一個工廠物件),而且這個物件一定是執行緒安全的。
程式開發
-
新建一個類
-
在applicationContext.xml中引入
<?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"> <!-- id:唯一 class:全限定類名 --> <bean id="person" class="com.prince.Person"></bean> </beans>
-
Main
public class TestPerson { @Test public void test(){ //建立Spring的工廠物件,並且在構造方法中指定配置檔案的位置 ApplicationContext applicationContext = new ClassPathXmlApplicationContext("/applicationContext.xml"); //根據id建立物件 Person person = (Person)applicationContext.getBean("person"); //測試 System.out.println(person); } }
細節分析
由Spring建立的物件,叫做Bean或者Component
常見方法
-
直接通過id值獲得bean物件,但是需要強制轉換
Person person = (Person)applicationContext.getBean("person");
-
傳入一個class位元組碼物件,就可以不用強制型別轉換了
Person person = applicationContext.getBean("person",Person.class);
-
甚至可以直接只傳入一個class位元組碼物件,表示根據型別來獲取值
Person person = applicationContext.getBean(Person.class);
注意:當Spring的容器中只存在一個Person物件時,才能夠這樣子獲取,如果有多個,會報異常(他不知道你想要的是哪個)。
-
獲取bean的所有id
String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames(); System.out.println(Arrays.toString(beanDefinitionNames));
-
獲取指定類的所有id
String[] beanNamesForType = applicationContext.getBeanNamesForType(Person.class); for (String s : beanNamesForType) { System.out.println(s); }
-
判斷是否存在指定的id
applicationContext.containsBeanDefinition("person");//當配置檔案顯式定義了id時,只判斷id 不判斷name ,沒有顯式定義id時,也可以判斷name applicationContext.containsBean("person");//id 和 name 都可以判斷
配置檔案
-
只配置class屬性,不配置id屬性
<bean class="com.prince.Person"></bean>
問:沒有手動設定id值,他有沒有id
驗證:String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames(); for (String beanDefinitionName : beanDefinitionNames) { System.out.println(beanDefinitionName); }
輸出結果為:
com.prince.Person#0
可以看到,當不指定id值的時候,spring 預設會為我們提供一個id值。
如果這個bean只需要使用一次,那麼久可以省略id值。如果會使用多次,或者需要被其他bean引用時,就必須要指定id屬性! -
name屬性:用於給bean定義別名(小名)
相同點:在getBean()方法,可以同時傳id和name來獲取物件。(name可以取代id的作用)
<bean name="p" class="com.prince.Person"></bean>
Person p = applicationContext.getBean("p",Person.class); System.out.println(p);
區別:
-
別名可以定義多個(用逗號分隔),但是ID只能定義一個
<bean name="p1,p2,p3" class="com.prince.Person"></bean>
-
在XML中,id屬性的命名要求:必須以字母開頭,不能以特殊字元開頭。name則沒有要求。所以name屬性會應用在特殊命名的場景下。
但是xml發展到今天,id的限制已不存在。 -
containsBeanDefinition
和containsBean
的區別。
-
Spring與日誌框架
Spring與⽇志框架進⾏整合,⽇志框架就可以在控制檯中,輸出Spring框架運⾏過程中的⼀些重要的資訊。
好處:便於瞭解Spring框架的運⾏過程,利於程式的除錯
如何整合日誌框架?
預設情況下:
Spring 1 2 3等早期版本都是使用commons-logging.jar
Spring 5.x預設整合的是 logback log4j2
如何整合log4j(我們不要log4j2)?
-
引入log4j的jar包
<dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>1.7.25</version> </dependency>
-
建立log4j.properties
log4j.rootLogger=debug,stdout log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.Target=System.out log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=[%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n
之後就可以很清楚地看到Spring的執行情況:
注入
注入:通過Spring工廠及配置檔案,為所建立的成員變數賦值。
平常的時候為成員變數賦值(使用程式碼的方式,存在耦合問題):
@Test
public void test4(){
Person p = applicationContext.getBean("p",Person.class);
p.setName("xiaoming");
p.setAge(18);
System.out.println(p);
}
使用Spring的配置檔案來注入:
<bean name="p1" class="com.prince.Person">
<property name="name">
<value>aaa</value>
</property>
<property name="age">
<value>18</value>
</property>
</bean>
<bean name="p1" class="com.prince.Person">
<property name="name" value="aaa"/>
<property name="age" value="18" />
</bean>
好處:解耦合
Set注入
Spring呼叫Set方法,通過配置檔案,為成員變數賦值。
String+8種基本型別
property標籤裡面巢狀value即可。
<property name="name">
<value>aaa</value>
</property>
陣列
property標籤裡面巢狀list,然後再在list裡巢狀多個value即可。
<property name="emails">
<list>
<value>123456@qq.com</value>
<value>123456@163.com</value>
<value>123456@126.com</value>
<value>123456@gmail.com</value>
</list>
</property>
Set集合
property標籤裡面巢狀set,然後再在set裡巢狀多個value即可。
<property name="tels">
<set>
<value>18888888888</value>
<value>18888888889</value>
<value>18888888890</value>
<value>18888888890</value>
</set>
</property>
細節:由於Set集合本身是無序的,所以最終輸出的順序不一定會和這個一樣。由於Set是無重複的,即使加入了重複的元素,也會自動去重。
List集合
和陣列一樣,都是property裡巢狀list
Map集合
<property name="map">
<map>
<entry key="k1" value="v1"/>
<entry>
<key><value>k2</value></key>
<value>v2</value>
</entry>
<entry>
<key><ref bean=""></ref></key>
<ref bean=""></ref>
</entry>
</map>
</property>
注意:key有專屬的標籤,寫在key裡面的內容就是key,因為第5行我的key是String型別,所以我在裡面巢狀value標籤,如果key是一個物件,那麼key標籤裡面巢狀的是ref標籤。
key外面的都是value。
Property
<property>
<props>
<prop key="k1">v1</prop>
</props>
</property>
使用者自定義型別
第一種方式:直接在property
裡面加bean 標籤即可,因為那個bean僅使用一次,所以不需要id屬性
<bean id="userServer" class="com.prince.basic.UserServiceImpl">
<property name="userDao">
<bean class="com.prince.basic.UserDaoImpl"></bean>
</property>
</bean>
第二種方式:
<bean id="userDao" class="com.prince.basic.UserDaoImpl"></bean>
<bean id="userServer" class="com.prince.basic.UserServiceImpl">
<property name="userDao">
<ref bean="userDao"></ref>
</property>
</bean>
簡化方法
-
基於屬性簡化
<property name="name" value="aaa"/> <property name="userDao" ref="userDao">
-
基於p名稱空間簡化
<bean name="p" class="com.prince.Person" p:name="bbb" p:age="180"></bean> <bean id="userServer" class="com.prince.basic.UserServiceImpl" p:userDao-ref="userDao"></bean>
直接寫在bean標籤上,p是property的縮寫。
構造注入
Spring呼叫構造方法來賦值。前提:提供有參構造方法。
-
必須提供有參構造方法。
public class People { public String name; public int age; public People() { } public People(String name, int age) { this.name = name; this.age = age; } }
-
配置bean標籤的時候,裡面不再是property標籤,而是
constructor-arg
,<bean id="people" class="com.prince.People"> <constructor-arg> <value>zhangsan</value> </constructor-arg> <constructor-arg> <value>18</value> </constructor-arg> </bean>
這裡需要注意的是,constructor-arg標籤的個數,和順序,必須要和構造方法裡的保持一致!
注:當建構函式的引數個數不一樣時,可以通過<constructor-arg>
標籤的個數進行區分。
當引數個數一樣時,需要指定type屬性,如果不指定,他將會隨機選一個來注入。
<bean id="people1" class="com.prince.People">
<constructor-arg type="int">
<value>123</value>
</constructor-arg>
</bean>
反轉控制與依賴注入
反轉控制
控制:對於成員變數賦值的控制權
反轉控制:把對於成員變數賦值的控制權,從程式碼中轉移到Spring工廠的配置檔案中完成。
好處:解耦合
底層實現:工廠設計模式
依賴注入
注入:通過Spring的工廠及配置檔案,為物件(bean,元件)的成員變數賦值。
依賴注⼊:當⼀個類需要另⼀個類時,就意味著依賴,⼀旦出現依賴,就可以把另⼀個類作為本類的成員變數,最終通過Spring配置⽂件進⾏注⼊(賦值)
複雜物件建立
簡單物件:可以直接通過new的方式建立
複雜物件:不能通過new的方式建立,比如Connection、SqlSessionFactory
實現FactoryBean介面
開發步驟:
- 新建一個類,繼承FactoryBean介面。使用FactoryBean介面的時候,要指定泛型。
public class ConnectionFactory implements FactoryBean<Connection> {
/**
* 建立複雜物件的過程放在這,Spring會拿它的返回值來當做要建立的物件。
* @return 複雜物件
* @throws Exception
*/
@Override
public Connection getObject() throws Exception {
Class.forName("com.mysql.jdbc.Driver");
return DriverManager.getConnection("jdbc:mysql:///mydata","root","root");
}
/**
*
* @return 複雜物件的Class位元組碼檔案
*/
@Override
public Class<?> getObjectType() {
return Connection.class;
}
/**
* 是否單例
* @return true或者false
*/
@Override
public boolean isSingleton() {
return false;
}
}
- Spring配置檔案的配置
<!--錯誤認知:通過getBean獲取conn,得到的是ConnectionFactory物件。
其實,Spring會對者做特殊處理,如果class指定的是FactoryBean介面,那麼通過getBean獲取到的就是那個複雜物件。
-->
<bean id="conn" class="com.factorybean.ConnectionFactory"></bean>
細節:如果就是想獲取FactoryBean物件,而不是對應的複雜物件,可以在getBean裡面的id前面加&
applicationContext.getBean("&conn");
依賴注入改造
Class.forName("com.mysql.jdbc.Driver");
return DriverManager.getConnection("jdbc:mysql:///mydata","root","root");
這四個引數對於Connection來說都是非常重要的,也就是依賴。
我們可以通過依賴注入的方式改造這個類:
public class ConnectionFactory1 implements FactoryBean<Connection> {
public String driverName;
public String url;
public String username;
public String password;
//getter setter略
@Override
public Connection getObject() throws Exception {
Class.forName(driverName);
return DriverManager.getConnection(url,username,password);
}
//getObjectType isSingleton 略
}
配置檔案中通過Set注入,好處:解耦合!!
<bean id="conn1" class="com.factorybean.ConnectionFactory1">
<property name="driverName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql:///mydata"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</bean>
FactoryBean總結:FactoryBean是Spring中用於建立複雜物件的一種方式,後續講Spring整合其他框架會大量使用這種模式!
例項工廠
為什麼使用例項工廠?
- 避免Spring框架的侵入(FactoryBean是Spring框架提供的)
- 整合遺留系統
開發步驟:
-
建立一個工廠類,建立一個
getInstance()
或者getXxxx()
方法來建立一個物件。/** * 使用例項工廠建立 */ public class ConnectionFactory2 { public Connection getConnection(){ Connection conn = null; try { Class.forName("com.mysql.jdbc.Driver"); conn = DriverManager.getConnection("jdbc:mysql:///mydata","root","root"); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SQLException throwables) { throwables.printStackTrace(); } finally { } return conn; } }
-
Spring配置檔案,
factory-bean
填的是工廠類的bean,factory-method
填的是工廠類建立工廠的方法。<!--例項工廠--> <bean id="connfactory" class="com.factorybean.ConnectionFactory2"></bean> <bean id="conn2" factory-bean="connfactory" factory-method="getConnection"></bean>
靜態工廠
靜態工廠和例項工廠的區別是:例項工廠的類的建立物件的方法不是靜態的,而靜態工廠的方法是靜態的,所以使用靜態工廠就省去了建立工廠類這一步。
<bean id="conn3" class="com.factorybean.ConnectionFactory3" factory-method="getConnection"></bean>
控制Spring工廠建立物件的次數
簡單物件
新增一個scope屬性即可
<bean id="account" scope="singleton|prototype" class="xxxx.Account"/>
sigleton:只會建立⼀次簡單物件 預設值
prototype:每⼀次都會建立新的物件
複雜物件
FactoryBean{
isSingleton(){
return true 只會建立⼀次
return false 每⼀次都會建立新的
}
}
如沒有isSingleton⽅法 還是通過scope屬性 進⾏物件建立次數的控制
物件的生命週期
生命週期:指的是一個物件建立、存活、消亡的一個完整過程
建立階段
建立階段:Spring工廠何時建立物件
scope="singleton"
Spring工廠建立的同時,建立物件scope="prototype"
Spring工廠在獲取物件的同時,建立物件
驗證:xml檔案裡:
<bean id="pro" class="com.life.Product" scope="singleton"></bean>
效果:在執行完下面程式碼後,物件建立(可以看到控制檯中輸出了構造方法列印的文字)
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("/life.xml");
而 scope="prototype"
的物件,只有呼叫了getBean()
方法之後才會建立物件。
如果,singleton
的物件也想實現prototype
的那種效果(只有呼叫了getBean()
才會建立物件),可以加入懶載入屬性lazy-init
:
<bean id="pro" class="com.life.Product" scope="singleton" lazy-init="true"></bean>
初始化階段
Spring工廠在建立完物件後,會呼叫物件的初始化方法,完成對應的初始化操作。
初始化方法,由程式設計師根據需求來提供;初始化方法的呼叫,由Spring來完成。
實現初始化的方式
-
實現InitializingBean介面,重寫afterPropertiesSet()方法,在方法裡面執行初始化語句。
public class Product implements InitializingBean { public Product() { System.out.println("Product物件已建立"); } @Override public void afterPropertiesSet() throws Exception { System.out.println("初始化"); } }
<bean id="pro" class="com.life.Product" scope="singleton"></bean>
執行程式碼,輸出:
-
類中提供一個普通方法,然後再在配置檔案中指定
init-method
屬性
我這裡配置的初始化方法是init()
<bean id="pro1" class="com.life.Product1" scope="singleton" init-method="init"></bean>
細節:
- 如果一個物件實現InitializingBean介面的同時,又提供普通的初始化方法,那麼兩個初始化方法都會執行。
- 注入在初始化之前執行
銷燬階段
Spring銷燬物件前,會呼叫物件的銷燬方法,完成銷燬操作。
Spring什麼時候銷燬物件? 答:工廠關閉的時候
((ClassPathXmlApplicationContext)applicationContext).close();
實現銷燬的方式
-
實現
DisposableBean
介面public class Product2 implements DisposableBean { public Product2() { System.out.println("Product物件已建立"); } @Override public void destroy() throws Exception { System.out.println("銷燬方法"); } }
-
自定義銷燬方法
<bean id="pro3" class="com.life.Product3" scope="singleton" destroy-method="myDestroy"></bean>
細節:
- 銷燬方法只使用於
scope="singleton"
- 如果兩種銷燬方法都存在,那麼兩種方法都執行
配置檔案引數化
把Spring配置檔案中需要經常修改的字串資訊,轉移到一個更小的配置檔案中。
1. Spring的配置⽂件中存在需要經常修改的字串?
存在 以資料庫連線相關的引數 代表
2. 經常變化字串,在Spring的配置⽂件中,直接修改
不利於項⽬維護(修改)
3. 轉移到⼀個⼩的配置⽂件(.properties)
利於維護(修改)
比如一個druid的連結池:
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql:///mydata"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</bean>
原來是那些value都整合在一個配置檔案中,可以通過下面的方法來把那些value分離出去
dp.properties
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql:///mydata
username=root
password=root
applicationContext.xml
<context:property-placeholder location="dp.properties"></context:property-placeholder>
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="${driverClassName}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</bean>
型別轉換器
型別轉換器
作⽤: Spring通過型別轉換器把配置⽂件中字串型別的資料,轉換成了物件中成員變數對應型別的資料,進⽽完成了注⼊
自定義型別轉換器
當Spring內部沒有提供特定的型別轉換器,而程式設計師在應用的過程中還需要使用,那麼就需要自定義型別轉換器
如:日期格式
<bean id="person" class="com.prince.Person">
<property name="id" value="111" />
<property name="birthday" value="2020-11-11"/>
</bean>
執行的時候直接報錯:
原因:缺少轉換器,沒法把字串"2020-11-11"轉成Date物件
解決方法:新增自定義型別轉換器(實現Converter介面,然後在Spring配置檔案中註冊)
-
新建一個類,實現Converter介面
可以發現Converter
是一個泛型,Converter<S,T>
中,S
表示源型別,T
表示要轉換的型別。
踩坑:Converter是org.springframework.core.convert.converter.Converter
,不要導錯包。public class MyConvert implements Converter<String, Date> { @Override public Date convert(String s) { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); try { return sdf.parse(s); } catch (ParseException e) { e.printStackTrace(); } return null; } }
-
在Spring配置檔案中註冊,讓Spring知道有這個類
<!--第一步:建立這個轉換器類的物件(最基本)--> <bean id="myConvert" class="com.prince.MyConvert" /> <!--第二步:建立ConversionServiceFactoryBean物件,注入那個轉換器,用於告訴Spring--> <!--踩坑:id一定是conversionService,否則不起作用--> <bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean"> <property name="converters"> <!--觀察原始碼發現,converters是一個Set集合--> <set> <ref bean="myConvert" /> </set> </property> </bean>
細節
-
自定義型別轉換器的
"yyyy-MM-dd"
可以用依賴注入。public class MyConvert implements Converter<String, Date> { public String pattern; public String getPattern() { return pattern; } public void setPattern(String pattern) { this.pattern = pattern; } @Override public Date convert(String s) { SimpleDateFormat sdf = new SimpleDateFormat(pattern); try { return sdf.parse(s); } catch (ParseException e) { e.printStackTrace(); } return null; } }
<bean id="myConvert" class="com.prince.MyConvert" > <property name="pattern" value="yyyy-MM-dd"/> </bean>
-
ConversionServiceFactoryBean的id值必須是conversionService
-
Spring內建的String–>Date轉換器只支援
yyyy/MM/dd
後置處理Bean
BeanPostProcessor
BeanPostProcessor
作⽤:對Spring⼯⼚所建立的物件,進⾏再加⼯。
底層實現:
程式設計師實現BeanPostProcessor規定接⼝中的⽅法:
Object postProcessBeforeInitiallization(Object bean String beanName)
作⽤: Spring建立完物件,並進⾏注⼊後,可以運⾏Before⽅法進⾏加⼯
獲得Spring建立好的物件 :通過⽅法的引數
最終通過返回值交給Spring框架
Object postProcessAfterInitiallization(Object bean String beanName)
作⽤: Spring執⾏完物件的初始化操作後,可以運⾏After⽅法進⾏加⼯
獲得Spring建立好的物件 :通過⽅法的引數
最終通過返回值交給Spring框架
開發步驟
-
新建一個類,實現
BeanPostProcessor
介面public class MyBeanPostProcessor implements BeanPostProcessor { @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { return bean; } @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { Person person = (Person)bean; person.setId(9999); return person; } }
-
在Spring配置檔案中配置(只需要把這個物件建立出來就行了)
<bean id="beanPostProcessor" class="com.prince.MyBeanPostProcessor"></bean>
注意:
-
不是Person類實現
BeanPostProcessor
介面,而是重新寫一個類來實現這個介面 -
一旦配置了這個
BeanPostProcessor
,那麼這個工廠裡建立的所有bean都會經過這個處理器,所以為了避免型別轉換異常,需要加一個判斷:@Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { if(bean instanceof Person){ Person person = (Person)bean; person.setId(9999); } return bean; }
-
在Spring配置檔案中配置(只需要把這個物件建立出來就行了)
<bean id="beanPostProcessor" class="com.prince.MyBeanPostProcessor"></bean>
相關文章
- Spring框架學習筆記(1)Spring框架筆記
- Spring筆記(1) - 工廠Spring筆記
- Java設計模式學習筆記——工廠模式與抽象工廠模式Java設計模式筆記抽象
- spring學習筆記(1)Spring筆記
- Java設計模式學習筆記(四) 抽象工廠模式Java設計模式筆記抽象
- Java設計模式學習筆記(三) 工廠方法模式Java設計模式筆記
- Scrapy 框架 (學習筆記-1)框架筆記
- Spring框架學習筆記(二):官方文件Core Technologies – Part 1Spring框架筆記
- Java設計模式學習筆記(二) 簡單工廠模式Java設計模式筆記
- Java Spring Boot 學習筆記(一)JavaSpring Boot筆記
- 設計模式學習筆記之工廠模式設計模式筆記
- Spring Boot 學習筆記(1):快速上手Spring Boot筆記
- spring boot學習簡要筆記1Spring Boot筆記
- Java 學習筆記--Day1Java筆記
- Camera KMD ISP學習筆記(1)-ISP框架筆記框架
- Spring Boot 學習筆記(4):配置properties(1)Spring Boot筆記
- spring學習筆記Spring筆記
- Spring 學習筆記Spring筆記
- java學習筆記1(入門級)Java筆記
- 【防忘筆記】Spring+Struts2古董框架學習筆記Spring框架
- SSM框架學習筆記_第1章_SpringIOC概述SSM框架筆記Spring
- .Net Core 學習筆記1——包、元包、框架筆記框架
- 重學Java設計模式-學習筆記(1)Java設計模式筆記
- Bootstrap框架:學習筆記boot框架筆記
- 設計模式學習筆記(三)簡單工廠、工廠方法和抽象工廠之間的區別設計模式筆記抽象
- Spring學習筆記(一)Spring筆記
- 學習筆記1筆記
- 學習筆記-1筆記
- 深度學習框架Pytorch學習筆記深度學習框架PyTorch筆記
- Spring 學習筆記(2) Spring BeanSpring筆記Bean
- Spring 學習筆記(3)Spring MVCSpring筆記MVC
- Spring學習記錄1Spring
- JAVA學習筆記Java筆記
- Spring框架學習筆記(一):官方文件介紹,IoC與AOP概念學習Spring框架筆記
- 機器學習框架ML.NET學習筆記【1】基本概念機器學習框架筆記
- Java_EE企業級開發學習筆記——spring學習筆記第二章Java筆記Spring
- 《JAVA學習指南》學習筆記Java筆記
- go學習筆記——gin框架Go筆記框架