PS C:\Users\sw> ls env:classpath Name Value ---- ----- CLASSPATH .;C:\Dev\Java\jdk1.8.0_171/lib/dt.jar;C:\Dev\Java\jdk1.8.0_171/lib/tools.jar
dt.jar 根據 Sun公司定義,把swing用來供給IDE描述 BeanInfo => 由此引入 Spring 一個極爲關鍵的東西 java.beans.PropertyEditorjava
================================= Ioc 容器 和 依賴注入 =========================mysql
Dependency Injection 是後來 matiin flower 給 IoC 起的一個名字。DI是一種具體實現方式。spring
Ioc容器的做用舉例說明,假設有一個 Sevice 層的類要調用 DAO 層的類 == 該 Service 層的類 依賴了 DAO 層的類,sql
此時IoC容器經過【xml配置】或者【註解】方式 配置這種依賴關係。express
依賴注入的方式有兩種 構造注入 和 setter注入。編程
============================= Bean 裝配 ===================================================緩存
做用域 Scope :Singleton Prototype(每次都建立新的實例) Request Session 基於portlet的Session安全
生命週期 LifeCycle:實現 InitializeBean DisposableBean ,比 xml 早一點。(afterPropertyiesSet start destroy stop )併發
Aware後綴的接口獲取相應的資源:【ApplicationContext】Aware 【BeanNameContext】Aware分佈式
自動裝配 AutoWiring :配置項 defautl-autowried="byType | byName | constructor"
ResourceLoader:【默認:跟隨 context 路徑資源】【classpath:資源】【file:資源】【url:資源】
public class GetResource implements ApplicationContextAware{ private ApplicationContext actx; public void setApplicationContext(ApplicationContext actx){ this.actx = actx; } public static void main(Stirng[] args){ actx.getResource("classpath:readme.txt"); //... } }
======================== 使用註解方式裝配 bean ======================================
<context:annotation-config / > 查找同一個 ApplicationContext 中的 bean 註解。
<context:component-scan /> 包含 <context:annotation-config / > ,能夠掃 @Component @Repository @Service @Controller
xml配置能夠改變自動掃描行爲
<context:component-scan base-package="org.example"> <!-- 掃 Stub --> <context:include-filter type="regex" expression=".*Stub.*Repository" /> <!-- 忽略@Repository --> <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Repostory" /> </context:component-scan>
註解方式定義Bean (Id、Scope、
BeanNameGenerator | ScopeMetadataResolver | ...
@Scope("prototype")
@Service("myService") public class MyServiceImpl implements MyService{ }
【@Autowired註解】自己是BeanPostProcessor處理,因此不能在自定義的BeanPostProcessor或自定義的BeanFactoryPostProcessor使用。
由於 @Autowired(required=true) 用在構造器上只容許一個。能夠經過 @Required 達到一樣的效果。
能夠經過 @Autowried 獲取 ApplicationContext 資源(Environment、ResourceLoader),而不須要實現 ApplicationContextAware。
獲取多個 Bean
能夠經過@Autowired 獲取全部相同類型的實例 裝配到 List 或別的集合,@Order(value="1")能夠爲集合元素指定順序。
能夠經過@Qualifier 限定縮小範圍,獲取多個Bean中指定的 Bean。
=================== @Configuration Java Config ====================
@Bean 指定建立對象名字、initMethod、destroyMethod
@ImportResource @Value == <context:property-placeholder location=...>
=========================== AOP 預編譯 運行期動態代理 ===========================
程序功能統一維護:日誌記錄、性能統計、安全控制、事務處理、異常處理
預編譯 :AspectJ 完整的AOP
運行期動態代理 (JDK動態代理,CGLib動態代理): Spring AOP、JBoss AOP
pointcut + advice
<aop:config> <aop:aspect id="aspectName" ref="beanName"> <aop:pointcut id="pointcutName" expression="" /> <aop:before method="before" pointcut-ref="pointCutName" /> <aop:after-returning method="afterReturning" pointcut-ref="pointCutName"/> <aop:after-throwing method="afterThrowing" pointcut-ref="pointCutName" /> <aop:after method="afterFinally" pointcut-ref="pointCutName" /> </aop:aspect> </aop:config>
=============================== 面向 AOP 編程 ===================
Soc Seperate on Concern 關注點分離,好比業務和非業務分離開。
權限控制 緩存控制 事務控制 審計日誌 性能監控 分佈式追蹤 異常處理。
硬編碼 == 代碼侵入性。怎麼辦?用@Aspect = @Pointcut + Advice(@Before @Atfer(finally) @AfterReturn @AfterThrowing @Around(全部))
切點表達式
① execution【 方法】、@target @args @ within @annoation 【註解】 、within 【包或類型】、this() bean() target() 【對象】、args() 【參數】
② * 任意數量字符 、+ 指定的類及子類、 .. 指定子包或參數
within【包或類型】經常使用於 限定一下類型 限定一下包
//匹配類型下全部方法 @Pointcut("within(com.example.Sample)")
//匹配包下全部類的方法 @Pointcut("within(com.example.*)")
this() bean() target() 【對象】
@Pointcut("this("com.example.Demo")")//實現IDAO接口對象方法 @Pointcut("target(com.example.IDAO)")@Pointcut("bean(*Service)")
args() 【參數】
@Pointcut("execution(* *..find*(Long))")@Pointcut("args(Long)")
@target @args @ within @annoation 【註解】
@Pointcut("@annoation("com.example.AdminOnly")") //RetentionPolicy要爲CLASS @Pointcut("@within("com.example.AdminOnly")") //RetentionPolicy要爲RUNTIME @Pointcut("@target("com.example.AdminOnly")") //傳參的地方 有@AdminOnly註解 @Pointcut("@args("com.example.AdminOnly")")
execution【 方法】{ * 任意數量字符 、+ 指定的類及子類、 .. 指定子包或參數}
execution{
modifier-pattern ?可省
returnType-pattern
declaringType-pattern?可省
name(param)
throws ?可省
}
@Pointcut("execution(public * com.example.*Service.*(..))") //加兩個.. 匹配到子包 @Pointcut("execution(public * com.example..*Service.*(..))")
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 通知 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// @Around = @Before + @After* // 須要把 接入點再傳出去 @Around("切點方法名") public Object do(ProceedingJoinPoint joinPoint){ // before Object result = null try{ result = joinPoint.proceeding(joinPoint.getArgs()); // afterReturning }catch (Throwable t) { // afterThrow } finally{ //after(finally) } }
獲取參數
@Before("切點方法名&&args(參數名)")
@After*("切點方法名&&args(參數名)")
================================================= AOP 原理就是 =====================================
【靜態接口代理模式】。Proxy 負責在具體方法鏈接點(before、after*),Target仍然負責具體方法邏輯。
【jdk動態接口代理】底層原理使用反射生成 接口實現方法,優勢 直接代理掉 一個類的全部方法(現有、將來新增的)
public class JdkProxy implements InvocationHandler{ private Subject subject; public JdkProxy(Subject subject) { this.subject = subject; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("before print"); Object result = null; try { result = method.invoke(subject, args); System.out.println("afterReturn print"); } catch (Exception e) { System.out.println("afterThrow print"); throw e; }finally { System.out.println("after print"); } return result; } } public class Client { public static void main(String[] args) { Subject subject = (Subject) java.lang.reflect.Proxy.newProxyInstance(Client.class.getClassLoader(), new Class[] {Subject.class}, new JdkProxy(new SubjectImpl())); subject.request(); } }
【cgLib 繼承代理】
static class CGLibMIntercepter implements MethodIntercepter{
@Override
public Object intercept(Object obj,Method method,Object[] args,MethodProxy proxy)throw Throwable{
//關鍵方法
Object result = proxy.invokeSuper(obj,args);
}
}
public static void main(String[] args){
Subject subject = getProxy(Subject.class,new CGLibMIntercepter());
subject.request();
}
public static Object getProxy(Class clz,MethodIntercepter intercepter){ Enhancer enhancer = new Enhancer(); enhancer.setSuperClass(clz); enhancer.setCallback(intercepter); return enhancer.create(); }
JDK與Cglib代理對比:
1:JDK只能針對有接口的類的接口方法進行動態代理;
2:Cglib基於繼承來實現代理,沒法對static、final類進行代理;
3:Cglib基於繼承來實現代理,沒法對private、static方法進行代理。
Spring 對於兩種實現方式都支持配置!DefaultAopProxyFactory 好比接口用JDK動態代理,是繼承用CgLib代理。(PS:Spring源碼好複雜。。。仍是掌握簡單的理解概念就好。)
【配置】@EnableAspectJAutoProxy(proxyTargetClass = true) 強制使用 CgLib 代理。
AOP 怎麼鏈式調用起來?使用了責任鏈模式。
============================= 事務管理 ====================================
AtomicityConsistencyIsolationDuralbility == ACID == 原子性(最小不可分割操做單位)、一致性(先後狀態)、隔離性(併發事務之間)、持久性(寫入記錄)
經典例子 轉帳。【事務回滾】
【PlatformTransactionManager 事務管理器】Platform 指的是 iBatis Hibernate JPA 具體實現。
【TransactionDefinition 事務定義信息(隔離 傳播 超時 只讀)】
【DEFAULT】mysql _ REPEATABLE_READ
【READ_UNCOMMITED】不隔離問題 髒讀、不可重複讀、幻讀
【READ_COMMITED】【髒讀】一個事務讀取另外一個事務改寫還沒提交的數據,沒提交若是回滾,讀到的數據是無效的。
【REPEATABLE_READ】【不可重複讀】一個事務下,屢次讀取數據,獲得不一樣結果,
【SERIALIZABLE】【幻讀】一個事務在執行讀取的時候,被插入另外一個事務記錄。
傳播
【目的 支持當前事務】
【傳播當前事務,沒有要傳播的事務】支持傳並建立、支持傳但不建立、不傳就拋異常 PROPAGATION_ ( REQUIRED、SUPPORTS、MANDATORY )
【讓事務分開】
【傳播當前事務,有要傳播的事務】另外建立、掛起當前但不支持傳、拒絕且拋異常】PROPAGATION_ ( REQUIRED_NEW、NOT_SUPPORTED、NEVER )
【讓事務嵌套執行 利用保存點回滾】
PROPAGATION_NESTED
【TransactionStatus 】
是否有保存點 等狀態
--------------------------------------------------------------------------- PlatformTransactionManager、CombopooledDataSource 事務的使用 ===========================
編程式使用事務 TransactionTemplate
聲明式使用事務 AOP
1種 TransactionProxyBean
<bean id="accountServiceProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"> <!-- 配置目標對象 --> <property name="target" ref="accountService"/> <!-- 注入事務管理器 --> <property name="transactionManager" ref="transactionManager"/> <!-- 注入事務屬性 --> <property name="transactionAttributes"> <props> <!-- PROPAGATION_REQUIRED:支持當前事務,若是不存在就新建一個事務 --> <!-- prop的格式: * PROPAGATION 事務的傳播行爲 * ISOLATION 事務的隔離級別 * readOnly 只讀(不可進行修改) * -Exception 發生哪些異常回滾事務 * +Exception 發生哪些異常事務不回滾 --> <prop key="具體方法或通配符">PROPAGATION_REQUIRED</prop> </props> </property>
</bean>
2種 AspectJ 只要調用到 AccountService的全部方法,都會啓動通知。
<!-- 配置事務的通知 --> <tx:advice id="txAdvice" transaction-manager="transactionManager"> <tx:attributes> <tx:method name="transfer" propagation="REQUIRED"/> </tx:attributes> </tx:advice> <!-- 配置切面 --> <aop:config> <!-- 配置切入點 --> <aop:pointcut expression="execution(* com.demo3.AccountService.*(..))" id="pointcut1"/> <!-- 配置切面 --> <aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut1"/> </aop:config>
3種 @Transactional
<!-- 開啓註解事務 --> <tx:annotation-driven transaction-manager="transactionManager"/> 在對應須要事務管理的業務層上加上註解 @Transactional