Spring使用之IOC

      這一段純屬廢話,能夠不用看........,兌現諾言,每週寫一篇博客。最近除了學習算法,還有想更全面瞭解Spring框架的使用。因而開始了個人學習之旅。因爲本人工做中接觸的是一個很是很是老的項目,因此對Spring的瞭解僅僅停留在一些基本的使用上。爲加深瞭解Spring提供的功能,因而就果斷買了《Spring實戰》,初略看下來,收穫仍是有的,但總感受也不是特別特別優秀的書。接下來,我就來談談我對Spring的一點淺薄理解。web

1、Spring第一印象

      對於Java後端開發來講,Spring基本是再熟悉不過的框架了,甚至能夠說,如今不用Spring框架進行開發的JAVA後端項目應該基本是百裏挑一(我的猜想)。相信一提到Spring,你們想到的就是DI(Dependency Injection)/IOC(Inversion of Control)、AOP這些名詞了,沒錯,這就是Spring提供的核心功能。DI、IOC說的就是同一個功能,翻譯過來分別是依賴注入、控制反轉,其實就是咱們把對象的建立、銷燬、維護交給Spring,讓它幫咱們管理這些對象,但咱們須要的時候,讓它直接給咱們一個,不須要咱們本身去new。AOP就是面向切面編程。額額,看着這些名詞一臉懵逼.................................算法

接下來就來個小例子看看這到底能幹嗎,能給咱們編程提供什麼樣的幫助。。spring

在給小例子以前咱們得先了解兩個概念:apache

一、既然要讓Spring幫咱們建立管理對象、那咱們就得先告訴Spring怎麼去建立這些對象,還有對象之間是什麼關係。Spring提供了3個方案來實現:一、XML中顯式配置。二、Java中顯式配置。三、自動包掃描編程

二、Spring提供了倆種容器類型,分別爲BeanFactory、ApplicationContext。BeanFactory只提供了基本的DI支持,ApplicationContext基於BeanFactory構建,能提供更多服務。後端

Spring上下文,就是一種容器,繼承自ApplicationContext,提供更多功能,如常見的,bash

AnnotationConfigApplicationContext可從JAVA配置類中加載上下文app

ClassPathXmlApplicationContext 從類路徑下的XML文件中加載上下文。框架

FileSystemXmlApplilcationContext 從文件系統路徑中加載上下文maven

例子

接下來咱們用Idea編輯器,經過maven工具建立一個maven項目來體驗下Spring。建立完以後咱們首先要引入Spring jar包,經過maven,咱們不須要本身去下載,只須要在配置文件中配置咱們須要用到的jar包。項目結構以下圖


