Spring基础

目录

1.spring概述

1.1.spring模块

1.2 spring的生态

2.Spring基础配置

2.1 依赖注入

代码示例

2.2 java配置

2.3 AOP

代码示例

1.spring概述

Spring框架是一个轻量级的企业级开发的一站式解决方案。所谓解决方案就是可以基于Spring解决Java EE开发的所有问题。Spring框架主要提供了IoC容器、AOP、数据访问、Web开发、消息、测试等相关技术的支持。
Spring使用简单的POJO(Plain Old Java Object,即无任何限制的普通Java对象)来进行企业级开发。
每一个被Spring管理的Java对象都称之为Bean;而Spring提供了一个IoC容器用来初始化对象,解决对象间的依赖管理和对象的使用。

1.1.spring模块

(1)核心容器(Core Container)
Spring-Core:核心工具类,Spring其他模块大量使用Spring-Core;
Spring-Beans:Spring定义Bean的支持;
Spring-Context:运行时Spring容器;
Spring-Context-Support:Spring容器对第三方包的集成支持;
Spring-Expression:使用表达式语言在运行时查询和操作对象。
(2)AOP
Spring-AOP:基于代理的AOP支持;
Spring-Aspects:基于AspectJ的AOP支持。
(3)消息(Messaging)
Spring-Messaging:对消息架构和协议的支持。
(4)Web
Spring-Web:提供基础的Web集成的功能,在Web项目中提供Spring的容器;
Spring-Webmvc:提供基于Servlet的Spring MVC;
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发展到现在已经不仅仅是Spring框架本身的内容,Spring目前提供了大量的基于Spring的项目,可以用来更深入地降低我们的开发难度,提高开发效率。
目前Spring的生态里主要有以下项目,我们可以根据自己项目的需要来选择使用相应的项目。
Spring Boot:使用默认开发配置来实现快速开发。
Spring XD:用来简化大数据应用开发。
Spring Cloud:为分布式系统开发提供工具集。
Spring Data:对主流的关系型和NoSQL数据库的支持。
Spring Integration:通过消息机制对企业集成模式(EIP)的支持。
Spring Batch:简化及优化大量数据的批处理操作。

Spring Security:通过认证和授权保护应用。
Spring HATEOAS:基于HATEOAS原则简化REST服务开发。
Spring Social:与社交网络API(如Facebook、新浪微博等)的集成。
Spring AMQP:对基于AMQP的消息的支持。
Spring Mobile:提供对手机设备检测的功能,给不同的设备返回不同的页面的支持。
Spring for Android:主要提供在Android上消费RESTful API的功能。
Spring Web Flow:基于Spring MVC提供基于向导流程式的Web应用开发。
Spring Web Services:提供了基于协议有限的SOAP/Web服务。
Spring LDAP:简化使用LDAP开发。
Spring Session:提供一个API及实现来管理用户会话信息。

2.Spring基础配置

Spring框架本身有四大原则:
1)使用POJO进行轻量级和最小侵入式开发。
2)通过依赖注入和基于接口编程实现松耦合。
3)通过AOP和默认习惯进行声明式编程。
4)使用AOP和模板(template)减少模式化代码。
Spring所有功能的设计和实现都是基于此四大原则的。

2.1 依赖注入

我们经常说的控制翻转(Inversion of Control-IOC)和依赖注入(dependency injection-DI)在Spring环境下是等同的概念,控制翻转是通过依赖注入实现的。所谓依赖注入指的是容器负责创建对象和维护对象间的依赖关系,而不是通过对象本身负责自己的创建和解决自己的依赖。
依赖注入的主要目的是为了解耦,体现了一种“组合”的理念。
Spring IoC容器(ApplicationContext)负责创建Bean,并通过容器将功能类Bean注入到你需要的Bean中。Spring提供使用xml、注解、Java配置、groovy配置实现Bean的创建和注入。
无论是xml配置、注解配置还是Java配置,都被称为配置元数据,所谓元数据即描述数据的数据。元数据本身不具备任何可执行的能力,只能通过外界代码来对这些元数据行解析后进行一些有意义操作。Spring容器解析这些配置元数据进行Bean初始化、配置和管理依赖。
声明Bean的注解:
@Component组件,没有明确的角色。
@Service在业务逻辑层(service层)使用。
@Repository在数据访问层(dao层)使用。
@Controller在展现层(MVC→Spring MVC)使用。

