第一章:Spring基礎

1.1 Spring概述

1.1.1 Spring的簡史

第一階段:xml配置
Spring1.x版本中,Spring開發都是通過xml配置獲取Bean,伴隨着項目的不斷擴大,我們通過文件路徑,區分不同的xml文件意義,開發過程中,不斷的切換開發的類和xml,加大了開發的難度。

第二階段:註解配置
Spring2.x版本中,Spring開發隨着JDK1.5版本的註解支持,也相應的提供了聲明Bean的註解,比如@Service,@Controller。至於Spring到底是使用xml配置和註解配置,大抵遵循,應用的基本配置(數據庫的配置)用xml,業務配置用註解。
第三階段:Java配置
Spring3.x至今,Spring提供了Java配置的功能,也是SpringBoot推薦使用的一種聲明Bean的方式。

1.1.2 Spring概述

我們知道Spring框架是一個輕量級的企業開發的一站式解決方案。Spring提供了一系列的模塊組件,主要有,IOC、AOP、數據訪問、Web開發、消息、測試等相關技術。
1. Spring的模塊
Spring模塊化,意味着,根據需要引用相應的Jar包。
這裏寫圖片描述

(1)核心模塊(Core Container)
Spring-Core:核心工具類,Spring其他模塊也大量使用了Spring-Core;
Spring-Beans:定義了對Bean 的支持;
Spring-Context:運行Spring容器;
Spring-Context-Support:Spring容器對第三方包的集成支持;
Spring-Expression:使用表達式語言在運行時查詢和操作對象。
(2)AOP
Spring-AOP:基於代理的AOP支持;
Spring-Aspects:基於AspectsJ的AOP支持。
(3)消息(Message)
Spring-Message:對消息架構和協議的支持。
(4)Web
Spring-Web:web集成功能的支持;
Spring-WebMvc:基於Servlet的SpringMVC;
Spring-WebSocket:提供了webSocket的支持;
Spring-WebMvc-Portlet:提供了對Portlet環境支持。
(5)數據訪問/集成(Data Access /Integration)
Spring-JDBC:提供了基於JDBC訪問數據庫的支持;
Spring-TX:提供了編程式和聲明式事務支持;
Spring-ORM:提供了對對象/關係映射的支持;
Spring-OXM:提供了對對象/xml映射的支持;
Spring-JMS:提供了對JMS的支持。

1.2 Spring基礎配置

Spring框架的四大原則:
1)使用POJO(Plain Old Java Object 無規則普通的Java對象),進行輕量級和最小侵入式開發
2)通過依賴注入和基於接口編程,實現鬆耦合
3)通過AOP和默認習慣進行聲明式編程
4)使用AOP和模版(template)減少模式化代碼

1.2.1 依賴注入

  1. 說明
    我們經常會說控制反轉(Inversion of Control-IOC)和依賴注入(Dependency Injection-DI)在Spring環境下是等同概念。控制反轉就是通過依賴注入實現的,所謂的依賴注入指的是容器負責創建對象和維護對象之間的依賴關係,其主要目的是爲了解耦。
    無論是xml配置,註解配置,還是Java配置,都是稱爲配置元數據。Spring容器解析這些配置元數據進行Bean的初始化,配置和管理依賴。
    聲明Bean的註解方式:

    • @Component組件,沒有明確的角色。
    • @Service,在業務邏輯層(Service層)使用。
    • @Repository,在數據訪問層(Dao層)使用。
    • @Controller,在控制器(Controller層)使用。

注入Bean的註解方式:

  • @Autowired:Spring提供的支持。
  • @Inject:JSR-330提供的支持。
  • @Resource:JSR-250提供的支持。

@Autowired、@Inject、@Resource可註解在set方法上或者屬性上。
2. 實例
1)編寫功能類的Bean

package com.dy.spring_demo.ch1.di;

import org.springframework.stereotype.Service;

/**
 * Author:dy_bom
 * Description: 功能類Bean
 * Date:Created in 下午6:59 2018/4/1
 * Copyright (c)  xdy_0722@sina.com All Rights Reserved.
 */
@Service //1
public class FunctionService {

    public String sayHello(String word){
        return  "Hello"+word+"!";
    }
}
/**
 * 代碼解釋
 * (1)使用@Service註解聲明當前FunctionService類是Spring管理的一個Bean
 * 其中,使用@Component@Service@Repository@Controller是等效,
 * 根據需要選用。
 * */

2)使用功能類的Bean

package com.dy.spring_demo.ch1.di;

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

/**
 * Author:dy_bom
 * Description: 使用功能類Bean
 * Date:Created in 下午7:06 2018/4/1
 * Copyright (c)  [email protected] All Rights Reserved.
 */
