Spring 筆記

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
相關文章
相關標籤/搜索