注入Bean的注解,一般情况下通用。
@Autowired:Spring提供的注解。
@Inject:JSR-330提供的注解。
@Resource:JSR-250提供的注解。
@Autowired、@Inject、@Resource可注解在set方法上或者属性上。

代码示例

1.编写功能类的bean

package com.springbootdemo.study;

import org.springframework.stereotype.Service;

/**
 * FunctionService
 *
 * @Description
 */
//使用@Service注解声明当前FunctionService类是Spring管理的一个Bean
@Service
public class FunctionService {

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

}

2.使用功能类的bean

package com.springbootdemo.study;

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

/**
 * UseFunctionService
 *
 * @Description
 */
// 使用@Service注解声明当前UseFunctionService类是Spring管理的一个Bean。
@Service
public class UseFunctionService {
    /**
     *  使用@Autowired将FunctionService的实体Bean注入到UseFunctionService中,
     *  让UseFunctionService具备FunctionService的功能,此处使用JSR-330的@Inject注解或者JSR-250的@Resource注解是等效的。
     */
    @Autowired
    FunctionService functionService;

    public String sayHello(String word){
        return functionService.sayHello(word);
    }

}

3.配置类

package com.springbootdemo.study;

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

/**
 * DiConfig
 *
 * @Description
 */
//@Configuration声明当前类是一个配置类
@Configuration
//使用@ComponentScan,自动扫描包名下所有使用@Service、@Component、@Repository和@Controller的类,并注册为Bean。
@ComponentScan("com.springbootdemo.study")
public class DiConfig {

}

4.运行测试

package com.springbootdemo.study;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

/**
 * Main
 * @Description
 */
public class Main {

    public static void main(String[] args) {
        //使用AnnotationConfigApplicationContext作为Spring容器,接受输入一个配置类作为参数;
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(DiConfig.class);
        //获得声明配置的UseFunctionService的Bean。
        UseFunctionService useFunctionService = context.getBean(UseFunctionService.class);
        System.out.println(useFunctionService.sayHello("di"));
        context.close();

    }
}

2.2 java配置

Java配置是Spring 4.x推荐的配置方式,可以完全替代xml配置;Java配置也是Spring Boot推荐的配置方式。Java配置是通过@Configuration和@Bean来实现的。
@Configuration声明当前类是一个配置类,相当于一个Spring配置的xml文件。
@Bean注解在方法上,声明当前方法的返回值为一个Bean。
开发时一般使用Java配置和注解混合配置。何时使用Java配置或者注解配置呢?主要原则是:全局配置使用Java配置(如数据库相关配置、MVC相关配置),业务Bean的配置使用注解配置(@Service、@Component、@Repository、@Controller)。

代码示例

1.编写功能类的bean

package com.springbootdemo.study.javaconfig;

/**
 * FunctionService
 *
 * @Description
 */
public class FunctionService {

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

2.使用功能类的bean

package com.springbootdemo.study.javaconfig;

/**
 * UseFunctionService
 * @Description
 */
public class UseFunctionService {

    FunctionService functionService;

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

    public String sayHello(String word){
        return functionService.sayHello(word);
    }


}

3.配置类

package com.springbootdemo.study.javaconfig;

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

/**
 * JavaConfig
 *
 * @Description
 */
//使用@Configuration注解表明当前类是一个配置类,这意味着这个类里可能有0个或者多个@Bean注解,此处没有使用包扫描,是因为所有的Bean都在此类中定义了。
@Configuration
public class JavaConfig {
    //使用@Bean注解声明当前方法FunctionService的返回值是一个Bean,Bean的名称是方法名。
    @Bean
    public FunctionService functionService(){
        return new FunctionService();
    }

    @Bean
    public UseFunctionService useFunctionService(){
        UseFunctionService useFunctionService = new UseFunctionService();
        //注入FunctionService的Bean时候直接调用functionService()。
        useFunctionService.setFunctionService(functionService());
        return useFunctionService;
    }