以後咱們在pom.xml文件中配置須要用到的jar文件,咱們將spring的幾個核心包配置進來。

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>cn.springstudy</groupId>
  <artifactId>luckyspring</artifactId>
  <version>1.0-SNAPSHOT</version>

  <name>luckyspring</name>
  <url>http://www.example.com</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.7</maven.compiler.source>
    <maven.compiler.target>1.7</maven.compiler.target>
    <!-- spring 版本  -->
    <org.springframework.version>4.0.0.RELEASE</org.springframework.version>
  </properties>
  <dependencies>
    <!-- 當前項目用到的3個核心spring jar包 -->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>${org.springframework.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-core</artifactId>
      <version>${org.springframework.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-beans</artifactId>
      <version>${org.springframework.version}</version>
    </dependency

    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>
  </dependencies>

</project>
複製代碼

如今假設咱們有一個公司,一個公司裏面得有僱員來工做,才能讓公司提供服務,因而咱們建立僱員類

package cn.springstudy.vo;

public class Employee {

    public void work(){
        System.out.println("Employ start to Work");
    };
}複製代碼

再建立公司類

package cn.springstudy.vo;

public class Company {

    //公司類有個僱員對象
    private Employee employee;

    public void  supportService(){
        employee.work();
    }

    public Employee getEmployee() {
        return employee;
    }

    public void setEmployee(Employee employee) {
        this.employee = employee;
    }
}複製代碼

前面咱們說過告訴Spring怎麼去建立對象有三種方式

方式一XML配置來告訴spring怎麼去建立咱們的僱員還有公司類,在建立一個applicationContext.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">
    <!-- 配置一個對象 指定該對象id爲emplayee-->  
    <bean id="employee" class="cn.springstudy.vo.Employee"></bean>
    <!--配置對象,以後往對象中放入一個Employee對象
       ref="employee"表示注入的對象爲spring容器中id爲employee的對象,這樣配置後建立Company
       對象後,會自動調用setEmployee()方法放入一個Employee對象
    -->    
    <bean id="company" class="cn.springstudy.vo.Company">
        <property name="employee" ref="employee"></property>
    </bean>
</beans>複製代碼

接下來咱們建立一個main函數做爲程序的入口,在main函數中去建立Spring容器

package cn.springstudy.spring;

import cn.springstudy.vo.Company;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class SpringStudy {
    public static void main(String arg[]){
        //方式一,XML文件中加載上下文,即Spring容器
        ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        //從容器中獲取一個Company對象
        Company company = (Company) classPathXmlApplicationContext.getBean("company");
        company.supportService();
    }
}複製代碼

執行一下,控制檯打印以下


咱們能夠看到咱們執行company.supportService()竟然沒報空指針,要知道咱們可沒在Company類中去建立Empoyee對象,說明什麼???Spring容器自動幫咱們建立Employee對象並set到Company對象中了。

方式二

建立一個配置Java類

package cn.springstudy.spring;

import cn.springstudy.vo.Company;
import cn.springstudy.vo.Employee;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

//註解,代表這個是一個Spring配置類
@Configuration
public class SpringConfig {

 //Spring容器管理的類,經過Bean註解,方法名即默認爲bean的id,也可在Bean註解後加參數指定Bean的ID
    @Bean
    public Employee employee(){
        return  new Employee();
    }
    //Spring容器管理的類,經過Bean註解
    @Bean
    public Company company(){
        Company company =  new Company();
        company.setEmployee(employee());
        return  company;
    }
}
複製代碼

main函數,程序入口,執行結果同上

package cn.springstudy.spring;

import cn.springstudy.vo.Company;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class SpringStudy {

    public static void main(String arg[]){

        //方式二,默認bean的名稱即爲配置方法的名稱,須要用到AnnotationConfigApplicationContext容器
        AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext();
        annotationConfigApplicationContext.register(SpringConfig.class);
        annotationConfigApplicationContext.refresh();
        Company company1 = (Company) annotationConfigApplicationContext.getBean("company");
        company1.supportService();
    }
}複製代碼

方式3、

方式三序藉助方式一或者方式二,咱們首先須要在須要被Spring容器管理的類上面加上@Component註解,因此咱們在Empoyee加上註解

package cn.springstudy.vo;

import org.springframework.stereotype.Component;

@Component
public class Employee {

    public void work(){
        System.out.println("Employ start to Work");
    };
}複製代碼

Company類上加上註解,需自動分配的對象上加@Autowired註解

package cn.springstudy.vo;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class Company {

    //Autowired,幫我分配個Employee對象過來。
    @Autowired
    private Employee employee;

    public void  supportService(){
        employee.work();
    }

    public Employee getEmployee() {
        return employee;
    }

    public void setEmployee(Employee employee) {
        this.employee = employee;
    }
}複製代碼

在配置類上加上包自動掃描路徑

package cn.springstudy.spring;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

//cn.springstudy.vo 爲掃描的基礎包路徑
@Configuration
@ComponentScan("cn.springstudy.vo")
public class SpringConfigScan {
}複製代碼

測試main方法

package cn.springstudy.spring;

import cn.springstudy.vo.Company;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class SpringStudy {

    public static void main(String arg[]){    
        //方式三,需藉助方式2
        AnnotationConfigApplicationContext annotationConfigApplicationContext2 = new AnnotationConfigApplicationContext();
        annotationConfigApplicationContext2.register(SpringConfig.class);
        annotationConfigApplicationContext2.refresh();
        Company company2 = (Company) annotationConfigApplicationContext.getBean("company");
        company2.supportService();
    }
}複製代碼

執行結果同上。

XML、Java配置文件混着使用

固然XML配置方式和Java配置文件還能混着用。

一、在XML配置中混用Java配置文件只需在配置文件中增長一個<bean></bea>便可將Java配置類導入XML配置中。二、XML中導入其餘XML配置,只需用<import>指定其餘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">
    <!--導入其餘XML配置文件  -->
    <import resource="applicationContext2.xml"></import>
    <!--Spring Java配置類-->
    <bean class="cn.springstudy.spring.SpringConfig"></bean>
    
    <bean id="employee" class="cn.springstudy.vo.Employee"></bean>
    <bean id="company" class="cn.springstudy.vo.Company">
        <property name="employee" ref="employee"></property>
    </bean>
    
</beans>複製代碼

一、Java配置文件混着XML配置文件,只需在Java類中加個註解便可,二、Java配置類導入其餘配置類,只需加@Import註解,指定配置類位置。

package cn.springstudy.spring;

import cn.springstudy.vo.Company;
import cn.springstudy.vo.Employee;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportResource;

@Configuration
//導入其餘XML配置文件
@ImportResource("classpath:applicationContext.xml")
//導入其餘配置類
@Import({SpringConfigScan.class})
public class SpringConfig {    
    @Bean
    public Employee employee(){
        return  new Employee();
    }

    @Bean
    public Company company(){
        Company company =  new Company();
        company.setEmployee(employee());
        return  company;
    }
}複製代碼

Spring DI初步使用方法已經如上,接下來咱們主要經過XML配置的方式來講明其餘功能。

構造方法注入依賴對象

以上的小例子中Company中的Employee對象是經過setEmployee方法配置進去的。咱們還能夠經過構造方法的形式配置進去。

給Company類增長一個構造方法

package cn.springstudy.vo;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

public class Company {

    private Employee employee;
    private String name;

    public Company(Employee employee,String name){
        this.employee = employee;
        this.name = name;
    }
    public void  supportService(){
        employee.work();
    }

    public Employee getEmployee() {
        return employee;
    }

    public void setEmployee(Employee employee) {
        this.employee = employee;
    }
}複製代碼

配置文件配置以下

<?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:c="http://www.springframework.org/schema/c" 
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/c http://www.springframework.org/schema/c/spring-c.xsd">
    <!--在上面beans中聲明spring中c命名空間-->

    <bean id="employee" class="cn.springstudy.vo.Employee"></bean>
   <!-- 構造方法中注入Employee對象,還有一個名稱其中
    c:爲命名空間前綴
    emplayee、name分別爲構造函數中參數的名稱
     -ref表示注入的是spring容器中的對象
    "emplayee"表示引入的是id爲emplayee的對象,name沒有帶-ref則是注入字符串juejin.com
   -->
    <bean id="company" class="cn.springstudy.vo.Company"
        c:employee-ref="employee"
        c:name="juejin.com">
    </bean>

</beans>複製代碼

工廠方法模式建立對象

以上說明Spring的依賴注入的基本使用。咱們在編程時候可能不是經過new來建立對象,有時也會使用靜態方法(靜態工廠模式)來建立對象,那麼Spring是否支持呢?答案是確定的。

public class ClientService {
    private ClientService() {}

    public static ClientService createInstance() {
        return new ClientService()
    }
}複製代碼

<bean id="clientService"
    class="examples.ClientService"
    factory-method="createInstance"/>複製代碼

固然工廠方法模式是經過非經過靜態方法建立對象的,Spring也是支持的,以下

public class DefaultServiceLocator {

    private static ClientService clientService = new ClientServiceImpl();

    public ClientService createClientServiceInstance() {
        return clientService;
    }
}複製代碼

<!-- 工廠類  -->
<bean id="serviceLocator" class="examples.DefaultServiceLocator">
</bean>
<!--  ClientService類配置 -->
<bean id="clientService"
    factory-bean="serviceLocator"
    factory-method="createClientServiceInstance"/>複製代碼

Spring中bean的做用域

默認狀況下,Spring容器中的bean都是單例的,能夠經過配置修改。spring定義了多種做用域:

一、Singleton(默認) 單例

二、Prototype 原型,每次經過容器獲取對象都會建立一個新對象、

三、Session 會話,一個web會話中使用一個對象

四、Request ,每次web請求使用一個對象

經過XML配置可在bean中指定scrop屬性指定

Java配置類可在方法上加註解@Scope("prototype")

自動掃描的類可在類上加註解@Scope("prototype")

<!-- scope 屬性指定做用域 -->
<bean id="employee" class="cn.springstudy.vo.Employee"  scope="prototype"></bean>複製代碼

@Component
@Scope("prototype")
public class Company {.....}複製代碼

@Configuration
public class SpringConfig {
    @Bean
    @Scope("prototype")
    public Employee employee(){
        return  new Employee();
    }
}複製代碼


最後,感受這篇寫得有點亂,也很基礎,還有不少東西沒說到,不知道看到這裏的人兒有無收穫,說好的一週一篇,額,那就先發出來吧,之後可能還作修改,待續。。

相關文章
相關標籤/搜索