Spring 核心組件總結


spring核心組件總結

spring介紹

2018-09-29_114847

spring概念

IOC: Inverse Of Control 控制反轉

​ 將我們創建對象的方式反轉了,以前創建對象是由我們開發人員自己維護,包括依賴注入關系也是自己注入。

​ 使用了spring之后,對象的創建以及依賴關系,由spring完成創建以及注入。

​ 控制反轉就是反轉了對象的創建方式。從我們自己創建反轉給了spring

2018-09-29_112547

DI: Dependency Injection 依賴注入

​ 實現ioc思想需要 DI提供支持

​ 注入方式:1)set方式注入 2) 構造方法注入 3) 字段注入(不推薦)

​ 注入類型:1) 值類型注入 2)引用類型注入

AOP 面向切面的編程 (橫向重復,縱向抽取)

舉例:攔截器(身份校驗)、過濾器(編碼處理)、動態代理(事務)

spring aop實現原理

動態代理(優先):被代理對象必須要實現接口,才能產生代理對象.如果沒有接口將不能使用動態代理技術

cglib代理(沒有接口):第三方代理技術,cglib代理.可以對任何類生成代理.代理的原理是對目標對象進行繼承代理. 如果目標對象被final修飾.那么該類無法被cglib代理.

spring名詞解釋

2018-09-29_183858

aop依賴所需包

2018-09-29_233628

aop代碼演示(xml配置)

//通知類
public class MyAdvice {
	//前置通知	
	//	|-目標方法運行之前調用
	//后置通知(如果出現異常不會調用)
	//	|-在目標方法運行之后調用
	//環繞通知
	//	|-在目標方法之前和之后都調用
	//異常攔截通知
	//	|-如果出現異常,就會調用
	//后置通知(無論是否出現 異常都會調用)
	//	|-在目標方法運行之后調用
	//----------------------------------------------------------------
	//前置通知
	public void before(){
		System.out.println("這是前置通知");
	}
	//后置通知
	public void afterReturning(){
		System.out.println("這是后置通知(出現異常不執行)!!");
	}
	//環繞通知
	public Object around(ProceedingJoinPoint pjp) throws Throwable {
		System.out.println("這是環繞通知之前的部分!");
		Object proceed = pjp.proceed();//璋冪敤鐩爣鏂規硶
		System.out.println("這是環繞通知之后的部分");
		return proceed;
	}
	//異常通知
	public void afterException(){
		System.out.println("這是異常通知,出現異常執行!");
	}
	//后置通知
	public void after(){
		System.out.println("這是后置通知(出現異常也會調用)!!");
	}
}
	<!-- 1.配置目標對象 -->
	<bean name="userService" class="com.yoci.service.UserServiceImpl"></bean>

	<!-- 2.配置通知對象 -->
	<bean name="myAdvice" class="com.yoci.springaop.MyAdvice"></bean>

	<!-- 3.配置將通知織入目標對象 -->
	<aop:config>
		<!-- 配置切入點 
			public void cn.itcast.service.UserServiceImpl.save() 
			void cn.itcast.service.UserServiceImpl.save()
			* cn.itcast.service.UserServiceImpl.save()
			* cn.itcast.service.UserServiceImpl.*()
			* cn.itcast.service.*ServiceImpl.*(..)
			* cn.itcast.service..*ServiceImpl.*(..)
		-->
		<aop:pointcut expression="execution(* com.yoci.service.*ServiceImpl.*(..))" id="pc"/>
		<aop:aspect ref="myAdvice">
			<!-- 指定名為before方法作為前置通知 -->
			<aop:before method="before" pointcut-ref="pc"/>
			<!-- 后置 -->
			<aop:after-returning method="afterReturning" pointcut-ref="pc" />
			<!-- 環繞通知 -->
			<aop:around method="around" pointcut-ref="pc"/>
			<!-- 異常攔截通知 -->
			<aop:after-throwing method="afterException" pointcut-ref="pc"/>
			<!-- 后置 -->
			<aop:after method="after" pointcut-ref="pc"/>
		</aop:aspect>
	</aop:config>

aop代碼演示(注解配置)

//通知類
@Aspect
public class MyAdvice {

	@Pointcut("execution(* com.yoci.service.*ServiceImpl.*(..))")
	public void pointcut(){}
	
	@Before("MyAdvice.pointcut()")
	public void before(){
		System.out.println("這是前置通知");
	}
	@AfterReturning("execution(* com.yoci.service.*ServiceImpl.*(..))")
	public void afterReturning(){
		System.out.println("這是后置通知(出現異常不執行)!!");
	}

