spring mvc 入门

Spring入门之IOC与AOP

内容概要: spring mvc 入门, spring ioc, spring 依赖注入, spring aop, spring 面向切面编程

欢迎大家来The Hu Post Forum与我讨论spring, spring mvc相关的内容~

spring mvc 入门

Spring是目前最流行的Java开发框架, Java 企业开发中的SSH或者SSM都与Spring有关。 Spring最根本的使命是简化Java开发。

基于这一使命,Spring有了以下4中关键策略:

  • 1.      基于POJO 的轻量级和最小侵入式编程;
  • 2.      通过依赖注入和面向接口编程实现松耦合;
  • 3.      基于切面和惯例进行声明式编程;
  • 4.      通过切面和模板减少样板式代码。

(PS.  Spring 实战,第4版)

Spring核心: IOC与AOP

这里简单的介绍下Spring最为核心的两个特性:IOC  和AOP

IOC控制反转容器

IOC(Inverse Of Control) 容器: 控制反转意思是应用程序不再负责维护对象(Java中主要是对象的创建,初始化),而将这部分工作交给IOC容器。  应用程序直接从IOC 容器中获取到所需要的对象,  只负责使用对象

这是一种分工合作的思想,  将对象的维护和使用进行了分工,应用程序只负责使用对象。

DI(Dependency Injecttion)依赖注入在Spring 中一般作为IOC 容器的同义词(PS. Spring 实战第4版 一书就使用的是DI).   个人理解, DI 是通过IOC容器来实现的,  IOC 容器不仅可以生成Java 对象,  还可以组装Java 对象之间的依赖关系,  这正式IOC 强大的地方。  如果你有一个对象A ,  它持有对象B 的引用即A 依赖B,  那当你使用Spring IOC 容器获取A对象时,  A 引用的B 对象也已经被IOC 容器准备好并且赋值给A 中的属性。

Spring依赖注入(DI) 方式

Spring 的依赖注入一般有两种方式:

  • 1.      设值注入

IOC 容器调用setter 方法将依赖注入到目标对象

  • 2.      构造注入

依赖作为构造器的参数,通过构造函数注入到目标对象

Spring 中的对象Bean

bean 的作用域

Spring 中对象(Bean)的作用域:

  • 1.      Singleton: 单例,一个bean容器中只存在一个, 默认行为;
  • 2.      prototype:   每次向bean容器请求都会创建一个实例;
  • 3.      request:  每次http请求都会创建一个实例,并且仅在当前request内有效,只在web-aware Spring ApplicationContext的上下文中有效
  • 4.      session :  每个会话会创建一个实例,并且在当前会话内有效,只在web-aware Spring ApplicationContext的上下文中有效
  • 5.      Global Session: 类似session,  只在portlet 环境中有效,  非portlet 环境中相当于session。只在web-aware Spring ApplicationContext的上下文中有效
bean的生命周期

Bean 的生命周期:

  • 1.      定义
  • 2.      初始化

实现InitializaingBean 接口或者配置init-method 方法

  • 3.      使用
  • 4.      销毁

实现DesposableBean 接口或者配置detroy-method 方法

bean的自动装配

Autowiring(自动装配):

  • 1.      No, 默认行为
  • 2.      byName
  • 3.      byType
  • 4.      Constructor

Spring 中可以开启自动装配功能, 这样不需要在bean的配置中显式的声明依赖对象,Spring 会自动进行依赖注入,通过配置的自动装配类型。

Aware 接口

  • 1.      ApplicationContextAware
  • 2.      BeanNameAware

Aware 接口可以获取到Spring的相关资源(如果Context容器,BeanName)来进行相关的操作。

AOP 面向切面编程

AOP(Aspect Oriented Programming,  面向切面编程),  通常用于分离业务逻辑和系统服务,实现松耦合

一般由预编译和动态代理两种实现方式,SpringAOP 是使用动态代理实现的。

Aspect(切面):一个关注点的模块化,会横切多个对象。

切面是一些系统级的服务,  每个业务模块都需要,  例如日志,性能统计,安全控制,事物处理等。

(PS. 事物, 一组操作要么一起成功要么一起失败)

PointCut(切点):  匹配连接点的断言