    /**
     * 另外一种注入的方式,直接将FunctionService作为参数给useFunctionService(),这也是Spring容器提供的极好的功能。
     * 在Spring容器中,只要容器中存在某个Bean,就可以在另外一个Bean的声明方法的参数中写入。
     * @param functionService
     * @return
     */
    @Bean
    public UseFunctionService useFunctionService(FunctionService functionService){
        UseFunctionService useFunctionService = new UseFunctionService();
        useFunctionService.setFunctionService(functionService);
        return useFunctionService;

    }

}

4.运行测试

package com.springbootdemo.study.javaconfig;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

/**
 * Main
 * @Description
 */
public class Main {

    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(JavaConfig.class);
        UseFunctionService useFunctionService = context.getBean(UseFunctionService.class);
        System.out.println(useFunctionService.sayHello("java config"));
        context.close();

    }
}

2.3 AOP

AOP:面向切面编程,相对于OOP面向对象编程。
Spring的AOP的存在目的是为了解耦。AOP可以让一组类共享相同的行为。在OOP中只能通过继承类和实现接口,来使代码的耦合度增强,且类继承只能为单继承,阻碍更多行为添加到一组类上,AOP弥补了OOP的不足。
Spring支持AspectJ的注解式切面编程。
(1)使用@Aspect声明是一个切面。
(2)使用@After、@Before、@Around定义建言(advice),可直接将拦截规则(切点)作为参数。
(3)其中@After、@Before、@Around参数的拦截规则为切点(PointCut),为了使切点复用,可使用@PointCut专门定义拦截规则,然后在@After、@Before、@Around的参数中调用。
(4)其中符合条件的每一个被拦截处为连接点(JoinPoint)。
本文基于注解拦截和基于方法规则拦截两种方式,演示一种模拟记录操作的日志系统的实现。其中注解式拦截能够很好地控制要拦截的粒度和获得更丰富的信息,Spring本身在事务处理(@Transcational)和数据缓存(@Cacheable等)上面都使用此种形式的拦截。

代码示例

1.添加spring aop支持及AspectJ依赖

本人使用idea构建的springboot项目,需要引入以下jar包

<dependency>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

2.编写拦截规则的注解

package com.springbootdemo.study.aop;

import java.lang.annotation.*;

/**
 * Action
 *
 *  这里讲下注解,注解本身是没有功能的,就和xml一样。注解和xml都是一种元数据,元数据即解释数据的数据,这就是所谓配置。
 * 注解的功能来自用这个注解的地方。
 * @Description
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Action {
    String name();
}

3.编写使用注解的被拦截类

package com.springbootdemo.study.aop;

import org.springframework.stereotype.Service;

/**
 * DemoAnnotationService
 *  使用注解的被拦截类
 * @Description
 */
@Service
public class DemoAnnotationService {
    @Action(name = "注解式拦截的add操作")
    public void add(){

    }

}

4.编写使用方法规则被拦截类

package com.springbootdemo.study.aop;

import org.springframework.stereotype.Service;

/**
 * DemoMethodService
 * 使用方法规则被拦截类。
 * @Description
 */
@Service
public class DemoMethodService {

    public void add(){

    }
}

5.编写切面

package com.springbootdemo.study.aop;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
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;

/**
 * LogAspect
 *
 * @Description
 */
@Component //通过@Component让此切面成为Spring容器管理的Bean。
@Aspect //通过@Aspect注解声明一个切面。
public class LogAspect {

    //通过@PointCut注解声明切点。
    @Pointcut("@annotation(com.springbootdemo.study.aop.Action)")
    public void annotationPointCut(){}

    //通过@After注解声明一个建言,并使用@PointCut定义的切点。
    @After("annotationPointCut()")
    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());
    }

    //通过@Before注解声明一个建言,此建言直接使用拦截规则作为参数。
    @Before("execution(* com.springbootdemo.study.aop.DemoMethodService.*(..))")
    public void before(JoinPoint joinPoint){
        MethodSignature signature = (MethodSignature)joinPoint.getSignature();
        Method method = signature.getMethod();
        System.out.println("方法规则式拦截," + method.getName());

    }

}

6.配置类

package com.springbootdemo.study.aop;

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

/**
 * AopConfig
 *
 * @Description
 */
@Configuration
@ComponentScan("com.springbootdemo.study.aop")
@EnableAspectJAutoProxy //使用@EnableAspectJAutoProxy注解开启Spring对AspectJ代理的支持。
public class AopConfig {

}

7.运行测试

package com.springbootdemo.study.aop;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

/**
 * Main
 *
 * @Description
 */
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();
    }
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值