	@Around("execution(* com.yoci.service.*ServiceImpl.*(..))")
	public Object around(ProceedingJoinPoint pjp) throws Throwable {
		System.out.println("這是環繞通知之前的部分!");
		Object proceed = pjp.proceed();//調用目標方法
		System.out.println("這是環繞通知之后的部分");
		return proceed;
	}
	
	@AfterThrowing("execution(* com.yoci.service.*ServiceImpl.*(..))")
	public void afterException(){
		System.out.println("這是異常通知,出現異常執行!");
	}

	@After("execution(* com.yoci.service.*ServiceImpl.*(..))")
	public void after(){
		System.out.println("這是后置通知(出現異常也會調用)!!");
	}
}
	<!-- 1.配置目標對象 -->
	<bean name="userService" class="com.yoci.service.UserServiceImpl"></bean>

	<!-- 2.配置通知對象 -->
	<bean name="myAdvice" class="com.yoci.annotationaop.MyAdvice"></bean>

	<!-- 3.開啟使用注解完成織入 -->
	<aop:aspectj-autoproxy></aop:aspectj-autoproxy>

spring 中的工廠(容器)

2018-09-29_144133

​ ApplicationContext接口由兩個實現類:

​ 1) ClassPathXmlApplicationContext: 加載類路徑下的spring的配置

​ 2)FilesSystemXmlApplicationContext:加載本地磁盤下的spring的配置

​ BeanFactrory(過時)

BeanFactory和ApplicationContext的區別:

​ 1)BeanFactory:是在getBean的時候才會生成類的實例

​ 2)ApplicationContext:是在加載applicationContext.xml(容器啟動)時就會創建

spring配置詳解

Bean元素

	<!-- 將User對象交給spring容器管理 -->
	<!-- Bean元素:使用該元素描述需要spring容器管理的對象
			class屬性:被管理對象的完整類名.
			name屬性:給被管理的對象起個名字.獲得對象時根據該名稱獲得對象.  
					可以重復.可以使用特殊字符.
			id屬性: 與name屬性一模一樣. 
					名稱不可重復.不能使用特殊字符.
			結論: 盡量使用name屬性.
	  -->
	<bean  name="user" class="cn.itcast.bean.User" ></bean>

	<!-- 導入其他spring配置文件 -->
	<!-- 分模塊配置 -->
	<import resource="cn/itcast/b_create/applicationContext.xml"/>

Bean元素進階

​ scope屬性(作用域)

1)singleton(默認值):單例對象.被標識為單例的對象在spring容器中只會存在一個實例

2)prototype:多例原型.被標識為多例的對象,每次再獲得才會創建.每次創建都是新的對象.整合struts2時,ActionBean必須配置為多例的.

​ 3)request:web環境下.對象與request生命周期一致.

​ 4)session:web環境下,對象與session生命周期一致.

​ 5)global-session:global-session和Portlet應用相關。當你的應用部署在Portlet容器中工作時,它包含很多portlet。如果你想要聲明讓所有的portlet共用全局的存儲變量的話,那么這全局變量需要存儲在global-session中。

​ 生命周期屬性

​ 1)init-method:配置一個方法作為生命周期初始化方法.spring會在對象創建之后立即調用.

​ 2)destory-method:配置一個方法作為生命周期的銷毀方法.spring容器在關閉並銷毀所有容器中的對象之前調用.

<bean  name="user" class="cn.itcast.bean.User"
		 init-method="init" destroy-method="destory" ></bean>
public class User {
	private String name;
	private Integer age;
	private Car car;

	public Car getCar() {return car;}
	public void setCar(Car car) {this.car = car;}
	public String getName() {return name;}
	public void setName(String name) {this.name = name;}
	public Integer getAge() {return age;}
	public void setAge(Integer age) {this.age = age;}
  
	public void init(){
		System.out.println("我是初始化方法!");
	}
	public void destory(){
		System.out.println("我是銷毀方法!");
	}
	@Override
	public String toString() {
		return "User [name=" + name + ", age=" + age + ", car=" + car + "]";
	}
	
}

spring創建對象的方式

​ 1)空參構造方式

​ 2)靜態工廠(了解)