连接点就是切面和业务模块相连的地方, 即实际要触发执行切面动作的业务模块代码位置。

Advice(通知):切面在连接点要执行的动作,有以下几种类型:

  • 1.      Before
  • 2.      After returning
  • 3.      After throwing
  • 4.      After
  • 5.      Around

Spring bean 装配方式配置

Spring 装配Bean的方式:

  • 1.      在XML 中进行显示配置
  • 2.      在Java 中进行显示配置(注解)
  • 3.      隐式的bean 发现机制和自动装配

Spring in Action 一书推荐优先使用组件扫描和自动装配,  其次是Java 配置,  再是XML 配置。

Spring Java 配置方式装配Bean 的常用注解:

@Component :  表明该类会作为组件类,Spring 要为这个类创建bean; 可以带一个字符串参数,显示指定bean ID.

如果不明确设置beanid , Spring  会根据类名指定一个, 即将类名的第一个字母小写作为ID.

@Configuration : 表明这是一个Spring 配置类

@ComponentScan:   开启组件扫描,扫描所有用@Component标记的类,  默认扫描与配置类相同的包, 可以用basePackage或者basePackageClasses属性来指定扫描的路径

@Autowired :   Sping 自动装配,  可以用于构造器和属性的setter 方法上,  required 属性默认为true,  意味着Spring 在创建应用上下文时,  如果没有匹配的bean 会抛出异常;  该属性设置为false 时,  如果没有批评的bean ,  Spring 会让这个bean 处于未装配的状态,  需要谨慎使用。

自动组件扫描和自动装配有时行不通,  例如需要将第三方库中的组件装配到应用中,  这时需要显示的配置Bean.

@Bean,    在javaConfig中声明bean(类似在xml 中声明bean)

@Configuration
//@ComponentScan(basePackageClasses = {Sgtpeppers.class})
public class CDPlayerConfig {
    
    @Bean
    public CompactDisc sgtPeppers()
    {
        return new Sgtpeppers();
    }
    
    @Bean
    public CDPlayer cdPlayer(CompactDisc compactDisc)
    {
        return new CDPlayer(compactDisc);
    }
}

@Bean 注解可以采用任何有必要的Java功能来产生bean,构造器和Setter方法是最常见的, 可能性仅仅受Java语言的限制。

XML配置提供的能力和JavaConfig 基本类似,  这里不展开了,  xml 中可以配置list,map,set 等类型,  参考Spring-util 命名空间中的元素:

http://www.cnblogs.com/shuqi/p/4595618.html

@Profile,   用于实现不同的环境不同的配置

@Conditional, 可以用到带有@Bean 注解的之上, 实现条件化Bean,  给定条件为true,  就会创建这个bean.


实践问题

  • 1.      Spring 5 Scope 定义发生了新的变化
Spring入门之IOC与AOP 1

Spring 5 中Scope 有如下几种:

  • 1.      Singleton
  • 2.      Prototype
  • 3.      Request
  • 4.      Session
  • 5.      Application
  • 6.      WebSocket
  • 2.      使用Spring bean 时候 Spring容器已经close,  bean 的destory-method 没有被调用,  配置destory 属性或者实现DisposableBean 接口都一样

Prototype下是没有destory 方式

Destroy method is not called forbeans of scope prototype. This is because the context doesn’t keep track of theprototype scope objects (if it does, it will cause a memory leak as springdoesn’t know when to dispose it).

https://stackoverflow.com/questions/16783552/destroy-method-is-not-working-in-spring-framework

  • 3.       Bean 初始化和销毁两种方式优先级?

初始化:   afterPropertiesSet  ->  init-method

销毁:   destroy() ->   destroy-method

两种方式可以同时使用。

  • 4.      Spring 作为Bean 容器有什么优点?

Spring 单独作为一个Bean 容器,  没有什么优点,  完全没必要。 使用Spring或者一个bean需要先在xml定义bean,  然后获得Spring 容器, 再从容器中取得bean.  过程比直接使用new 复杂多了。  如果单独作为一个bean 容器来使用完全是大材小用。 Spring 的优势是依赖注入,  当对象之间有复杂的依赖关系时,  使用Spring 容器的优势就体现出来了, 无论bean 依赖多严重,  还是可以直接从Spring 容器中获取需要的bean,  而且各种依赖关系Spring 都准备好了。

  • 5.      使用Spring AOP 时,  死活不对(AOP 配置很简单), 一直提示:
