IOC:(Inversion(反轉) Of Control):控制反轉java
DI:(Dependency Injection)依賴注入mysql
<!--一個Bean標籤能夠註冊一個組件(類、對象)-->
<!-- class:組件的全類名 id:惟一標識 -->
<bean id="person1" class="com.bean.Person">
<!--使用property標籤爲Person對象的屬性賦值-->
<!-- name="" : 指定屬性名 value="" :指定屬性的值-->
<property name="personName" value="張三" ></property>
<property name="personAge" value="18" ></property>
</bean>
複製代碼
public void test(){
//ApplicationContext 表明ioc容器
//ClassPathXmlApplicationContext:當前應用的xml配置文件在ClassPath下
//根據配置文件獲得ioc容器對象
ApplicationContext ioc = new ClassPathXmlApplicationContext("spring.xml");
Person person = (Person)ioc.getBean("person1");
}
複製代碼
注意!web
<bean id="person1" class="com.bean.Person">
<property name="personName" value="張三" ></property>
<property name="personAge" value="18" ></property>
</bean>
<bean id="person2" class="com.bean.Person">
<property name="personName" value="小花" ></property>
<property name="personAge" value="18" ></property>
</bean>
複製代碼
public void test(){
ApplicationContext ioc = new ClassPathXmlApplicationContext("spring.xml");
//若是ioc容器中這個類型的bean有多個,查找就會報錯
Person person = ioc.getBean(Person.class);
//這樣使用 即使ioc容器中這個類型的bean有多個,查找也不會報錯
Person person = ioc.getBean("person1",Person.class);
}
複製代碼
調用有參構造器建立對象並賦值正則表達式
<bean id="person1" class="com.bean.Person">
<constructor-arg name="personName" value="張三"></constructor-arg>
<constructor-arg name="personAge" value="18"></constructor-arg>
<!--此處能夠省略name屬性,但須要按照構造器參數的順序指定value值-->
<constructor-arg value="張三"></constructor-arg>
<constructor-arg value="18"></constructor-arg>
<!--index="0" 爲參數指定索引 從0開始-->
<constructor-arg value="張三" index="0"></constructor-arg>
<constructor-arg value="18" index="1"></constructor-arg>
<!--若是有多個有參構造器 使用type指定參數類型-->
<constructor-arg value="張三" index="0"></constructor-arg>
<constructor-arg value="18" index="1" type="java.lang.Integer"></constructor-arg>
</bean>
複製代碼
public void test(){
ApplicationContext ioc = new ClassPathXmlApplicationContext("spring.xml");
Person person = ioc.getBean("person1");
}
複製代碼
名稱空間:在xml中名稱空間是用來防止標籤重複的spring
<!--使用p名稱空間賦值時,需先導入p名稱空間-->
<bean id="person1" class="com.bean.Person" p:personName="張三" p:personAge="18">
</bean>
複製代碼
//實體類
public class Person{
private String name;
private int age;
private Car car;//Car是一個實體類
private List<Book> books;//Book是一個實體類
private Map<String,Object> maps;
private Properties properties;
}
複製代碼
<bean id="car" class="com.bean.Car">
<property name="carNmae" value="寶馬"></property>
</bean>
<bean id="book" class="com.bean.Book">
<property name="bookNmae" value="西遊記"></property>
</bean>
<bean id="person1" class="com.bean.Person">
<!--賦值爲null-->
<property name="name">
<null/>
</property>
<!--ref="car" 這是一個嚴格的引用 person中的car跟 直接從容器中獲取的car是同樣的-->
<property name="car" ref="car"></property>
<!--爲list類型賦值-->
<property name="books">
<list>
<!--內部bean 寫id和不寫id是同樣的 外部獲取不到-->
<bean id="book" class="com.bean.Book" p:bookName="西遊記"></bean>
<ref bean="book"/>
</list>
</property>
<!--爲map類型賦值-->
<bean id="maps">
<!--底層用的是LinkedHashMap-->
<map>
<!--一個entry表明一個鍵值對-->
<entry key="key1"value="value1"></entry>
<entry key="key2"value="value2"></entry>
<entry key="key3"value-ref="book"></entry>
<entry key="key4">
<!--內部bean沒法用id獲取 不管是否有id-->
<bean id="" class="com.bean.Car">
<property name="carName" value="寶馬"></property>
</bean>
</entry>
</map>
</bean>
<!--爲Properties類型賦值-->
<bean name="properties">
<!--properties 裏面 全部的k=v都是String類型-->
<props>
<prop key="username">root</prop>
<prop key="username">123456</prop>
</props>
</bean>
</bean>
複製代碼
<bean id="car01" class="cam.bean.Car">
<property name="carName" value="寶馬"></property>
</bean>
<bean id="person" class="cam.bean.Person">
<property name="car" ref="car01"></property>
<property name="car.carName" value="奔馳"></property>
</bean>
複製代碼
注意sql
<bean id="person1" class="com.bean.Person">
<property name="perName" value="張三"></property>
<property name="perAge" value="15"></property>
<property name="perGender" value="男"></property>
</bean>
<!--parent="" : 指定當前的bean的配置信息繼承於哪一個bean class=""能夠省略不寫 -->
<bean id="person2" class="com.bean.Person" parent="person1">
<property name="perName" value="張三"></property>
</bean>
<!--abstract="true" 表示這個bean只能被繼承 不能夠獲取-->
<bean id="person3" class="com.bean.Person" parent="person1" abstract="true">
<property name="perGender" value="男"></property>
</bean>
複製代碼
<!--原來是按照配置的順序建立bean-->
<bean id="person" class="com.bean.Person"></bean>
<bean id="car" class="com.bean.Car"></bean>
<bean id="book" class="com.bean.Book"></bean>
<!-- depends-on="car,book" 改變bean的建立順序-->
<bean id="person" class="com.bean.Person" depends-on="car,book"></bean>
<bean id="car" class="com.bean.Car"></bean>
<bean id="book" class="com.bean.Book"></bean>
複製代碼
<bean id="book" class="com.bean.Book" scope=""></bean>
複製代碼
scope="" 設置做用域 默認全部的bean都是單實例的數據庫
靜態工廠:工廠自己不用建立對象,經過靜態方法調用,對象 = 工廠類.工廠方法名();express
public class AirPlaneStaticFactory{
//這個方法是靜態方法
public static AirPlane getAirPlane(String planeName){
AirPlane airplane = new AirPlane();
airplane.setPlaneName(planeName);
return airPlane;
}
}
複製代碼
<!--靜態工廠(不須要建立工廠自己) 1.class指定靜態工廠全類名, 2.factory-method 指定工廠方法, 3.constructor-arg 能夠爲方法傳參 -->
<bean id="airPlane" class="com.factory.AirPlaneStaticFactory" factory-method="getAirPlane">
<constructor-arg name="planeName" value="大飛機1號" ></constructor-arg>
</bean>
複製代碼
public void test(){
ApplicationContext ioc = new ClassPathXmlApplicationContext("spring.xml");
//獲取到的是飛機 並非工廠
AirPlane airplane = ioc.getBean("airPlane");
}
複製代碼
**實例工廠:**工廠自己須要建立對象,編程
工廠類 工廠對象 = new 工廠類();session
對象 =工廠對象.工廠方法名();
public class AirPlaneInstanceFactory{
//這個方法不是靜態方法
public AirPlane getAirPlane(String planeName){
AirPlane airplane = new AirPlane();
airplane.setPlaneName(planeName);
return airPlane;
}
}
複製代碼
<!--實例工廠(須要建立工廠自己)-->
<bean id="airPlaneInstanceFactory" class="com.factory.AirPlaneInstanceFactory">
</bean>
<!--factory-bean="" 指定當前對象由哪一個工廠建立 factory-method=""指定工廠方法-->
<bean id="airPlane" class="com.bean.AirPlane" factory-bean="airPlaneInstanceFactory" factory-method="getAirPlane">
<constructor-arg name="planeName" value="大飛機2號" ></constructor-arg>
</bean>
複製代碼
public void test(){
ApplicationContext ioc = new ClassPathXmlApplicationContext("spring.xml");
//獲取到的是飛機 並非工廠
AirPlane airplane = ioc.getBean("airPlane");
}
複製代碼
FactoryBean 是Spring規定的一個接口,只要是這個接口的實現類 ,spring都認爲是一個工廠,Spring會自動調用工廠方法建立實例
第一步:須要寫一個實現了FactoryBean接口的類
public class MyFactoryBeanImpl implements FactoryBean<Book>{
//getObject:工廠方法 返回建立的對象
@Override
public Book getObject() throws Exception{
Book book = new Book();
book.setId(1);
return book;
}
//返回 建立的對象的類型
@Override
public Class<?> getObjectType(){
return Book.class;
}
//返回 是不是單例
//false : 不是單例 true: 是單例
@Override
public boolean isSingleton(){
return false;
}
}
複製代碼
第二步:在配置文件中進行註冊
<!-- 注意!:不管 isSingleton()這個方法返回值是什麼 ioc容器啓動的時候不會建立這個實例-->
<bean id="myFactoryBeanImpl" class="com.factory.MyFactoryBeanImpl"></bean>
複製代碼
**注意 獲取到的是book對象 **
public void test(){
ApplicationContext ioc = new ClassPathXmlApplicationContext("spring.xml");
//獲取到的是book對象
Book book = ioc.getBean("myFactoryBeanImpl");
}
複製代碼
<bean id="book" class="com.bean.Book" destory-method="" init-method="" >
</bean>
複製代碼
<bean id="book" class="com.bean.Book" destory-method="" init-method="" scope="protorype" >
</bean>
複製代碼
數據庫連接池做爲單實例是最好的,一個項目就一個鏈接池,鏈接池裏面管理不少連接,連接是直接從連接池裏面拿
可讓Spring幫咱們建立鏈接池對象 管理鏈接池
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="user" value="root"></property>
<property name="password" value="123456"></property>
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/test"></property>
<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
</bean>
複製代碼
spring管理鏈接池引用外部配置文件
jdbc.properties
#username=root
jdbc.username=root
jdbc.password=123456
jdbc.jdbcUrl=jdbc:mysql://localhost:3306/test
jdbc.driverClass=com.mysql.jdbc.Driver
複製代碼
在ApplicationContext.xml中配置時 須要引入context命名空間
注意!
<!--加載外部配置文件的 classpath: 表示引用類路徑下的配置文件-->
<context:property-placeholder location="classpath:jdbc.properties" />
<!--username 是spring中的一個關鍵字 在這裏不可使用username-->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<!--<property name="user" value="${username}"></property>-->
<property name="user" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
<property name="jdbcUrl" value="${jdbc.jdbcUrl}"></property>
<property name="driverClass" value="${jdbc.driverClass}"></property>
</bean>
複製代碼
**注意!自動裝配僅限於自定義類型的屬性 **
<bean id="car" class="com.bean.Car">
<property name="carName" value="寶馬"></property>
<property name="color" value="白色"></property>
</bean>
<!-- autowire="" default/no:不自動裝配,不自動爲car屬性賦值 byName:以屬性名做爲id去容器中找到一個組件,給他賦值,若是找不到就賦值null byType:以屬性的類型做爲查找依據去容器中找到這個組件,若是容器中有多個這樣的類型會報錯 constructor:按照有參構造器爲car賦值 1.先按照有參構造器參數類型進行裝配,沒有就直接爲組件裝配null 2.若是按照類型找到了多個bean:以參數的名做爲id繼續裝配,找不到就null 假設有一個List<Book> books屬性,容器能夠把容器中全部的book封裝進list -->
<bean id="person" class="com.bean.Person" autowire="default"></bean>
複製代碼
表達式語言
<bean id="car" class="com.bean.Person">
<property name="carName" value="寶馬"></property>
</bean>
<bean id="person" class="com.bean.Person">
<property name="age" value="#{12*5}"></property>
<property name="perName" value="#{car.carName}"></property>
<property name="car" value="#{car}"></property>
<property name="email" value="#{T(java.util.UUID).randomUUID().toString()}"></property>
<property name="testName" value="#{car.getCarName()}"></property>
</bean>
複製代碼
spring有四個註解某個類上註解任何一個均可以講這個組件加入到ioc容器中
使用註解將組價快速加入到容器中須要幾步
給要添加的組件上標上以上四個註解之一
告訴spring,自動掃描加了註解的組件,依賴context命名空間
<!--自動組件掃描-->
<!--base-package="" 指定掃描的基礎包-->
<context:component-scan base-package=""></context:component-scan>
複製代碼
使用context:exclude-filter指定掃描包時不包含的類
掃描的時候能夠排除一些不要的組件
type="annotation":按照註解進行排除-->標註了指定註解的組建不要
expression="":註解的全類名
type="assignable":按照類進行排除
expression="":類的全類名
type="aspectj":aspectj表達式(不多用)
type="custom":自定義一個TypeFilter;本身寫代碼決定哪些使用(不多用)
type="regex":正則表達式(不多用)
<context:component-scan base-package="">
<!--表示標註了@controller的註解不進行掃描-->
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
<!--表示com.controller.BookController這個類不進行掃描-->
<context:exclude-filter type="assignable" expression="com.controller.BookController"/>
</context:component-scan>
複製代碼
使用context:include-filter指定掃描包時包含的類
指定只掃描哪些組件,
注意!須要使用 use-default-filters="false" 取消默認行爲
type="annotation":按照註解進行排除-->標註了指定註解的組建不要
expression="":註解的全類名
type="assignable":按照類進行排除
expression="":類的全類名
type="aspectj":aspectj表達式(不多用)
type="custom":自定義一個TypeFilter;本身寫代碼決定哪些使用(不多用)
type="regex":正則表達式(不多用)
<context:component-scan base-package="" use-default-filters="true">
<!--表示只有標註了@controller的註解進行掃描-->
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
<!--表示只有com.controller.BookController這個類進行掃描-->
<context:include-filter type="assignable" expression="com.controller.BookController"/>
</context:component-scan>
複製代碼
必定要導入AOP包 支持加註解模式
這裏bean的id默認就是類名首字母小寫
使用註解加入到容器中的組件,和使用配置加入到容器中的組件行爲都是默認同樣的:
public void test(){
ApplicationContext ioc = new ClassPathXmlApplicationContext("spring.xml");
Object bean = ioc.getBean("");
}
複製代碼
注意,若是想要修改默認行爲
@Repository("你想要的id名") 四個註解都是同樣的
複製代碼
@Scope(value="prototype")
複製代碼
@Autowired爲bookservice自動賦值
@Controller
public class BookServlet{
@Autowired
private BookService bookService;
}
複製代碼
@Autowired原理
先按照類型去容器中找到對應的組件;bookService = ioc.getBean("BookService.class");
注意!
可使用required=false 來解決 若是@Autowired找不到指定bean 就賦值爲null
@Autowired(required=false)
@Autowired
public void methods(@Qualifier("newbookservice")BookService bookservice){
System.out.println("")
}
複製代碼
導包 導入spring-test-4.0.0
@ContextConfiguration使用這個註解來指定spring的配置文件的位置
@RunWith()指定用哪一種驅動進行單元測試。默認就是junit
@RunWith(SpringJUnit4ClassRunner.class)
使用spring的單元測試模塊來執行標註了@Test註解的測試方法
之前的@Test只是由JUnit執行
@ContextConfiguration(locations="classpath:spring.xml")
@RunWith(SpringJUnit4ClassRunner.class)
public class SpringTest{
ApplicationContext ac = null;
@Autowired
BookServlet bookServlet;
}
複製代碼
泛型依賴注入,注入一個組件的時候,他的泛型也是參考標準
public abstract class BaseDao<T>{
public abstract void save();
...
}
複製代碼
@Repository
public class BookDao extends BaseDao<Book>{
@Override
public void save(){
...
}
...
}
複製代碼
@Repository
public class UserDao extends BaseDao<User>{
@Override
public void save(){
...
}
...
}
複製代碼
@Service
public class BookService extends BaseService<Book>{
...
}
複製代碼
@Service
public class UserService extends BaseService<User>{
...
}
複製代碼
public class BaseService<T>{
@Autowired
private BaseDao<T> baseDao;
public void test(){
baseDao.save();
}
...
}
複製代碼
流程分析
@Test
public void test() {
ApplicationContext ioc = new ClassPathXmlApplicationContext("spring.xml");
BookService bookService = ioc.getBean(BookService.class);
bookService.test();
}
複製代碼