​ 3)實例工廠(了解)

	<!-- 創建方式1:空參構造創建  -->
	<bean  name="user" class="cn.itcast.bean.User"
		 init-method="init" destroy-method="destory" ></bean>

	<!-- 創建方式2:靜態工廠創建 
		  調用UserFactory的createUser方法創建名為user2的對象.放入容器
	 -->
	<bean  name="user2" 
		class="cn.itcast.b_create.UserFactory" 
		factory-method="createUser" ></bean>

	<!-- 創建方式3:實例工廠創建 
		 調用UserFactory對象的createUser2方法創建名為user3的對象.放入容器
	 -->
	<bean  name="user3" 
		factory-bean="userFactory"
		factory-method="createUser2" ></bean>
		
	<bean  name="userFactory" 
		class="cn.itcast.b_create.UserFactory"   ></bean>
public class UserFactory {

	public static User createUser(){
		
		System.out.println("靜態工廠創建User");
		
		return new User();
		
	}
	
	public  User createUser2(){
		
		System.out.println("實例工廠創建User");
		
		return new User();
		
	}
	
}

spring屬性注入

	<!-- set方式注入: -->
	<bean name="user" class="com.yoci.entity.User" >
		<!-- 值類型注入 -->
		<property name="name" value="zhangsan"></property>
		<property name="age" value="22"></property>
		<!-- 引用類型注入 -->
		<property name="car" ref="car"></property>
	</bean>
	
	<!-- 將car對象配置到容器當中 -->
	<bean name="car" class="com.yoci.entity.Car">
		<property name="name" value="蘭博基尼"></property>
		<property name="color" value="黃色"></property>
	</bean>
	
	
	<!-- 構造函數注入 -->
	<bean name="user1" class="com.yoci.entity.User">
		<!-- name屬性: 構造函數的參數名 -->
		<!-- index屬性: 構造函數的參數索引 -->
		<!-- type屬性: 構造函數的參數類型-->
		<constructor-arg name="name" index="0"  value="李四" ></constructor-arg>
		<constructor-arg name="car" index="1" ref="car" ></constructor-arg>
	</bean>
	
	<!-- p名稱空間注入 -->
	<!-- 
		1.導入P名稱空間  xmlns:p="http://www.springframework.org/schema/p"
		2.使用p:屬性完成注入
		-值類型: p:屬性名="值"
		-對象類型: p:屬性名-ref="bean名稱" -->
	<bean name="user2" class="com.yoci.entity.User" p:name="wangwu" p:age="26" p:car-ref="car"></bean>
	
	<!-- spEL注入 -->
	<bean name="user3" class="com.yoci.entity.User">
		<property name="name" value="#{user1.name}"></property>
		<property name="age" value="#{user2.age}"></property>
		<property name="car" ref="car"></property>
	</bean>

	<!-- 復雜類型注入 -->
	<bean name="collection" class="com.yoci.entity.Collection">
		<!-- 如果數組中只准備注入一個值(對象),直接使用value|ref即可 
			<property name="arr" value="tom" ></property>
		-->
		<!-- array注入,多個元素注入 -->
		<property name="arr">
			<array>
				<value>tom</value>
				<value>jack</value>
				<ref bean="user2"></ref>
			</array>
		</property>
		
		<!-- 
			如果List中只准備注入一個值(對象),直接使用value|ref即可 
			<property name="list" value="jack" ></property>
		-->
		<property name="list">
			<list>
				<value>zhangsan</value>
				<value>李四</value>
				<ref bean="user"/>
			</list>
		</property>
		
		<!-- map類型注入 -->
		<property name="map">
			<map>
				<entry key="url" value="www.yoci.com"></entry>
				<entry key="user3" value-ref="user"></entry>
			</map>
		</property>
		
		<!-- prperties 類型注入 -->
		<property name="prop">
			<props>
				<prop key="driverClass">com.jdbc.mysql.Driver</prop>
				<prop key="userName">root</prop>
				<prop key="password">1234</prop>
			</props>
		</property>

spring事務

什么是事務:

​ 事務邏輯上的一組操作,組成這組操作的各個邏輯單元,要么一起成功,要么一起失敗。

事務特性

原子性 :強調事務的不可分割.

一致性 :事務的執行的前后數據的完整性保持一致.

隔離性 :一個事務執行的過程中,不應該受到其他事務的干擾

持久性 :事務一旦結束,數據就持久到數據庫

如果不考慮隔離性引發安全性問題:

臟讀 :一個事務讀到了另一個事務的未提交的數據

不可重復讀 :一個事務讀到了另一個事務已經提交的 update 的數據導致多次查詢結果不一致.

虛幻讀 :一個事務讀到了另一個事務已經提交的 insert 的數據導致多次查詢結果不一致.

解決讀問題:設置事務隔離級別

未提交讀 :臟讀,不可重復讀,虛讀都有可能發生

已提交讀 :避免臟讀。但是不可重復讀和虛讀有可能發生