Caused by: java.lang.NoClassDefFoundError:org/aspectj/weaver/reflect/ReflectionWorld$ReflectionWorldException

                atjava.lang.Class.getDeclaredConstructors0(Native Method)

                atjava.lang.Class.privateGetDeclaredConstructors(Class.java:2671)

                atjava.lang.Class.getConstructor0(Class.java:3075)

                atjava.lang.Class.getDeclaredConstructor(Class.java:2178)

                atorg.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:79)

                ...71 more

Caused by:java.lang.ClassNotFoundException:org.aspectj.weaver.reflect.ReflectionWorld$ReflectionWorldException

                atjava.net.URLClassLoader.findClass(URLClassLoader.java:381)

                atjava.lang.ClassLoader.loadClass(ClassLoader.java:424)

                atsun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)

                atjava.lang.ClassLoader.loadClass(ClassLoader.java:357)

                ...76 more

AOP 定义如下:

<?xml version="1.0"encoding="UTF-8"?>
<beansxmlns="http://www.springframework.org/schema/beans"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:aop="http://www.springframework.org/schema/aop"
      xsi:schemaLocation="http://www.springframework.org/schema/beans
                http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsd">

    <beanid="User"class="User"scope="singleton" init-method="init"destroy-method="destory1">
       <!--constructor-arg ref="IPhone"/ -->
       <property name="phone"ref="IPhone"/>
    </bean>
    <beanid="IPhone"class="Iphone"/>
    <beanid="MyAspect"class="MyAspect"/>

    <aop:config>
        <aop:aspectid="Aspect"ref="MyAspect">
            <aop:pointcutid="MyPointCut"
                         expression="execution(**.recordMessage(..))"/>
            <aop:before pointcut-ref="MyPointCut"
                        method="monitorAspect"/>
        </aop:aspect>
    </aop:config>

   <!--more bean definitions go here -->

</beans>

原因: 定义切点时,使用了AspectJ的切点表达式语言,  需要在依赖工程依赖中加入AspectJ 的依赖,  在POM 中添加AspectJ的依赖后问题解决:

<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjrt</artifactId>
    <version>1.8.11</version>
</dependency>

<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>1.8.11</version>
</dependency>
写在 spring mvc 入门 最后:
spring可以搭配其他ORM框架使用, 例如mybatis, mybatis相关内容可以参考我写的 mybatis使用入门

常见问题:

什么是MVC?

MVC全名是Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写,一种软件设计典范,用一种业务逻辑、数据、界面显示分离的方法组织代码,将业务逻辑聚集到一个部件里面,在改进和个性化定制界面及用户交互的同时,不需要重新编写业务逻辑。MVC被独特的发展起来用于映射传统的输入、处理和输出功能在一个逻辑的图形化用户界面的结构

什么是Spring MVC?

Spring MVC属于SpringFrameWork的后续产品,已经融合在Spring Web Flow里面。Spring 框架提供了构建 Web 应用程序的全功能 MVC 模块。使用 Spring 可插入的 MVC 架构,从而在使用Spring进行WEB开发时,可以选择使用Spring的Spring MVC框架或集成其他MVC开发框架,如Struts1(现在一般不用),Struts 2(一般老项目使用)等。

spring与springboot区别?

1.Spring Boot提供极其快速和简化的操作,让 Spring 开发者快速上手。
2.Spring Boot提供了 Spring 运行的默认配置。
3.Spring Boot为通用 Spring项目提供了很多非功能性特性,例如:嵌入式 Serve、Security、统计、健康检查、外部配置等等。

什么是DI依赖注入?

把有依赖关系的类放到容器中,解析出这些类的实例,就是依赖注入。目的是实现类的解耦。
实例:Class A中用到了Class B的对象b,一般情况下,需要在A的代码中显式的new一个B的对象。采用依赖注入技术之后,A的代码只需要定义一个私有的B对象,不需要直接new来获得这个对象,而是通过相关的容器控制程序来将B对象在外部new出来并注入到A类里的引用中。这样做有什么好处呢?

什么是AOP面向切面编程?

在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期间动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top