spring IOC與AOP

Spring IOC容器

spring IOC 容器有兩種,分別是 BeanFactory 容器和 ApplicationContext 容器。java

BeanFactory以下:spring

/*第一步,利用ClassPathResource()API加載路徑CLASSPATH下的可用的Bean的xml配置文件
  而後利用框架提供的 XmlBeanFactory() API生成工廠Bean,XmlBeanFactory()負責建立和初始化全部對象
  而後用getBean方法獲得所須要Bean並轉化類型爲真正的對象
*/
XmlBeanFactory factory = new XmlBeanFactory(new ClassPathResource("Beans.xml"));   
HelloWorld obj = (HelloWorld) factory.getBean("helloWorld");
obj.getMessage();
<?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-3.0.xsd">

   <bean id="helloWorld" class="com.tutorialspoint.HelloWorld">
       <property name="message" value="Hello World!"/>
   </bean>

</beans>

 

ApplicationContext接口的實現:數據庫

FileSystemXmlApplicationContext:從xml文件中加載已經被定義的bean,須要提供的參數爲完整的XML文件路徑express

ClassPathXmlApplicationCOntext:從xml文件中加載已經被定義的bean,但從CLASSPATH加載xml文件框架

package com.tutorialspoint;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;
public class MainApp {
   public static void main(String[] args) {
      //第一步
      ApplicationContext context = new FileSystemXmlApplicationContext("C:/Users/ZARA/workspace/HelloSpring/src/Beans.xml");
      //第二步
    HelloWorld obj = (HelloWorld) context.getBean("helloWorld");
      obj.getMessage();
   }
}

Spring Bean 的做用域

singleton:是bean的默認做用域;看成用域爲singleton時,IOC容器只會存在一個共享的bean實例,屢次getBean時,返回的都是同一個Bean函數

<bean id="..." class="..." scope="singleton">
    <!-- collaborators and configuration for this bean go here -->
</bean>

prototype:表示一個bean的定義對應多個對象實例,每次getbean時都會返回一個新的bean實例;ui

spring的依賴注入

基於構造函數的注入

<!-- id是bean的id,用於識別bean; class是bean所對應的類-->
<bean id="textEditor" class="com.tutorialspoint.TextEditor">    
      <!--constructor-arg表示基於構造函數注入 ,ref表示注入的值是引用而非通常的數值-->
      <constructor-arg ref="spellChecker"/>   
</bean>
   <bean id="foo" class="x.y.Foo">
      <!-- 當構造函數存在多個參數時,按順序定義便可按順序傳參-->
      <constructor-arg ref="bar"/>
      <constructor-arg ref="baz"/>
   </bean>

基於設值函數的依賴注入

   <bean id="textEditor" class="com.tutorialspoint.TextEditor">
      <property name="spellChecker" ref="spellChecker"/>    <!-- property表示基於設值函數注入,設值函數的名字必定要是 setSpellChecker()-->
      <property name="name" value="John Doe"/>           <!-- name是屬性的名字,value是屬性的值-->
  </bean>

基於註解的配置

註解

@required:用在set方法上,一旦用了這個註解,bean在初始化時就必須對這個值進行依賴注入;不然報錯this

public class Zoo {
    private Dog dog ;
    public Dog getDog() {
        return dog;
    }
    @required     //若是xml文件中沒有對Dog屬性進行注入,則會報錯
    public void setDog(Dog dog) {
        this.dog = dog;
    }
}  

@Autowired:能夠不寫依賴注入的配置,讓容器本身尋找依賴並注入spa

public class Zoo {
    @Autowired        private Dog dog ;
    public Dog getDog() {
        return dog;
    }
    public void setDog(Dog dog) {
        this.dog = dog;
    }
}   

 基於註解的注入

在xml配置中添加下列語句,告訴spring要用註解的方式進行配置prototype

<context:annotation-config/>
import org.springframework.beans.factory.annotation.Autowired;

public class Product {     
private int id; //在屬性前加上Autowired註解,實現注入; //這時Category屬性就能夠不要set函數了,在xml中的Product的bean也不能再配置Category屬性了;但product的bean仍是須要的; //若是在xml中的product的bean中也配置了Category屬性,則會按照xml優先的原則尋找屬性對應的set函數或者構造函數,若是找不到則報錯 @Autowired private Category category; public int getId() { return id; } public void setId(int id) { this.id = id; } //也能夠在設值函數前加上Autowired註解,實現注入; //這種狀況下同上,能夠不用在xml文件中配置category屬性,但product的bean仍是須要聲明的 @Autowired   public void setCategory(Category category) {     this.category = category;   } }

此時的xml:僅僅去掉了對屬性是引用的Category屬性的配置,其它的並無省略;(省略的是下方註釋的那一行)

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="
   http://www.springframework.org/schema/beans
   http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
   http://www.springframework.org/schema/aop
   http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
   http://www.springframework.org/schema/tx
   http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
   http://www.springframework.org/schema/context     
   http://www.springframework.org/schema/context/spring-context-3.0.xsd">
  