可重復讀 :避免臟讀和不可重復讀.但是虛幻讀有可能發生.

串行化的 :避免以上所有讀問題.

Mysql 默認:可重復讀 Oracle 默認:讀已提交

事務的操作對象

​ 在spring中玩事務管理.最為核心的對象就TransactionManager對象

事務的屬性介紹

​ 事務隔離級別:

​ 1 讀未提交 2 讀已提交 4 可重復讀 8 串行化

​ 是否只讀:

​ true/false

​ 事務的傳播行為:

2018-09-29_234855

spring代碼(xml配置)

<!-- 事務管理器 -->
	<bean id="transactionManager"	class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<!-- 數據源 -->
		<property name="dataSource" ref="dataSource" />
	</bean>

	<!-- 通知 -->
	<tx:advice id="txAdvice" transaction-manager="transactionManager">
		<tx:attributes>
			
          <!-- 以方法為單位,指定方法應用什么事務屬性
			isolation:隔離級別
			propagation:傳播行為
			read-only:是否只讀
		 -->
          <!-- 傳播行為 -->
		<tx:method name="save*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" />
		<tx:method name="persist*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" />
		<tx:method name="update*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" />
		<tx:method name="modify*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" />
		<tx:method name="delete*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" />
		<tx:method name="remove*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" />
		<tx:method name="get*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="true" />
		<tx:method name="find*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="true" />
		<tx:method name="transfer" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" />
		</tx:attributes>
	</tx:advice>

	<!-- 切面 -->
	<aop:config>
		<aop:advisor advice-ref="txAdvice"
			pointcut="execution(* cn.itcast.crm.service.*.*(..))" />
	</aop:config>


spring代碼(注解配置)

<!-- 事務管理器 -->
	<bean id="transactionManager"	class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<!-- 數據源 -->
		<property name="dataSource" ref="dataSource" />
	</bean>

<!-- 開啟使用注解管理aop事務 -->
<tx:annotation-driven/>

@Transactional(isolation=Isolation.REPEATABLE_READ,propagation=Propagation.REQUIRED,readOnly=true)
public class AccountServiceImpl implements AccountService {

	private AccountDao ad ;
	private TransactionTemplate tt;
		@Transactional(isolation=Isolation.REPEATABLE_READ,propagation=Propagation.REQUIRED,readOnly=false)
	public void transfer(final Integer from,final Integer to,final Double money) {
				//減錢
				ad.decreaseMoney(from, money);
				int i = 1/0;
				//加錢
				ad.increaseMoney(to, money);
	}

}


spring注解

開啟spring注解

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd ">
  
<!-- 
	引入:
	xmlns:context="http://www.springframework.org/schema/context"
	http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-4.2.xsd
-->
<!-- 指定掃描cn.itcast.bean報下的所有類中的注解.
	 注意:掃描包時.會掃描指定報下的所有子孫包
 -->
<context:component-scan base-package="cn.itcast.bean"></context:component-scan>

</beans>

注解使用介紹

@Component("user") = <bean name="user" class="cn.itcast.bean.User"  />
  // service層
  @Service("user") 
  // web層
  @Controller("user") 
  // dao層
  @Repository("user")
  
//指定對象的作用范圍
@Scope(scopeName="singleton/prototype")
  
//屬性注入,推薦使用set方法注入方式, 第一種破壞封裝性
@Value("18")
private Integer age;
@Value("tom")	
public void setName(String name) {
  this.name = name;
}

//自動裝配
@Autowired //問題:如果匹配多個類型一致的對象.將無法選擇具體注入哪一個對象.
@Qualifier("car2")//使用@Qualifier 配合 @Autowired注解告訴spring容器自動裝配哪個名稱的對象
//手動裝配,指定注入哪個名稱的對象
@Resource(name="car")
private Car car;

//在對象被創建后調用.init-method
@PostConstruct 
public void init(){
  System.out.println("我是初始化方法!");
}

//在銷毀之前調用.destory-method
@PreDestroy 
public void destory(){
  System.out.println("我是銷毀方法!");
}



spring整合junit測試

導入aop+test包

//幫我們創建容器
@RunWith(SpringJUnit4ClassRunner.class)
//指定創建容器時使用哪個配置文件
@ContextConfiguration("classpath:applicationContext.xml")
//指定多個配置文件時
@ContextConfiguration(locations = { "classpath*:/spring1.xml", "classpath*:/spring2.xml" }) 
public class Demo {
	//將名為user的對象注入到u變量中
	@Resource(name="user")
	private User u;
	
	@Test
	public void fun1(){
		
		System.out.println(u);
		
	}

}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM