第一章: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万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章