    <context:annotation-config/>
    <bean name="c" class="com.how2java.pojo.Category">
        <property name="name" value="category 1" />
    </bean>
    <bean name="p" class="com.how2java.pojo.Product">
        <property name="name" value="product1" />
<!--         <property name="category" ref="c" /> -->
    </bean>
  
</beans>

進一步省略基於註解的注入

先將xml中的什麼都去掉,只新增一行<context:component-scan base-package="com.how2java.pojo"/>,這時告訴spring,bean在哪一個java包下

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="
   http://www.springframework.org/schema/beans
   http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
   http://www.springframework.org/schema/aop
   http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
   http://www.springframework.org/schema/tx
   http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
   http://www.springframework.org/schema/context     
   http://www.springframework.org/schema/context/spring-context-3.0.xsd">
  
    <context:component-scan base-package="com.how2java.pojo"/>
     
</beans>

而後在java文件中作以下改動

package com.how2java.pojo;
import javax.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
 
//@component代表Product類是bean,這至關於在xml中聲明一個bean
@Component("p")
public class Product {
    //屬性的初始化如今放在屬性聲明中進行
    private int id = 10;
    private String name="product 1";
    //同上,對Category屬性進行自動注入
    @Autowired
    private Category category;
 
}

 

Spring AOP

aop概念

鏈接點(joinpoint):一個類或者一段程序擁有的具備邊界性質的特定點,叫作鏈接點。

切點(pointcut):是某些特定的鏈接點;若是用數據庫的概念來比喻鏈接點和切點的關係,鏈接點至關於客觀存在的記錄數據,而切點至關於查詢條件;

加強(advice):加強是織入到鏈接點上的一段程序代碼(就是一個方法);

目標對象:要被織入代碼的類

切面:切面 = 加強 + 切點

基於xml的aop

服務類:

import org.aspectj.lang.ProceedingJoinPoint;
//加強所在的類 
public class LoggerAspect {
    //加強,即要織入的方法
    public void log(JoinPoint joinPoint) throws Throwable {
        System.out.println("start log");
        return object;
    }
}  

xml配置:

<!-- 聲明業務類對象-->
<bean name="s" class="com.how2java.service.ProductService">
</bean> 
<!-- 聲明服務類對象-->
<bean id="loggerAspect" class="com.how2java.aspect.LoggerAspect"/>

<aop:config>
        <!-- id是切入點的名字,定義了一個切點 -->
        <!-- expression 表示知足這個expression 的方法在被調用以後,就會執行切面操做,至關於觸發了切面;-->
        <!--第一個*表示返回值返回任意類型,第二個*表示任意方法,(..)表示方法的參數是任意數量和類型 --> 
        <aop:pointcut id="loggerCutpoint"  expression="execution(* com.how2java.service.ProductService.*(..)) "/>
        <!-- 定義了一個切面,切面 = 加強 + 切點--> 
        <!-- id是切面的名字, ref是加強所在的類-->  
        <aop:aspect id="logAspect" ref="loggerAspect">
            <!-- pointcut-ref 表示本切面和哪一個切點相關聯; method表明加強-->
            <!-- aop:after 表示要在什麼時候調用加強;before在方法調用前,after在方法調用後,after-returning在方法執行成功後-->
            <!-- after-throwing在方法拋出異常後調用;around在方法調用前和調用後執行-->
            <aop:after pointcut-ref="loggerCutpoint" method="log"/>
        </aop:aspect>
</aop:config>

基於註解方式的aop

 業務類以下:

package com.how2java.service;
import org.springframework.stereotype.Component;
//用component來聲明這是一個bean
@Component("s")
public class ProductService {
    public void doSomeService(){
        System.out.println("doSomeService");
    }     
}

服務類以下:

package com.how2java.aspect;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
//Aspect註解表示這是一個切面,component註解聲明瞭一個bean
@Aspect
@Component
public class LoggerAspect {
    //around註解表示對目標類中的某些方法進行切面操做 
    @Around(value="execution(*com.how2java.service.ProductService.*(..))")
    public Object log(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("start log:" + joinPoint.getSignature().getName());
        Object object = joinPoint.proceed();
        System.out.println("end log:" + joinPoint.getSignature().getName());
        return object;
    }
}

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"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="
   http://www.springframework.org/schema/beans
   http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
   http://www.springframework.org/schema/aop
   http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
   http://www.springframework.org/schema/tx
   http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
   http://www.springframework.org/schema/context     
   http://www.springframework.org/schema/context/spring-context-3.0.xsd">
    <!-- 下面兩行是告訴spring應該掃描哪些包-->
    <context:component-scan base-package="com.how2java.aspect"/>
    <context:component-scan base-package="com.how2java.service"/>
  
    <aop:aspectj-autoproxy/> 
   
</beans>
相關文章
相關標籤/搜索