本篇咱們就開始學習Java領域大名鼎鼎的Spring Framework,本篇介紹的Spring Framework中的IOC(控制反轉,也稱依賴注入),原本想用初遇篇,這個題目的,可是一想這個題目不太見名知義,就改爲上柱國列傳了。爲何叫上柱國IOC列傳呢,由於以爲上柱國這個名字挺好聽。
上柱國: 原義爲自春秋起爲軍事武裝的高級統帥,引伸義爲功勳的榮譽稱號,戰國時楚、趙置,位令尹、相國下,甚尊。原爲保衛國都之官
2002年 Rod Johnson在2002年編著的《Expert One-On-One J2EE Design And Development》一書中對,對Java EE正統框架(EJB)臃腫、低效、脫離現實的學院派提出了質疑,而後以該書爲指導思想,編寫了interface21框架。而後在interface21框架的基礎上,通過從新設計,於2004年發佈。到如今開始已經十八年左右了。java
在《歡迎光臨Spring時代-緒論》中咱們提出了幾個關於如何取對象的問題,這裏咱們再回憶一下:正則表達式
在我剛學Spring框架的時候,很多視頻都會說,咱們並不在new對象,而是將對象放進IOC容器中,你要取的時候,向IOC容器中取便可。這裏咱們先從實例入手再來解釋IOC。結合着例子來解釋IOC會更加易懂。
本篇咱們還基於maven來作示例,基本上開發Spring Framework的程序基本上就只須要五個jar包就夠了,分別是下面這五個:spring
此次咱們選的版本都是5.2.8.RELEASE。
若是你不會用maven,而後請參考個人這篇博客:express
若是暫時還不想學maven,還想作jar包下載。那麼有兩種形式能夠下載到對應的jar包:segmentfault
瀏覽器訪問這個網址: https://maven.springframework...
下載完粘貼到對應的lib目錄下便可。數組
輸入上面的jar包名字,粘貼對應的依賴便可。
開發工具我這裏用的是IDEA,提示比較強大,用着比較順手。
若是你不習慣用IDEA,是Eclipse黨,這邊推薦你下載Spring官方出品的開發工具STS,也是在Eclipse的基礎開發的,開發Spring框架的程序更加快速。
瀏覽器輸入: https://spring.io/tools/
本文的示例都是基於IDEA來作的,若是不會用IDEA,想用STS,能夠參考文末後面的參考資料,是視頻。
通常Spring框架的這個配置文件,咱們都命名爲applicationContext.xml,這是一種大體的約定。
上面的問題是如何優雅的取對象,在取以前你首先就得存,向applicationContext.xml放對象。怎麼放?
像下面這樣放:
我建了一個Student類,而後裏面有name和age屬性,無參和有參構造函數,get和set函數,重寫了toString方法。
bean裏的id是惟一的,class是Student類的全類名(包名+類名)。
如何取:瀏覽器
public class SpringDemo { public static void main(String[] args) { // 加載配置文件 ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml"); Student student = (Student) applicationContext.getBean("student"); System.out.println(student); } }
打印結果:
springboot
咱們直接new,在Spring的配置文件配置參數,而後間接取對象的方式, 咱們稱之爲控制反轉(IOC Inversion of Control)或依賴注入(DI Dependency Injection)。首先解釋一下爲何有兩個稱呼,剛開始是隻有控制反轉,後來發現控制反轉這個概念有點難以理解,就在一次大會上講控制反轉改成依賴注入。
那什麼是控制反轉,咱們能夠認爲new 對象是一種控制權,而後控制反轉就是咱們將new對象的控制權交給Spring Framework。依賴注入呢? 其實也是同樣,咱們能夠理解爲在Spring的配置文件配置完對象以後,Spring將該對象給須要該對象的對象,此時就回答了上面咱們提出的第二個問題:session
對象之間有複雜的依賴關係的時候,在不但願是硬編碼的狀況下,如何取對象才能作到優雅和可配置化?
若是對象之間有複雜的依賴關係,那麼就請將這種複雜的依賴關係當作配置參數同樣,放在Spring的配置文件中,而後再從Spring IOC容器中取值,咱們此時姑且就能夠將配置文件當作IOC容器,放置了對象。
用上面的配置只能解決簡單的值,那若是某個對象的某個屬性也是對象類型的呢? Spring也想到了,當對象的屬性是屬性用ref注入,像下面這樣:app
<bean id = "studentCard" class = "org.example.StudentCard"> <property name = "id" value="1"></property> <property name = "cardNo" value="code01"></property> </bean> <bean id="student" class="org.example.Student"> <property name = "name" value = "zs"></property> <property name = "age" value = "23"></property> <property name = "studentCard" ref = "studentCard"></property> </bean>
普通屬性用value,那麼引用類型就用ref,ref的值是配置文件中bean標籤的id屬性,因此在applicationContext.xml中id禁止重複。
咱們上面的第三個問題,咱們Dao層的對象在對應的Service只須要一份就能夠了,Spring容器中的對象默認都是單例的。
那Dao層有的時候都沒有屬性,咱們還要寫在配置文件中嗎?Spring也想到了,提供了下面幾個註解:
@Controller 對應控制層 @Service 對應服務層 @Component 通用註解,若是你不肯定這個對象屬於那一層的話,就用這個。 @Repository 對應dao層
而後在配置文件中加入:
<!--配置掃描器,base-package放須要掃描的包,指定了包以後,Spring會掃描。 該包下面的類,若是有以上四個註解,那麼就會將對應的類加入到容器中,id默認爲類名首字母轉小寫。 多個包也能夠寫,用逗號隔開便可。若是寫是一個包下面有多個包, 好比org.example.service,org.example.dao。寫到二級包:org.example。Spring會自動掃描全部的子包。 --> <context:component-scan base-package="org.example"/>
因此咱們上面的第三個問題就獲得了回答,咱們寫Service層須要對應的dao層對應的時候就能夠這麼寫:
@Service public class StudentService { // 僞裝Student是dao層,被打上@Autowired的屬性,Spring在掃描的時候會自動去容器去尋找對應的類型 // 而後給該屬性注入值,因此若是你有兩個IOC容器中有兩個Student對象,那麼可能就會報錯 // Spring官方並不推薦如此注入 @Autowired private Student student; public void print(){ System.out.println(student); } }
官方推薦的注入方式是 @Autowired出如今set方法或構造方法上:
@Service public class StudentService { private Student student; @Autowired public StudentService(Student student) { this.student = student; } public void print(){ System.out.println(student); } }
至此咱們上面提出的第一個問題和第三個問題獲得瞭解決:
而後有不懂SpringMVC框架的同窗這裏可能就會問了,那我在Servlet中該如何取IOC容器中的對象啊,Servlet的初始化又不像main函數,有個明確的入口,用戶是能夠從任意一個網頁進入的。對於這個問題能夠參看:
Spring視頻教程的P十一、P十二、P1三、P14。
接着咱們回答第二個問題,難以把握對象的建立時機的這個問題,對於這個問題,Spring框架的答案是條件註解。
IOC容器有兩種形式,一種是基於配置文件(咱們上面用的就是),一種是基於註解。條件註解是基於註解形式的,查了一些資料仍是沒找到如何用配置文件實現條件註解的。可是基於配置文件的IOC還須要再補充一些,因此下面是先將配置文件形式的講解完畢後,纔會講基於註解的,條件註解也是基於註解。
咱們知道建立一個對象是有幾種不一樣的方式的:
一樣的在配置文件中配置對象參數的也有幾種形式,上面的property的配置的形式就是經過第一種方式來建立對象的。有興致的同窗能夠測試下。
接下來咱們介紹的就是經過第二種方式將對象放入IOC容器中:
<bean id = "studentCard" class = "org.example.StudentCard"> <constructor-arg value="1" index = "0"/> <constructor-arg value="11" index = "1"/> </bean>
constructor-arg有四個屬性:
經過反射產生對象:
<bean id = "studentCard" class = "org.example.StudentCard" p:id="1" p:cardNo="23"> </bean>
引用類型經過p:屬性名-ref來設定IOC容器中bean的ID
首先咱們準備一個集合的類,構造函數省略,get和set方法省略:
public class CollectionDemo { private List<String> list; private String[] arrayString; private Set<String> set; private Map<String, Object> map; private Properties properties; }
Spring配置文件:
<bean id = "collectionDemo" class = "org.example.CollectionDemo"> <property name="list"> <value> 14 </value> </property> <property name="arrayString"> <array> <value>ddd</value> </array> </property> <property name = "set"> <set> <value>aaa</value> </set> </property> <property name="map"> <map> <entry> <key> <value>zs</value> </key> <value>zs</value> </entry> </map> </property> <property name = "properties"> <props> <prop key="aa">bb</prop> <prop key="cc">dd</prop> </props> </property> </bean>
示例:
public class SpringDemo { public static void main(String[] args) { ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml"); CollectionDemo collectionDemo = (CollectionDemo)applicationContext.getBean("collectionDemo"); System.out.println(collectionDemo); } }
剛學Spring框架的時候,視頻上說控制反轉,咱們本身再也不new對象,我覺得就是真的再也不new了,就在配置文件裏面配就好了,後來隨着編碼量的上升,才發現這是對Spring框架的一種誤解,是有複雜依賴關係的咱們在配置文件裏面配,像你要是想用個HashMap,就沒必要了。
咱們在配置文件配置對象的時候,用的值都和XML預約義的符號值不衝突,什麼意思呢? 假設我給對象的值是<,就會報錯。
咱們上面配置Student對象的參數的時候,咱們用的是這種:
<bean id="student" class="org.example.Student"> <property name = "name" value = "zs"></property> <property name = "age" value = "23"></property> <property name = "studentCard" ref = "studentCard"></property> </bean>
咱們稱之爲value屬性注入,其實還能夠這麼寫:
<bean id="student" class="org.example.Student"> <property name = "name" > <value type="java.lang.String">zs</value> </property> <property name = "age" value = "23"></property> <property name = "studentCard" ref = "studentCard"></property> </bean>
咱們稱之爲value子標籤注入。 二者的區別以下:
因此當咱們配置的屬性值是< 這個符號的時候咱們就能夠這麼寫:
<bean id="student" class="org.example.Student"> <property name = "name" > <value type="java.lang.String">z<s</value> </property> </bean>
也能夠這麼寫:
<bean id="student" class="org.example.Student"> <property name = "name" > <value type="java.lang.String"><![CDATA[z<3]]></value> </property> </bean>
那我要給屬性的值注入null怎麼辦? 方法有兩個
<bean id="student" class="org.example.Student" autowire = "byName"> <property name = "name" > <null/> </property> </bean>
上面咱們提到在Spring的配置文件中配置對象的屬性值的時候,若是屬性值是對象類型的,那麼用ref就能夠了,其實這個也能夠不寫,用自動注入就能夠了,用這種自動注入也有兩種方式:
<bean id = "studentCard" class = "org.example.StudentCard"> <property name="id" value="1"></property> <property name="cardNo" value="zs"></property> </bean> <bean id="student" class="org.example.Student" autowire = "byName"> <property name = "name" > <value type="java.lang.String"><![CDATA[z<3]]></value> </property> <property name="age"> <value>34</value> </property> </bean>
運行結果再也不展現,假設你把第一個bean標籤的id改成studentCard1,那麼就注入不了。
<bean id="student" class="org.example.Student" autowire = "byType"> <property name = "name" > <value type="java.lang.String"><![CDATA[z<3]]></value> </property> <property name="age"> <value>34</value> </property> </bean
在xml裏面限制仍是挺多的,若是你不當心寫錯了屬性名,那麼也是到運行時才能發現錯誤,若是你不當心給錯了類型值,也是到運行時才能發現錯誤,好比屬性是數字類型,你給了一個字符串。不少時候咱們都但願儘量早的發現錯誤,那麼咱們的配置文件能不能變換一種形式呢? 用代碼作配置文件怎麼樣呢? 好啊,很好的想法啊,那咱們就用代碼作配置文件吧。
@Configuration public class SpringConfig { @Bean(name = "studentCard") public StudentCard studentCard(){ return new StudentCard(11,"22"); } @Bean public Student student(@Qualifier("studentCard") StudentCard studentCard){ return new Student(20,"zs",studentCard); } @Bean public StudentCard studentCard2(){ return new StudentCard(11,"22"); } } private static void annotationTest() { ApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringConfig.class); Student student = applicationContext.getBean("student", Student.class); System.out.println(student); }
運行結果:
給一個類打上註解@Configuration
將原先的bean標籤變成方法,方法返回對象類型便可。同時方法要加上@Bean註解。方法名默認爲id。
能夠,在@bean標籤中,用name屬性自定義就好
像上面同樣,在方法參數中寫對應的參數便可。
也能夠調用對應的方法來完成注入。
你能夠本身new,可是爲何不直接用IOC容器的呢。
@Qualifier中指定對象名便可。
@import(註解) 、FactoryBean(接口)、ImportBeanDefinitionRegistrar(接口)、ImportSelector(接口)是Spring提供的將對象加入IOC容器的另外方式。
@Configuration @ComponentScan(basePackages = "org.example") // ImportTest是我建的一個空類,用來測試@import,value是一個數組 @Import(value = {ImportTest.class}) public class SpringConfig { }
測試一下:
private static void annotationPrintAllBean() { ApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringConfig.class); String[] beanNames = applicationContext.getBeanDefinitionNames(); for (String beanName : beanNames) { System.out.println(beanName); } }
測試結果:
這種方式加進來的bean名是全類名。
首先實現ImportSelector接口:
public class MyImportSelector implements ImportSelector { // 最後返回的即爲須要加入到容器的類名 @Override public String[] selectImports(AnnotationMetadata importingClassMetadata) { return new String[]{ImportTest.class.getName()}; } }
而後在配置類上引入:
@Configuration @ComponentScan(basePackages = "org.example") @Import(value = MyImportSelector.class) public class SpringConfig { }
測試代碼:
private static void annotationPrintAllBean() { ApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringConfig.class); String[] beanNames = applicationContext.getBeanDefinitionNames(); for (String beanName : beanNames) { System.out.println(beanName); } }
測試結果:
AnnotationMetadata 中攜帶打上@import註解的配置類上的元信息。
先實現接口:
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar { @Override public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { // BeanDefinitionRegistry能夠將bean註冊進IOC工廠 // 咱們須要準備一個BeanDefinition。 BeanDefinition beanDefinition = new RootBeanDefinition(ImportTest.class); registry.registerBeanDefinition("importTest",beanDefinition); } }
配置類引入:
@Configuration @ComponentScan(basePackages = "org.example") @Import(value = MyImportBeanDefinitionRegistrar.class) public class SpringConfig { }
測試代碼:
private static void annotationPrintAllBean() { ApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringConfig.class); String[] beanNames = applicationContext.getBeanDefinitionNames(); for (String beanName : beanNames) { System.out.println(beanName); } }
測試結果:
FactoryBean是一個接口,還有一個接口叫BeanFactory。
反射是框架的靈魂,有的時候,某個bean重複性的屬性太多,在配置文件裏面配置也是一件讓人煩心的事情,可是程序不是擅長作重複工做嗎? 咱們可否少寫點,從配置文件中讀,而後用程序來作這種重複性工做呢?這也就是FactoryBean接口作的事情。
@Component public class MyFactory implements FactoryBean<Car> { private String cardInfo; public MyFactory() { // 僞裝從Spring的配置文件中讀到了值。 this.cardInfo = "brand,100,200.12";; } /** * 向IOC容器中放入對象 * @return * @throws Exception */ @Override public Car getObject() throws Exception { Car car = new Car(); String[] cardInfoArray = cardInfo.split(","); car.setBrand(cardInfoArray[0]); car.setMaxSpeed(Integer.parseInt(cardInfoArray[1])); car.setPrice(Double.parseDouble(cardInfoArray[2])); return car; } /** * 向IOC容器返回指定的類型 * @return */ @Override public Class<?> getObjectType() { return Car.class; } /** * 設置是不是單例模式 * @return */ @Override public boolean isSingleton() { return false; } }
測試代碼:
private static void testFactoryBean() { ApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringConfig.class); // 表明取MyFactory MyFactory myFactory = applicationContext.getBean("&myFactory", MyFactory.class); // 不加&表明取工廠中放入的bean Car car = applicationContext.getBean("myFactory", Car.class); System.out.println(myFactory); System.out.println(car); }
測試結果:
在配置類上加上:
@ComponentScan(basePackages = "org.example", excludeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION,value = {Service.class})})
是一個枚舉類型,值都在FilterType中,一共有六種:
- ANNOTATION 過濾打上指定註解(@Controller,@Component,@Repository,@Service)上的類。
- ASSIGNABLE_TYPE: 指定的類型,已經寫在配置類中的,好比說Student類,沒法排除。默認應當是先加載配置文件中的類,而後在根據掃描的包,掃描類,去將要加入到IOC容器的對象,加入到IOC容器中。
- ASPECTJ 按照Aspectj的表達式
- REGEX 按照正則表達式
- CUSTOM 自定義規則
我建了一個類,打上了Service註解,如今咱們來測試下:
@Configuration @ComponentScan(basePackages = "org.example", excludeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION,value = {Service.class})}) // @ComponentScan(basePackages = "org.example", excludeFilters = {@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE,value = {StudentDao.class})}) // @ComponentScan(basePackages = "org.example", includeFilters= {@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE,value = {StudentDao.class})},useDefaultFilters = false) // @ComponentScan(basePackages = "org.example", includeFilters = {@ComponentScan.Filter(type = FilterType.CUSTOM,value = {MyFilter.class})},useDefaultFilters = false) public class SpringConfig { @Bean(name = "studentCard") public StudentCard studentCard(){ return new StudentCard(11,"22"); } @Bean public Student student(@Qualifier("studentCard") StudentCard studentCard){ return new Student(20,"zs",studentCard); } @Bean public StudentCard studentCard2(){ return new StudentCard(11,"22"); } } private static void annotationTest() { ApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringConfig.class); // 獲取IOC容器中全部的bean String[] beanNameArray = applicationContext.getBeanDefinitionNames(); for (String beanDefinitionName : beanNameArray) { System.out.println(beanDefinitionName); } }
測試結果:
沒有service了。
下面解除第二個@ComponentScan的註釋,將第一個@ComponentScan的註釋解除掉。再度測試:
會發現StudentDao沒了。
與排除指定的類是相似的,只不過Spring默認會加載子包上須要加入到IOC容器中的類,也就是說你想只包含的類在basePackages下面,那麼這個包含就是無效的。因此咱們須要經過useDefaultFilters來禁止Spring的默認行爲。
咱們註釋掉其餘的@ComponentScan,只讓第三個@ComponentScan解除註釋。測試一下:
會發現打上@Service類的對象沒了。
自定義規則要實現TypeFilter,像下面這樣:
public class MyFilter implements TypeFilter { // 返回true加入到IOC容器中 @Override public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException { // 獲取掃描的元數據類型 ClassMetadata classMetadata = metadataReader.getClassMetadata(); // 每掃到子包下的一個類,這個方法就會被調用。 String className = classMetadata.getClassName(); // 只要類名中包含Student的,我就加入到容器中 if (className.contains("Student")){ return true; }else{ return false; } } }
仍是上面的配置類, 咱們解除第四個@ComponentScan的註釋,其餘的所有註釋。測試一下。
HomeStudentCondition是我本身建的類,沒加咱們介紹的Spring提供的註解,也加進來了。
條件註解可讓某些對象在某些條件知足的狀況下,才加入到IOC容器中(等價於建立該對象),若是該條件不知足則該對象不建立,也就是不加入到對應的IOC容器中。那條件該怎麼告訴Spring框架呢? 也是經過一個類,這個類要求實現Condition接口。
順帶提一下Spring Boot很大程度上也依賴於條件註解。
首先兩個bean:
public class HomeStudent extends Student { /** * 出入證 無參和構造函數 get set方法再也不列出 */ private String pass; } public class BoardStudent extends Student { /** * 宿舍號 無參和構造函數 get set方法再也不列出 */ private String dormitoryNumber; }
而後準備條件,須要實現Condition接口:
public class HomeStudentCondition implements Condition { @Override public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) { // 獲取當前的環境,通常開發環境分紅三套: 開發、測試、生產。 Environment environment = conditionContext.getEnvironment(); // 從環境中獲取學生類型 String studentType = environment.getProperty("studentType"); // 若是是住宿學生就加入到IOC容器中 if ("HomeStudent".equals(studentType)){ return true; } return false; } } public class BoardStudentCondition implements Condition { @Override public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { Environment environment = context.getEnvironment(); String studentType = environment.getProperty("studentType"); if ("BoardStudent".equals(studentType)){ return true; } return false; } }
而後在對應的bean上加上條件變量:
@Configuration @ComponentScan(basePackages = "org.example") public class SpringConfig { @Bean @Conditional(HomeStudentCondition.class) public HomeStudent homeStudent() { return new HomeStudent("出入證"); } @Bean @Conditional(BoardStudentCondition.class) public BoardStudent boardStudent() { return new BoardStudent("宿舍200"); } }
在IDEA中配置環境。
測試代碼:
private static void annotationTest() { ApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringConfig.class); String[] beanNames = applicationContext.getBeanDefinitionNames(); for (String beanName : beanNames) { System.out.println(beanName); } }
測試結果:
會發現boardStudent沒了。
僅在基於WEB的Spring ApplicationContext的狀況才生效。
咱們主要經常使用的是singleton和prototype,下面咱們來測試一下:
public class SpringConfig { @Bean(name = "studentCard") public StudentCard studentCard(){ return new StudentCard(11,"22"); } @Bean @Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE) public Student student(@Qualifier("studentCard") StudentCard studentCard){ return new Student(20,"zs",studentCard); } @Bean public StudentCard studentCard2(){ return new StudentCard(11,"22"); } } private static void annotationTest() { ApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringConfig.class); Student student1 = (Student) applicationContext.getBean("student"); Student student2 = (Student) applicationContext.getBean("student"); System.out.println(student1 == student2); }
結果:
ConfigurableBeanFactory不是枚舉類型,只是有兩個常量字符串: singleton和prototype。你直接寫這兩個字符串中任意一個也行。
配置文件中進行測試:
<bean id="student" class="org.example.Student" scope="prototype"> <property name = "name" > <value type="java.lang.String"><![CDATA[z<3]]></value> </property> <property name="age"> <value>34</value> </property> </bean>
private static void xmlTest() { ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml"); Student student1 = (Student) applicationContext.getBean("student"); Student student2 = (Student) applicationContext.getBean("student"); System.out.println(student1 == student2); }
在singleton做用域下,容器在啓動的時候就會建立該對象,可是也支持懶加載,即在首次向容器中獲取該對象的時候建立。
那麼怎麼告知IOC容器,在啓動的時候,先不要建立呢? 經過@Lazy註解。如何測試呢? 你能夠在對應對象的構造函數上,打斷點或者輸出點東西測試,也能夠在啓動的時候,打印IOC容器來全部對象的名字來打印。
這裏是在對應對象的構造函數上輸出一點東西來測試。
@Configuration public class SpringConfig { @Bean(name = "studentCard") public StudentCard studentCard(){ return new StudentCard(11,"22"); } @Bean @Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE) public Student student(@Qualifier("studentCard") StudentCard studentCard){ return new Student(20,"zs",studentCard); } @Bean @Lazy public StudentCard studentCard2(){ return new StudentCard(11,"22"); } }
<bean id="student" class="org.example.Student" lazy-init="true"> <property name="age"> <value>34</value> </property> </bean>
這裏測試結果就再也不展現了。
上面咱們已經介紹了,自動裝配的兩個註解了:
@Autowired(required = false),就能夠避免在容器中找不到對應類型時拋出錯誤。
這裏咱們再介紹幾個:
優先,能夠配合@Autowired使用,假設容器裏有兩個@Autowired須要的對象,在裝配時,被打上@Primary的對象,優先被選中
從剛開始的Spring framework,到如今Spring家族已經有不少產品了:
後面咱們將會介紹SpringMVC,接管MVC的C的一個框架。Java領域的問題,在Spring帝國,幾乎均可以找到解決方案(一個是方案整合(Spring Cloud),一個是本身提供(Spring MVC)。)
最開始我是從視頻開始學習Spring框架的,看視頻也是最快學框架的方式,其實看視頻的時候,內心仍是有些疑問的,可是又找不到人去問。感受視頻中講的有的時候很牽強,不成系統,零零碎碎的。我不是很喜歡零零碎碎的知識點,我喜歡系統一點的,因而就又系統的整理了一下本身對Spring的理解,也算是入門教程,也算是總結。但願對各位學習Spring有所幫助。