spring(一):spring IoC的注入方式总结
前言:談談對springIOc的理解,兩張圖很好的闡述了springIoc容器的作用。
傳統應用程序示意圖.jpg
IoC容器后程序結構示意圖.jpg
?
?
?
springIoC容器注入方式有set注入,構造器注入,注解注入。
一:set方式注入
1.先準備幾個bean類,一個普通的學生類,以及一個A類,A類組合了學生類對象。
Student.java
package com.cnblogs.bean;public class Student {// 學號 private String sNo;private String name;private int age;// 性別 private String sex;//年級private String grade;public Student() {super();}public Student(String sNo, String name, int age, String sex, String grade) {super();this.sNo = sNo;this.name = name;this.age = age;this.sex = sex;this.grade = grade;}// set和get方法
// toString方法()
}
?
A.java
package com.cnblogs.bean;public class A {private String desc;private Student stu;public A() {super();// TODO Auto-generated constructor stub }public A(String desc, Student stu) {super();this.desc = desc;this.stu = stu;}// set和get方法// toString方法()}
?set.xml中
<!-- 基于set方法的注入 --><bean name="stu" class="com.cnblogs.bean.Student"><property name="sNo" value="1001"></property><property name="name" value="jack"></property><property name="age" value="12"></property><property name="sex" value="male"></property><property name="grade" value="三年級"></property></bean><!-- 注入引用類型 --><bean name="A" class="com.cnblogs.bean.A"><property name="desc" value="A組合了Student類對象"></property><!-- ref屬性表示調用這個setStudent方法的時候要用的參數是名字為stu的對象 --><property name="stu" ref="stu"></property></bean>1.<bean>標簽中,name和id起標識這個對象的作用,id會幫我們檢查給對象起的名字是否規范(名字不能重復,不能有空格,不能已數字開頭),name不會檢查這些東西。
class屬性是一個類的全限定名,標識配置那個類。
2.springIoC默認是已單例模式管理對象,即通過相同的名字多次拿出來的對象一樣,可以再<bean>標簽中加屬性 scope="prototype"代表非單例,
scope="Singleton"代表單例模式。
3.可以給某一個對象加別名,在</bean>后面加一條<alias name="stu" alias="s1"/>??梢酝ㄟ^stu拿對象,也可以通過s1 拿對象。
4.當類中的一個成員變量為另一個類的對象時,在<property>子標簽中可以通過ref引入,ref的值為一個<bean>標簽的name或id值。
5.同一個類可以配置多個對象,但是標識多個對象的id或name值要不同。
注意:set方式底層會用到一個bean類的set方法,如果bean類的成員變量沒有set方法卻采用了set方式注入會報錯。
測試方法:
/*** 基于set方法的注入*/@Testpublic void set(){try{String[] path = {"com/cnblogs/ioc/set/set.xml"};ApplicationContext container = new ClassPathXmlApplicationContext(path);Student stu = (Student)container.getBean("stu");System.out.println(stu);Object a = container.getBean("A");System.out.println(a);} catch(Exception e) {e.printStackTrace();} }?
?結果:
?Student [sNo=1001, name=jack, age=12, sex=male, grade=三年級]
A [desc=A組合了Student類對象, stu=Student [sNo=1001, name=jack, age=12, sex=male, grade=三年級]]
?
2.set方式注入之集合的注入
(1)準備一個B類,里面包括了各種集合:list,set,map,property
B.java
package com.cnblogs.bean;import java.util.List; import java.util.Map; import java.util.Properties; import java.util.Set;public class B {// list集合private List<String> list;// set集合private Set<String> set;// mapprivate Map<String,String> map;// propprivate Properties prop;// set和get方法}collection.xml
<!-- 集合的注入 --><bean name="coll" class="com.cnblogs.bean.B"><!-- list集合 --><property name="list"><list><value>jack</value><value>tom</value><value>tina</value></list></property><!-- set集合 --><property name="set"><set><value>1001</value><value>1002</value><value>1003</value></set></property><!-- map集合 --><property name="map"><map><entry key="name" value="zhangsan"></entry><entry key="age" value="12"></entry><entry key="gender" value="male"></entry></map></property><!-- properties集合注入 --><property name="prop"><props><prop key="driver">com.mysql.jdbc.Driver</prop><prop key="username">study</prop></props></property></bean>?
測試方法:和上面那個一樣,就是xml的文件路徑改一下。
?
(2):如果一個list集合的泛型是一個類,也可以注入。
HobbyGroup.java
package com.cnblogs.bean;import java.util.List;// 興趣小組 public class HobbyGroup {private Long id;private String name;private List<Student> stu;public HobbyGroup() {super();// TODO Auto-generated constructor stub }public HobbyGroup(Long id, String name, List<Student> stu) {super();this.id = id;this.name = name;this.stu = stu;}// set和get方法
// toString方法() }
collection.xml
<bean name="hg" class="com.cnblogs.bean.HobbyGroup"><property name="id" value="1"></property><property name="name" value="羽毛球興趣小組"></property><property name="stu"><list><bean name="stu1" class="com.cnblogs.bean.Student" ><property name="sNo" value="1001"></property><property name="name" value="jack"></property><property name="age" value="12"></property><property name="sex" value="male"></property><property name="grade" value="三年級"></property></bean><bean name="stu2" class="com.cnblogs.bean.Student"><property name="sNo" value="1002"></property><property name="name" value="tom"></property><property name="age" value="13"></property><property name="sex" value="male"></property><property name="grade" value="三年級"></property></bean><bean name="stu3" class="com.cnblogs.bean.Student"><property name="sNo" value="1003"></property><property name="name" value="tina"></property><property name="age" value="11"></property><property name="sex" value="female"></property><property name="grade" value="三年級"></property></bean></list></property></bean>?
3.set注入之自動注入
1.自動注入一般針對一個類中組合了另一類的對象。
2.自動注入有byName注入和byType注入
3.byName注入:spring容器會到當前的類中找property的名字,然后再根據這個名字去spring容器中找有沒有和這個property名字相同的對象,有的話,
就把這個對象當做參數放到setXxxx這個方法里面注入進來。(找到多個不會報錯)
4.byType注入:spring容器會根據set方法的參數類型去容器中找相匹配的對象,找到就注入,沒找到就算了。如果找到多個會報錯。
5.可以在<beans>標簽中加 default-autowire="byType",則下面的標簽會根據byType方式自動注入。
6.可以在<bean>標簽中autowire=" "指定注入方式,該方式會屏蔽 default-autowire=" "。
示例:
同樣用到com.cnblogs.bean.A類和com.cnblogs.bean.Student類。
autowired.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"xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-4.3.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context-4.3.xsd"default-autowire="byName" ><bean name="stu" class="com.cnblogs.bean.Student"><property name="sNo" value="1001"></property><property name="name" value="jack"></property><property name="age" value="12"></property><property name="sex" value="male"></property><property name="grade" value="三年級"></property></bean><!-- byName --><bean name="A1" class="com.cnblogs.bean.A"><property name="desc" value="A組合了Student類對象,byName"></property></bean><!-- byType --><bean name="A2" class="com.cnblogs.bean.A" autowire="byType"><property name="desc" value="A組合了Student類對象,byType"></property></bean> </beans>
?
測試方法:
@Testpublic void autowired(){try{String[] path = {"com/cnblogs/ioc/autowired/autowired.xml"};ApplicationContext container = new ClassPathXmlApplicationContext(path);// byNameA a1 = (A) container.getBean("A1");System.out.println(a1);// byTypeA a2 = (A) container.getBean("A2");System.out.println(a2);} catch(Exception e) {e.printStackTrace();} }?
?結果:
A [desc=A組合了Student類對象,byName, stu=Student [sNo=1001, name=jack, age=12, sex=male, grade=三年級]]
A [desc=A組合了Student類對象,byType, stu=Student [sNo=1001, name=jack, age=12, sex=male, grade=三年級]]
?
二:構造器注入
構造器有分兩種注入方式,一個根據參數類型注入,一個根據下標注入。
1.根據參數類型注入
同樣用到com.cnblogs.bean.Student類。
constructor.xml
<!-- 根據參數類型 --><bean name="stu1" class="com.cnblogs.bean.Student"><constructor-arg type="String" value="1001"></constructor-arg><constructor-arg type="String" value="jack"></constructor-arg><constructor-arg type="int" value="12"></constructor-arg><constructor-arg type="String" value="male"></constructor-arg><constructor-arg type="String" value="三年級"></constructor-arg></bean>?
2.根據參數下標注入
<!-- 根據下標 --><bean name="stu2" class="com.cnblogs.bean.Student"><constructor-arg index="0" value="1002"></constructor-arg><constructor-arg index="1" value="tina"></constructor-arg><constructor-arg index="2" value="12"></constructor-arg><constructor-arg index="3" value="female"></constructor-arg><constructor-arg index="4" value="三年級"></constructor-arg></bean>?
?
?
三、注解注入
首先需要在xml文件中指定使用注解注入的包,springIoC容器讀取這個文件的時候就會知道。
anatation.xml:
<context:component-scan base-package="com.cnblogs.ioc.anatation" />???
?
com.cnblogs.ioc.annotation.Office.java
package com.cnblogs.ioc.anatation;import org.springframework.stereotype.Component;@Component public class Office {private String num = "001";public Office(){}public Office(String num) {this.num = num;}public String getNum() {return num;}public void setNum(String num) {this.num = num;}}?
com.cnblogs.ioc.annotation.Car.java
package com.cnblogs.ioc.anatation;import org.springframework.stereotype.Component;
@Component public class Car {private double price;private String name;public Car(){}public Car(double price, String name) {this.price = price;this.name = name;}public double getPrice() {return price;}public void setPrice(double price) {this.price = price;}public String getName() {return name;}public void setName(String name) {this.name = name;} }
?
com.cnblogs.ioc.annotation.Boss.java
package com.cnblogs.ioc.anatation;import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; import javax.annotation.Resource;import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component;@Component @Scope("prototype") public class Boss {private String name;@Autowiredprivate Car car;@Resourceprivate Office office;public Boss(){}public Boss(String name, Car car, Office office) {this.name = name;this.car = car;this.office = office;}public Boss( Car car, Office office) {this.car = car;this.office = office;}public String getName() {return name;}public void setName(String name) {this.name = name;}public Car getCar() {return car;}public void setCar(Car car) {this.car = car;}public Office getOffice() {return office;}public void setOffice(Office office) {this.office = office;}@PostConstructpublic void init(){System.out.println("初始化..");}@PreDestroypublic void destory(){System.out.println("銷毀...");} }?測試方法:
/*** 注解注入*/@Testpublic void anatation(){try{String[] path = {"com/cnblogs/ioc/anatation/anatation.xml"};ApplicationContext container = new ClassPathXmlApplicationContext(path);Boss boss = (Boss) container.getBean("boss");System.out.println(boss.getName());System.out.println(boss.getCar());System.out.println(boss.getOffice());System.out.println(boss);} catch(Exception e) {e.printStackTrace();} }?
?結果
?初始化..
null
com.cnblogs.ioc.anatation.Car@50de0926
com.cnblogs.ioc.anatation.Office@2473b9ce
com.cnblogs.ioc.anatation.Boss@60438a68
?
?幾個注解的作用:
@Autowired1) @Autowired使用后需要在xml文件加入以下配置才能生效: <context:annotation-config/>2) @Autowired注解可以寫在成員變量、setter方法、構造器函數上面3) @Autowired默認按照byType匹配的方式進行注入,如果沒有一個bean的類型是匹配的則會拋異常,如果有多個bean的類型都匹配成功了,那么再按byName方式進行選擇4) @Autowired如果最終匹配不成功(注意一定是一個都沒有找到的情況)則會拋出異常,但是如果設置為 @Autowired(required=false),則最終匹配不成功沒有不會拋出異常。5) @Autowired可以結合@Qualifier("beanName")來使用,則可以達到byName的效果@Resource1) @Resource使用后需要在xml文件加入以下配置才能生效:<context:annotation-config/>2) @Resource的作用和@Autowired差不多,只不過 @Resource是默認先用byName,如果找不到合適的就再用byType來注入3) @Resource有倆個屬性,name和type,使用name屬性則表示要byName匹配,使用type屬性則表示要byType匹配@PostConstruct和@PreDestroy1) 標注了@PostConstruct注解的方法將在類實例化后調用2) 標注了@PreDestroy注解的方法將在類銷毀之前調用@Component1) @Component注解可以直接定義bean,而無需在xml定義。但是若兩種定義同時存在,xml中的定義會覆蓋類中注解的Bean定義2) @Component注解直接寫在類上面即可3) @Component有一個可選的參數,用于指定bean的名稱@Component("boss")public class Boss{}4) @Component如果不指定參數,則bean的名稱為當前類的類名小寫//和上面例子的相關相同@Componentpublic class Boss{}5) @Component使用之后需要在xml文件配置一個標簽<context:component-scan/>6) <context:component-scan base-package="com.briup.ioc.annotation" /> 表示spring檢查指定包下的java類,看它們是否使用了 @Component注解7) @Component定義的bean默認情況下都是單例模式的,如果要讓這個bean變為非單例,可以再結合這個@Scope注解來達到目標@Scope("prototype")@Component是Spring中所有bean組件的通用形式, @Repository @Service @Controller 則是 @Component的細化,用來表示更具體的用例,分別對應了持久化層、服務層和表現層。但是至少到現在為止這個四種注解的實質區別很小(甚至幾乎沒有),都是把當前類注冊為spring容器中的一個bean注意:1.component-scan標簽默認情況下自動掃描指定路徑下的包(含所有子包)2.component-scan標簽將帶有@Component @Repository @Service @Controller注解的類自動注冊到spring容器中3.component-scan標簽對標記了@Required @Autowired @PostConstruct @PreDestroy @Resource @WebServiceRef @EJB @PersistenceContext @PersistenceUnit等注解的類進行對應的操作,使注解生效4.component-scan標簽包含了annotation-config標簽的作用?
?
?
?
?
轉載于:https://www.cnblogs.com/yangji0202/p/10863883.html
總結
以上是生活随笔為你收集整理的spring(一):spring IoC的注入方式总结的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 分享一些好用的 Chrome 插件!
- 下一篇: 第十周补充