您好,登錄后才能下訂單哦!
這篇文章給大家分享的是有關SSM框架之Spring怎么用的內容。小編覺得挺實用的,因此分享給大家做個參考,一起跟隨小編過來看看吧。
控制反轉:對對象(beans)控制權的轉移,從程序代碼本身反轉到了外部容器(xml配置文件, applicationContext.xml)
對象的創建不是在view層,而是通過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" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- 注冊Service 底層相當于ISomeService service = new SomeServiceImpl(); --> <bean id="myService" class="service.SomeServiceImpl"/> </beans>
ApplicationContext容器:反應速度快/占用資源
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml"); //創建容器對象(對象bean也創建了) ISomeService service = (ISomeService) ac.getBean("myService"); //從容器獲取對象 service.doSome();
BeanFactory容器:反應速度慢/省資源(因為scope="prototype"的存在,已棄用)
BeanFactory bf = new XmlBeanFactory(new ClassPathResource("applicationContext.xml")); //創建容器對象(對象bean沒創建) ISomeService service = (ISomeService) bf.getBean("myService"); service.doSome();
裝配即對象的生成
(1)默認方式
調用類的無參構造器
<bean id="myService" class="ba01.SomeServiceImpl"/>
(2)動態工廠bean
通過工廠類創建對象
<!-- 注冊動態動態工廠 --> <bean id="factory" class="ba02_dynamicF.ServiceFactory"/> <!-- 注冊Service :動態工廠Bean --> <bean id="myService" factory-bean="factory" factory-method="getSomeService" scope="prototype"/> //通過factory對象中的getSomeService方法創建myService對象 //scope:原型模式,每次對象都是新的(獲取對象的是否才創建對象)
(3)靜態工廠bean
<bean id="myService" class="ba03_silenceF.ServiceFactory" factory-method="getSomeService"/> <!-- 相當于ServiceFactory.getSomeService -->靜態工廠不需要創建對象
(4)bean后處理器
(5)bean的生命周期
注入:對對象屬性賦值
(1)分類
設值注入:通過<property>,前提:在類里面有set方法
<bean id="myService" class="ba06.SomeServiceImpl" init-method="setUp" destroy-method="tearDown"> <property name="adao" value="aaa"/> <!-- 給對象屬性注入值 --> <property name="bdao" value="bbb"/>
構造注入:
(2)集合屬性注入值
<property name="myList" value="大興,亦莊"/>
(3)指定多個配置文件
ApplicationContext ac = new ClassPathXmlApplicationContext("spring-*.xml"); //可變參數
注釋:替換spring配置文件中bean的注冊
@Component(value="mySchool") //表示當前類被Spring容器所管理 public class School { @Value(value="清華大學") private String name;
面向切片編程:切面——交叉業務邏輯(通知advice/顧問advisor,對主業務的增強),主業務邏輯(需要做的,在接口中定義的方法)
aop思想讓系統業務邏輯和主業務邏輯分開開發,底層使用動態代理增強主業務邏輯
術語:
通知(Advice)
連接點(JoinPoint)
切入點(Pointcut)
切面(Aspect):包含通知的類,對目標方法增強的類
引入(introduction)
目標(target)
代理(proxy)
織入(weaving)
(1)Advice通知
前置通知:目標方法執行之前執行
public class MyMethodBeforeAdvice implements MethodBeforeAdvice { //當前方法在目標方法執行前執行 //method:目標方法 //args:目標方法的參數列表 //target:目標對象 @Override public void before(Method method, Object[] args, Object target) throws Throwable { //對目標方法的增強代碼寫在這里! System.out.println("執行前置通知方法"); } }
<!-- 注冊目標對象 --> <bean id="someService" class="aop01.SomeServiceImpl"/> <!-- 注冊切面:通知 --> <bean id="myAdvice" class="aop01.MyMethodBeforeAdvice"/> <!-- 生成代理對象 --> <bean id="serviceProxy" class="org.springframework.aop.framework.ProxyFactoryBean"> <!-- 指定目標對象 --> <property name="target" ref="someService"/> <!-- 相當于傳遞給invoke的target:實現類對象 --> <!-- 指定切面 --> <property name="interceptorNames" value="myAdvice"/> </bean>
public class MyTest { @Test public void test01() { ApplicationContext ac = new ClassPathXmlApplicationContext("aop02/applicationContext.xml"); ISomeService service = (ISomeService) ac.getBean("serviceProxy"); //代理對象 service.doFirst(); System.out.println("================="); service.doSecond(); } }
后置通知:目標方法執行之后執行
public class MyAfterReturningAdvice implements AfterReturningAdvice { //在目標方法執行之后執行 //returnValue:目標方法的返回值,可以獲取但是不能改變 @Override public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable { System.out.println("執行后置通知方法 returnValue=" + returnValue); } }
<!-- 注冊目標對象 --> <bean id="someService" class="aop02.SomeServiceImpl"/> <!-- 注冊切面:通知 --> <bean id="myAdvice" class="aop02.MyAfterReturningAdvice"/> <!-- 生成代理對象 --> <bean id="serviceProxy" class="org.springframework.aop.framework.ProxyFactoryBean"> <property name="target" ref="someService"/> <!-- 相當于傳遞給invoke的target:實現類對象 --> <property name="interceptorNames" value="myAdvice"/> </bean>
環繞通知:目標方法執行前后都執行
public class MyMethodinterceptor implements MethodInterceptor { @Override public Object invoke(MethodInvocation invocation) throws Throwable { System.out.println("執行環繞通知:目標方法執行之前"); //執行目標方法 Object result = invocation.proceed(); //類似于method.invoke() System.out.println("執行環繞通知:目標方法執行之后"); return result; //可獲取目標方法結果,且能修改 } }
異常通知:當目標方法拋出指定類型的異常時,執行當前方法
public class MyThrowsAdvice implements ThrowsAdvice { public void afterThrowing(UsernameException ex) { System.out.println("發生用戶名異常:" + ex.getMessage()); } public void afterThrowing(PasswordException ex) { System.out.println("發生密碼異常:" + ex.getMessage()); } //其他異常執行該方法 public void afterThrowing(Exception ex) { System.out.println("異常:" + ex.getMessage()); } }
(2)Advisor顧問
通知會增強所有的目標方法,增強某些目標方法需要用顧問,對通知進行了包裝
名稱匹配切入點顧問
<!-- 注冊目標對象 --> <bean id="someService" class="aop05_advisor.SomeServiceImpl"/> <!-- 注冊切面:通知 --> <bean id="myAdvice" class="aop05_advisor.MyAfterReturningAdvice"/> <!-- 注冊切面:顧問 --> <bean id="myAdvisor" class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor"> //名稱匹配 <!-- 指定通知 --> <property name="advice" ref="myAdvice"/> <!-- 指定通知切入點 --> //***** <!-- <property name="mappedName" value="doFirst"/> --> <property name="mappedNames" value="doFirst,doThird"></property> </bean> <!-- 生成代理對象 --> <bean id="serviceProxy" class="org.springframework.aop.framework.ProxyFactoryBean"> <property name="target" ref="someService"/> <property name="interceptorNames" value="myAdvisor"/> //*****代理用的顧問 </bean>
正則表達式匹配切入點顧問
<!-- 注冊目標對象 --> <bean id="someService" class="aop06_advisor.SomeServiceImpl"/> <!-- 注冊切面:通知 --> <bean id="myAdvice" class="aop06_advisor.MyAfterReturningAdvice"/> <!-- 注冊切面:顧問2 --> <bean id="myAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor"> <!-- 指定通知 --> <property name="advice" ref="myAdvice"/> <!-- 指定通知切入點 --> <property name="pattern" value=".*doFirst"/> <!-- 正則表達式(方法全路徑) .* —— 字符出現多次 --> </bean>
自動代理生成器DefaultAdvisorAutoProxyCreator
不用指定需要代理的對象,都會生成代理,引用的也直接是目標對象
名稱自動代理生成器BeanNameAutoProxyCreator
(3)AspectJ對AOP的實現
AspectJ:是一個面向切面的框架,定義了AOP語法。
Spring并入了AspectJ框架
AspectJ和Spring對AOP實現的區別:
aspectj多一個最終通知(無論怎樣都會執行)
切入點表達式:
AspectJ基于注解的AOP:
前置通知
<!-- 注冊切面 --> <bean id="myAspect" class="com.bjpowernode.annotation.MyAspect"/> <!-- 注冊目標對象 --> <bean id="someService" class="com.bjpowernode.annotation.SomeServiceImpl"/> <!-- 注冊AspectJ的自動代理 --> <aop:aspectj-autoproxy/>
@Before("execution(* *..ISomeService.doFirst(..))") //切入點表達式 public void myBefore() { System.out.println("執行前置通知方法"); }
AspectJ基于XML的AOP:
<!-- 注冊切面 --> <bean id="myAspect" class="com.bjpowernode.xml.MyAspect"/> <!-- 注冊目標對象 --> <bean id="someService" class="com.bjpowernode.xml.SomeServiceImpl"/> <!-- AOP配置 --> //***** <aop:config> <aop:pointcut expression="execution(* *..ISomeService.doFirst(..))" id="doFirstPointcut"/> <aop:pointcut expression="execution(* *..ISomeService.doSecond(..))" id="doSecondPointcut"/> <aop:pointcut expression="execution(* *..ISomeService.doThird(..))" id="doThirdPointcut"/> <aop:aspect ref="myAspect"> <aop:before method="myBefore" pointcut-ref="doFirstPointcut"/> <aop:before method="myBefore(org.aspectj.lang.JoinPoint)" pointcut-ref="doFirstPointcut"/> <aop:after-returning method="myAfterReturning" pointcut-ref="doSecondPointcut"/> <aop:after-returning method="myAfterReturning(java.lang.Object)" pointcut-ref="doSecondPointcut" returning="result"/> <aop:around method="myAround" pointcut-ref="doSecondPointcut"/> <aop:after-throwing method="myAfterThrowing" pointcut-ref="doThirdPointcut"/> <aop:after-throwing method="myAfterThrowing(java.lang.Exception)" pointcut-ref="doThirdPointcut" throwing="ex"/> <aop:after method="myAfter" pointcut-ref="doThirdPointcut"/> </aop:aspect> </aop:config>
// 切面 public class MyAspect { public void myBefore() { System.out.println("執行前置通知方法"); } }
為了避免直接使用JDBC帶來復雜和冗長的代碼,Spring提供了一個強有力的模板類jdbcTemplate來簡化JDBC操作
(1)基礎操作
注冊數據源
<bean id="myDataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://127.0.0.1:3366/test"/> <property name="username" value="root"/> <property name="password" value="111"/> </bean>
注冊jdbcTemplate
<!-- 注冊JdbcTemplate --> <!-- <bean id="myJdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource" ref="myDataSource"/> </bean> <bean id="studentDao" class="com.bjpowernode.dao.StudentDaoImpl"> <property name="jdbcTemplate" ref="myJdbcTemplate"/> </bean>
注冊Dao
<!-- 注冊Dao --> <bean id="studentDao" class="com.bjpowernode.dao.StudentDaoImpl"> //含具體增刪改查 <property name="dataSource" ref="myDataSource"/> </bean>
注冊服務
<!-- 注冊Service --> <bean id="studentService" class="com.bjpowernode.service.StudentServiceImpl"> <property name="dao" ref="studentDao"/> //***依賴注入 </bean>
注:<property name="dao" ref="studentDao"/> 依賴注入,初始化對象屬性,在studentService對象中可使用dao對象中的方法,dao對象中的方法含有sql語句,sql語句通過jdbc模板對象與數據庫操作
(2)進階
查詢返回結果得封裝
public List<Student> selectAllStudents() { String sql = "select id,name,age from student"; return this.getJdbcTemplate().query(sql, new StudentRowMapper()); }
public class StudentRowMapper implements RowMapper<Student> { // rs:當查詢出總的結果集后,框架會自動遍歷這個結果集,每一次遍歷的一行數據,都會被存放到 // 這個方法的rs參數中。也就是說,這里的rs代表的是一行數據,并非所有查詢結果。換個角度 // 來說,只要能執行到這個方法,就說明這里的rs不會是空的 @Override public Student mapRow(ResultSet rs, int rowNum) throws SQLException { Student student = new Student(); student.setId(rs.getInt("id")); student.setName(rs.getString("name")); student.setAge(rs.getInt("age")); return student; }
事務:數據庫概念即關于數據庫的一系列操作
Spring事務默認回滾方式:發生運行異常時回滾,發生受查異常提交
事務管理主要是防止數據庫未按要求更改而出錯
>>>將事務管理作為切面,在目標方法執行后執行,如果整個目標方法執行沒出錯,則事務提交,否則事務回滾
事務管理的三種方法:
(1)事務代理工廠
<!-- ================================= AOP ==================================== --> <!-- 注冊事務管理器 --> <bean id="myTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="myDataSource"/> </bean> <!-- 生成事務代理對象 --> <bean id="serviceProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"> <property name="transactionManager" ref="myTransactionManager"/> <property name="target" ref="buyStockService"/> //切面 <property name="transactionAttributes"> <props> <prop key="open*">ISOLATION_DEFAULT,PROPAGATION_REQUIRED</prop> //以open開始的方法 <!-- -異常:表示發生指定異常后回滾,這時的異常通常是受查異常 +異常:表示發生指定異常后提交,這時的異常通常是運行時異常 --> <prop key="buyStock">ISOLATION_DEFAULT,PROPAGATION_REQUIRED, -BuyStockException</prop> </props> </property> </bean>
(2)事務注解
(3)使用Aspect的AOP配置
<!-- ================================= AOP ==================================== --> <!-- 注冊事務管理器 --> <bean id="myTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="myDataSource"/> </bean> <!-- 注冊事務通知 --> <tx:advice id="txAdvice" transaction-manager="myTransactionManager"> <tx:attributes> <!-- 這里指定的是:為每一個連接點指定所要應用的事務屬性 --> <tx:method name="open*" isolation="DEFAULT" propagation="REQUIRED"/> <tx:method name="buyStock" isolation="DEFAULT" propagation="REQUIRED" rollback-for="BuyStockException"/> </tx:attributes> </tx:advice> <!-- AOP配置 --> <aop:config> <!-- 這里指定的是切入點 --> <aop:pointcut expression="execution(* *..service.*.*(..))" id="myPointcut"/> <aop:advisor advice-ref="txAdvice" pointcut-ref="myPointcut"/> </aop:config> </beans>
(1)mapper動態代理
MyBatis:
主配置文件中的不用配置據庫連接池(Spring配置文件中)
<configuration> <typeAliases> <package name="com.bjpowernode.beans"/> <!--別名,簡單類名代替全路徑名--> </typeAliases> <mappers> <package name="com.bjpowernode.dao"/> <!--注冊映射文件--> </mappers> </configuration>
dao不是在程序中通過sqlsessionFactory生成,而是在Spring配置文件中注入
<context:property-placeholder location="classpath:jdbc.properties"/> <bean id="mySqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="configLocation" value="classpath:mybatis.xml"/> <property name="dataSource" ref="myDataSource"/> </bean> <!-- 生成Dao的代理對象 --> <bean id="studentDao" class="org.mybatis.spring.mapper.MapperFactoryBean"> <property name="sqlSessionFactory" ref="mySqlSessionFactory"/> <property name="mapperInterface" value="com.bjpowernode.dao.IStudentDao"/> </bean> <!-- 注冊Service --> <bean id="studentService" class="com.bjpowernode.service.StudentServiceImpl"> <property name="dao" ref="studentDao"/> </bean>
(2)支持掃描的mapper動態代理,為dao包底下的所有類生成代理對象
<!-- 生成Dao的代理對象 當前配置會為指定的基本包中所有的接口生成代理對象 --> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="sqlSessionFactoryBeanName" value="mySqlSessionFactory"/> <property name="basePackage" value="com.bjpowernode.dao"/> </bean>
感謝各位的閱讀!關于“SSM框架之Spring怎么用”這篇文章就分享到這里了,希望以上內容可以對大家有一定的幫助,讓大家可以學到更多知識,如果覺得文章不錯,可以把它分享出去讓更多的人看到吧!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。