IOC
由于java 編譯后才能運(yùn)行缕溉,由于編譯期進(jìn)行的檢查可能導(dǎo)致我們?nèi)苯M件不能編譯通過弃衍。所以要想個(gè)辦法繞過編譯器的檢測(cè)盲厌,所以反射就引用而生馒过。編譯完成后不能修改參數(shù)臭脓,所以配置文件應(yīng)用而生。
有些時(shí)候?qū)ο笮枰貜?fù)調(diào)用腹忽,這個(gè)時(shí)候需要一個(gè)容器存著可以調(diào)用對(duì)象来累。這個(gè)就是bean。以前都是自己new對(duì)象窘奏,現(xiàn)在是向bean要對(duì)象嘹锁。所以稱為控制反轉(zhuǎn)。
所以有對(duì)象創(chuàng)建對(duì)象獲取兩類着裹。最后還包括main函數(shù)的運(yùn)行兼耀。
main函數(shù)獲取容器里對(duì)象的方法
BeanFactory 才是 Spring 容器中的頂層接口。
ApplicationContext 是它的子接口求冷。
BeanFactory 和 ApplicationContext 的區(qū)別:
創(chuàng)建對(duì)象的時(shí)間點(diǎn)不一樣瘤运。
ApplicationContext:只要一讀取配置文件,默認(rèn)情況下就會(huì)創(chuàng)建對(duì)象匠题。
BeanFactory:什么使用什么時(shí)候創(chuàng)建對(duì)象拯坟。
ApplicationContext 常用三個(gè)實(shí)現(xiàn)類:
ClassPathXmlApplicationContext:
它是從類的根路徑下加載配置文件 推薦使用這種
FileSystemXmlApplicationContext:
它是從磁盤路徑上加載配置文件,配置文件可以在磁盤的任意位置韭山。
AnnotationConfigApplicationContext:
當(dāng)我們使用注解配置容器對(duì)象時(shí)郁季,需要使用此類來創(chuàng)建 spring 容器冷溃。它用來讀取注解。
xml 對(duì)象創(chuàng)建
- 創(chuàng)建方法
<bean id="" class="" scope=""></bean>
id:給對(duì)象在容器中提供一個(gè)唯一標(biāo)識(shí)梦裂。用于獲取對(duì)象似枕。
class:指定類的全限定類名。用于反射創(chuàng)建對(duì)象年柠。默認(rèn)情況下調(diào)用無參構(gòu)造函數(shù)凿歼。
scope:指定對(duì)象的作用范圍。
* singleton :默認(rèn)值冗恨,單例的.
* prototype :多例的.
* request :WEB 項(xiàng)目中
<!-- 告知 spring 創(chuàng)建容器時(shí)要掃描的包 -->
<context:component-scan base-package="com.itheima"></context:component-scan>
- 構(gòu)造方法
<!--構(gòu)造函數(shù)constructor-arg-->
<!--set 注入property-->
<property name="password" value="1234"></property>
<property name="password" ref="引用一個(gè)定義"></property>
- 同樣可以注入集合setmap
<property name="myList">
<array>
<value>AAA</value>
<value>BBB</value>
<value>CCC</value>
</array>
</property>
其中 list 對(duì)應(yīng)array
set對(duì)應(yīng)list
props對(duì)應(yīng)map
如何注入變量呢答憔?
注解創(chuàng)建對(duì)象
- 創(chuàng)建對(duì)象
@Component(value="name")
將當(dāng)前類注入到spring容器。默認(rèn)將首字母改成小寫的掀抹。與<bean id="" class="">
一樣
他們?nèi)齻€(gè)注解都是針對(duì)一個(gè)的衍生注解虐拓,他們的作用及屬性都是一模一樣的。因?yàn)橹挥芯唧w類可以實(shí)例化傲武,所以這里肯定也是可以實(shí)例的類蓉驹。他們只不過是提供了更加明確的語義化。
@Controller:一般用于表現(xiàn)層的注解揪利。
@Service:一般用于業(yè)務(wù)層的注解戒幔。
@Repository:一般用于持久層的注解。
細(xì)節(jié):如果注解中有且只有一個(gè)屬性要賦值時(shí)土童,且名稱是 value,value 在賦值是可以不寫工坊。
- 注入數(shù)據(jù)
- 只能注入其他 bean 類型献汗。
@Autowired
自動(dòng)按照類型注入。當(dāng)使用注解注入屬性時(shí)王污,set 方法可以省略罢吃。它只能注入其他 bean 類型。當(dāng)有多個(gè)類型匹配時(shí)昭齐,使用要注入的對(duì)象變量名稱作為 bean 的 id尿招,在 spring 容器查找,找到了也可以注入成功阱驾。找不到就報(bào)錯(cuò)就谜。
@Qualifier
參數(shù)是名字,通過名字獲取變量數(shù)據(jù)里覆。丧荐。必須在autowired之后。
@Resource
// 注入基本數(shù)據(jù)類型和 String 類型數(shù)據(jù)的
@Value
@scope
singleton
prototype
- 改變作用范圍
@Scope
取值:singleton prototype request session globalsession
getBean('impl',class)???
id,強(qiáng)制類型轉(zhuǎn)換的類型注入數(shù)據(jù)順序
Autowired
Configuration
指定該類的spring配置類喧枷,被指定路徑引入時(shí)可以省略虹统。
獲取容器時(shí)需要使用
AnnotationApplicationContext(有@Configuration 注解的類.class)
@ComponentScan("")
指定需要掃描的包
@PropertySource
property配置文件
@Bean(name="")
只能用于方法上弓坞,表明此方法創(chuàng)建一個(gè)對(duì)象放入容器
@Import
引入其他配置類
-寫property文件
public class JdbcConfig {
@Value("${jdbc.driver}")
private String driver;
@Value("${jdbc.url}")
private String url;
@Value("${jdbc.username}")
private String username;
@Value("${jdbc.password}")
private String password;
//這樣就可以存入spring容器里了。
@Bean(name="dataSource")
public DataSource createDataSource() {
}
}
//jdbc.properties 文件:
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/day44_ee247_spring
-
實(shí)例代碼
- 通過注解獲取容器
ApplicationContext ac =
new AnnotationConfigApplicationContext(SpringConfiguration.class);
- Spring 整合Junit
2.使用@RunWith 注解替換原有運(yùn)行器
3.使用@ContextConfiguration 指定 spring 配置文件的位置
4.使用@Autowired 給測(cè)試類中的變量注入數(shù)據(jù)
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations= {"classpath:bean.xml"})
public class AccountServiceTest {
@Autowired
private IAccountService as ;
}
AOP
Aspect oriented Programming
實(shí)現(xiàn)方式:動(dòng)態(tài)代理的方式车荔。典型應(yīng)用事務(wù)管理渡冻,日志管理。
使用CGlib 的Enhancer 類創(chuàng)建代理對(duì)象
Proxy.newProxyInstance
Spring自帶的AOP細(xì)節(jié)
sprin術(shù)語
Joinpoint(連接點(diǎn)):
所謂連接點(diǎn)是指那些被攔截到的點(diǎn)忧便。在 spring 中,這些點(diǎn)指的是方法,因?yàn)?spring 只支持方法類型
的連接點(diǎn)族吻。
Pointcut(切入點(diǎn)):
所謂切入點(diǎn)是指我們要對(duì)哪些 Joinpoint 進(jìn)行攔截的定義。對(duì)連接點(diǎn)的定義是切入點(diǎn)茬腿。
Advice(通知/增強(qiáng)):
所謂通知是指攔截到 Joinpoint 之后所要做的事情就是通知呼奢。通知的類型:前置通知,后置通知,異常通知,最終通知,環(huán)繞通知。
Introduction(引介):
引介是一種特殊的通知在不修改類代碼的前提下, Introduction 可以在運(yùn)行期為類動(dòng)態(tài)地添加一些方法或 Field切平。
Target(目標(biāo)對(duì)象):
代理的目標(biāo)對(duì)象握础。
Weaving(織入):
是指把增強(qiáng)應(yīng)用到目標(biāo)對(duì)象來創(chuàng)建新的代理對(duì)象的過程。spring 采用動(dòng)態(tài)代理織入悴品,而 AspectJ 采用編譯期織入和類裝載期織入禀综。
Proxy(代理):
一個(gè)類被 AOP 織入增強(qiáng)后,就產(chǎn)生一個(gè)結(jié)果代理類苔严。
Aspect(切面):
是切入點(diǎn)和通知(引介)的結(jié)合定枷。
- 1.配置
<!-- 配置通知 -->
<bean id="txManager" class="com.itheima.utils.TransactionManager">
<property name="dbAssit" ref="dbAssit"></property>
</bean>
- 2.聲明aop
<aop:config>
...........
</aop:config>
- 3.配置切面
<aop:aspect id="txAdvice" ref="txManager">
<!--配置通知的類型要寫在此處-->
</aop:aspect>
ref 引用已經(jīng)配置好的通知類bean的id
- 4.配置切入點(diǎn)表達(dá)式
<aop:pointcut expression="execution(
public void com.itheima.service.impl.AccountServiceImpl.transfer(
java.lang.String, java.lang.String, java.lang.Float)
)" id="pt1"/>
- 配置具體的通知
<aop:before method="方法" pointct-ref="引用切入點(diǎn)表達(dá)式">
- 代碼
<aop:config>
<aop:pointcut expression="execution(* com.itheima.service.impl.*.*(..))"id="pt1"/>
<aop:aspect id="txAdvice" ref="txManager">
<!-- 配置環(huán)繞通知 -->
<aop:around method="transactionAround" pointcut-ref="pt1"/>
</aop:aspect>
</aop:config>
使用注解方式實(shí)現(xiàn)aop
- 創(chuàng)建通知類,聲明為切面類
@Component("txManager")
@Aspect//表明當(dāng)前類是一個(gè)切面類
public class TransactionManager {
//定義一個(gè) DBAssit
@Autowired
private DBAssit dbAssit ;
}
- 2.在 spring 配置文件中開啟 spring 對(duì)注解 AOP 的支持
<aop:aspectj-autoproxy/>
- 3.切面表達(dá)式
@Pointcut("execution(* com.itheima.service.impl.*.*(..))")
private void pt1() {
}
- 4.定義通知
@Around("pt1()")//注意:千萬別忘了寫括號(hào)
public Object transactionAround(ProceedingJoinPoint pjp) {
//怎么獲得函數(shù)的名字
//定義返回值
Object rtValue = null;
try {
//獲取方法執(zhí)行所需的參數(shù)
Object[] args = pjp.getArgs();
//前置通知:開啟事務(wù)
beginTransaction();
//執(zhí)行方法
rtValue = pjp.proceed(args);
//后置通知:提交事務(wù)
commit();
}catch(Throwable e) {
//異常通知:回滾事務(wù)
rollback();
e.printStackTrace();
}finally {
//最終通知:釋放資源
release();
}
return rtValue;
}
環(huán)境搭建
- 在配置文件中導(dǎo)入 context 的名稱空間
jdbcTemplate
- aop 和tx命名空間
- 實(shí)體類届氢,編寫業(yè)務(wù)層接口和實(shí)現(xiàn)類
- 持久層和實(shí)現(xiàn)類
- 在配置文件中配置業(yè)務(wù)層和持久層對(duì)
<!-- 配置業(yè)務(wù)層-->
<bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl">
<property name="accountDao" ref="accountDao"></property>
</bean>
<!-- 配置賬戶的持久層-->
<bean id="accountDao" class="com.itheima.dao.impl.AccountDaoImpl">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 配置數(shù)據(jù)源-->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql://localhost:3306/eesy"></property>
<property name="username" value="root"></property>
<property name="password" value="1234"></property>
</bean>
<!-- spring中基于XML的聲明式事務(wù)控制配置步驟
1欠窒、配置事務(wù)管理器
2、配置事務(wù)的通知
此時(shí)我們需要導(dǎo)入事務(wù)的約束 tx名稱空間和約束退子,同時(shí)也需要aop的
使用tx:advice標(biāo)簽配置事務(wù)通知
屬性:
id:給事務(wù)通知起一個(gè)唯一標(biāo)識(shí)
transaction-manager:給事務(wù)通知提供一個(gè)事務(wù)管理器引用
3岖妄、配置AOP中的通用切入點(diǎn)表達(dá)式
4、建立事務(wù)通知和切入點(diǎn)表達(dá)式的對(duì)應(yīng)關(guān)系
5寂祥、配置事務(wù)的屬性
是在事務(wù)的通知tx:advice標(biāo)簽的內(nèi)部
-->
<!-- 配置事務(wù)管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 配置事務(wù)的通知-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<!-- 配置事務(wù)的屬性
isolation:用于指定事務(wù)的隔離級(jí)別荐虐。默認(rèn)值是DEFAULT,表示使用數(shù)據(jù)庫的默認(rèn)隔離級(jí)別丸凭。
propagation:用于指定事務(wù)的傳播行為福扬。默認(rèn)值是REQUIRED,表示一定會(huì)有事務(wù)惜犀,增刪改的選擇铛碑。查詢方法可以選擇SUPPORTS。
read-only:用于指定事務(wù)是否只讀虽界。只有查詢方法才能設(shè)置為true亚茬。默認(rèn)值是false,表示讀寫浓恳。
timeout:用于指定事務(wù)的超時(shí)時(shí)間刹缝,默認(rèn)值是-1碗暗,表示永不超時(shí)。如果指定了數(shù)值梢夯,以秒為單位言疗。
rollback-for:用于指定一個(gè)異常,當(dāng)產(chǎn)生該異常時(shí)颂砸,事務(wù)回滾噪奄,產(chǎn)生其他異常時(shí),事務(wù)不回滾人乓。沒有默認(rèn)值勤篮。表示任何異常都回滾。
no-rollback-for:用于指定一個(gè)異常色罚,當(dāng)產(chǎn)生該異常時(shí)碰缔,事務(wù)不回滾,產(chǎn)生其他異常時(shí)事務(wù)回滾戳护。沒有默認(rèn)值金抡。表示任何異常都回滾。
-->
<tx:attributes>
<tx:method name="*" propagation="REQUIRED" read-only="false"/>
<tx:method name="find*" propagation="SUPPORTS" read-only="true"></tx:method>
</tx:attributes>
</tx:advice>
<!-- 配置aop-->
<aop:config>
<!-- 配置切入點(diǎn)表達(dá)式-->
<aop:pointcut id="pt1" expression="execution(* com.itheima.service.impl.*.*(..))"></aop:pointcut>
<!--建立切入點(diǎn)表達(dá)式和事務(wù)通知的對(duì)應(yīng)關(guān)系 -->
<aop:advisor advice-ref="txAdvice" pointcut-ref="pt1"></aop:advisor>
</aop:config>
- spring-framework-5.0.02.RELEASE
- xmlns
- xsi
- xsi:schemaLocation