@Service //1
public class UseFunctionService {

    @Autowired //2
    FunctionService functionService;

    public String sayHello(String word){
        return  functionService.sayHello(word);
    }
}
/**
 * 代碼解釋
 * 1:使用@Service 註解聲明當前UseFunctionService類是Spring 管理的一個Bean
 * 2:使用@Autowired將FunctionService的實體Bean注入到UseFunctionService中,
 *    此處@Inject 和@Resource等效。
 * */

3)配置類

package com.dy.spring_demo.ch1.di;

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

/**
 * Author:dy_bom
 * Description:
 * Date:Created in 下午7:12 2018/4/1
 * Copyright (c)  xdy_0722@sina.com All Rights Reserved.
 */
@Configuration //1
@ComponentScan("com.dy.spring_demo.ch1.di")  //2
public class DiConfig {

    /**
     * 代碼解釋
     * 1:@Configuration聲明當前類是一個配置類,
     * 2:@ComponentScan,自動掃描定義包下所有使用@Service@Controller
     *    、@Repository@Component的類,並註冊爲Bean
     * */
}

4)運行

package com.dy.spring_demo.ch1.di;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

/**
 * Author:dy_bom
 * Description: 運行
 * Date:Created in 下午7:17 2018/4/1
 * Copyright (c)  [email protected] All Rights Reserved.
 */
public class Main {

    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(DiConfig.class); //1

        UseFunctionService useFunctionService = context.getBean(UseFunctionService.class); //2

        System.out.println(useFunctionService.sayHello("DI(依賴注入)"));

        context.close();
    }
}

結果如下:

Hello DI(依賴注入)!

1.2.2 Java配置

1.說明
Java配置是Spring4.x推薦的配置方式,可以完全替代xml配置,同時也是SpringBoot推薦的使用方式。
Java配置通過@Configuraton 和 @Bean來實現的。

  • @configuration聲明當前類是一個配置類,相當於一個Spring配置的xml文件。

  • @Bean註解在方法上,聲明當前方法返回值一個Bean。

平時的使用原則:全局配置使用Java配置(數據庫相關配置、MVC相關的配置),業務Bean配置使用註解配置(@Controller、@Service、@Repository、@Component)
2. 實例
1) 編寫功能類Bean

package com.dy.spring_domo.ch1.javaconfig;
/**
 * Author:dy_bom
 * Description: 功能類Bean
 * Date:Created in 下午6:59 2018/4/1
 * Copyright (c)  [email protected] All Rights Reserved.
 */
//1
public class FunctionService {

    public String sayHello(String word){
        return  "Hello "+word+"!";
    }
}

/**
 * 代碼解釋
 * (1)此處沒有@Service聲明Bean
 * */

2) 使用功能類Bean

package com.dy.spring_domo.ch1.javaconfig;

/**
 * Author:dy_bom
 * Description: 使用功能類Bean
 * Date:Created in 下午7:06 2018/4/1
 * Copyright (c)  [email protected] All Rights Reserved.
 */
//1
public class UseFunctionService {

    //2
    FunctionService functionService;

    public void setFunctionService(FunctionService functionService) {
        this.functionService = functionService;
    }

    public String sayHello(String word) {
        return functionService.sayHello(word);
    }
}
/**
 * 代碼解釋
 * 1:沒有@Service聲明Bean
 * 2:沒有@Autowired注入Bean
 */

3)配置類

package com.dy.spring_domo.ch1.javaconfig;

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

/**
 * Author:dy_bom
 * Description: Java配置類
 * Date:Created in 下午7:12 2018/4/1
 * Copyright (c)  [email protected] All Rights Reserved.
 */
@Configuration //1
public class JavaConfig {

    @Bean //2
    public FunctionService functionService() {
        return new FunctionService();
    }


    @Bean //3
    public UseFunctionService useFunctionService(FunctionService functionService) {
        UseFunctionService useFunctionService = new UseFunctionService();
        useFunctionService.setFunctionService(functionService);
        return useFunctionService;
    }
}
  * 代碼解釋
     * 1:使用@configuration聲明當前類是一個配置類,此處沒有包掃描,是因爲所有的Bean在這裏定義了
     * 2:使用@Bean聲明瞭當前方法返回值是一個Bean
     */

4)運行

package com.dy.spring_domo.ch1.javaconfig;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

/**
 * Author:dy_bom
 * Description: 運行
 * Date:Created in 下午7:17 2018/4/1
 * Copyright (c)  [email protected] All Rights Reserved.
 */
public class Main {

    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(JavaConfig.class); //1

        UseFunctionService useFunctionService = context.getBean(UseFunctionService.class); //2

        System.out.println(useFunctionService.sayHello("Java Config"));

        context.close();
    }
}

結果如下:

Hello Java Config!

1.2.3 AOP

1.說明
AOP:面向切面編程,可以讓一組類共享相同的行爲,目的是爲了解耦,一定程度上彌補了OOP的不足。
Spring支持AspectJ的註解式切面編程:
1) 使用@Aspect聲明一個切面
2)使用@After、@Before、@Around定義建言(Advice),可以直接攔截規則(切點)作爲參數。
攔截方式有兩種,分別爲基於註解攔截和基於方法規則攔截。演示一種模擬記錄操作的日誌系統的實現。其中註解式攔截更好的控制攔截的粒度。
2.實例
1)添加Spring AOP支持和AspectJ的依賴

    <properties>
        <aspectjrt.version>1.8.10</aspectjrt.version>
        <aspectjweaver.version>1.8.10</aspectjweaver.version>
    </properties>

     <!--aspectJ支持-->
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjrt</artifactId>
            <version>${aspectjrt.version}</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>${aspectjweaver.version}</version>
        </dependency>

2)編寫攔截規則的註解

package com.dy.spring_demo.ch1.aop;

import java.lang.annotation.*;

/**
 * Author:dy_bom
 * Description:
 * Date:Created in 下午8:32 2018/4/1
 * Copyright (c)  [email protected] All Rights Reserved.
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Action {
    String name();
}

3)編寫使用註解的被攔截類

package com.dy.spring_demo.ch1.aop;

import org.springframework.stereotype.Service;

/**
 * Author:dy_bom
 * Description: 使用註解被攔截的類
 * Date:Created in 下午8:37 2018/4/1
 * Copyright (c)  [email protected] All Rights Reserved.
 */
@Service
public class DemoAnnotationService {

    @Action(name = "註解式攔截的add操作")
    public void  add(){

    }
}

4)編寫使用方法規則的被攔截的類

package com.dy.spring_demo.ch1.aop;

import org.springframework.stereotype.Service;

/**
 * Author:dy_bom
 * Description: 使用方法規則被攔截類
 * Date:Created in 下午8:39 2018/4/1
 * Copyright (c)  [email protected] All Rights Reserved.
 */
@Service
public class DemoMethodService {

    public void add(){

    }
}

5)編寫切面

package com.dy.spring_demo.ch1.aop;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;

/**
 * Author:dy_bom
 * Description: 切面
 * Date:Created in 下午8:40 2018/4/1
 * Copyright (c)  [email protected] All Rights Reserved.
 */
@Aspect  //1    聲明一個切面
@Component  //2  聲明一個Bean
public class LogAspect {

    @Pointcut("@annotation(com.dy.spring_demo.ch1.aop.Action)")  //3 聲明一個切點
    public void annotationPointCut() {
    }

    @After("annotationPointCut()") // 4 聲明一個建言,並使用一個切點
    public void after(JoinPoint joinPoint) {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        Action action = method.getAnnotation(Action.class);
        System.out.println("攔截式註解:" + action.name());// 5 通過反射獲取註解上的屬性
    }

    @Before("execution(* com.dy.spring_demo.ch1.aop.DemoMethodService.*(..)))") // 6 聲明一個建言,使用攔截規則作爲參數
    public void before(JoinPoint joinPoint) {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        System.out.println("方法規則攔截:" + method.getName());
    }
}

6)配置類

package com.dy.spring_demo.ch1.aop;

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

/**
 * Author:dy_bom
 * Description: aop配置
 * Date:Created in 下午8:52 2018/4/1
 * Copyright (c)  [email protected] All Rights Reserved.
 */
@Configuration
@ComponentScan("com.dy.spring_demo.ch1.aop")
@EnableAspectJAutoProxy //1 開啓對Aspect支持
public class AopConfig {
}

7)運行

package com.dy.spring_demo.ch1.aop;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

/**
 * Author:dy_bom
 * Description: 運行
 * Date:Created in 下午8:54 2018/4/1
 * Copyright (c)  [email protected] All Rights Reserved.
 */
public class Main {

    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AopConfig.class);

        DemoAnnotationService demoAnnotationService = context.getBean(DemoAnnotationService.class);
        DemoMethodService demoMethodService = context.getBean(DemoMethodService.class);

        demoAnnotationService.add();
        demoMethodService.add();

        context.close();

    }
}

結果如下:

攔截式註解:註解式攔截的add操作
方法規則攔截:add

代碼地址:點我
下一篇:Spring常用配置

發佈了99 篇原創文章 · 獲贊 230 · 訪問量 32萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章