Spring框架总结

Spring框架总结

Spring的设计理念

  • spring 是一个集众多设计模式(工厂模式、单例模式、适配器模式…)于一身的开源轻量级框架。
  • 初衷不是创造轮子,而是使现用的轮子更好的运转,致力于整合现有的框架技术(mybatis、struts…)。

Spring作用

  • 接管项目中组件(dao、service、action)的创建、销毁和生产。
  • 通过依赖注入降低耦合、AOP编程方式简化java开发,解放生产力。

Spring核心思想

  • IOC(Inversion of Control):控制权利反转,把手动创建对象的权利交给框架
    DI(Dependency Injection): 依赖注入 ,由IOC容器维护对象之间的依赖关系
  • AOP(Aspect-Oriented Programming):面向切面编程

Spring体系结构

Spring 有可能成为所有企业应用程序的一站式服务点,然而,Spring 是模块化的,允许你挑选和选择适用于你的模块,不必要把剩余部分也引入。下面的部分对在 Spring 框架中所有可用的模块给出了详细的介绍。

Spring 框架提供约 20 个模块,可以根据应用程序的要求来使用。

核心容器

核心容器由spring-core,spring-beans,spring-context,spring-context-support和spring-expression(SpEL,Spring表达式语言,Spring Expression Language)等模块组成,它们的细节如下:

  • spring-core模块提供了框架的基本组成部分,包括 IoC 和依赖注入功能。

  • spring-beans 模块提供 BeanFactory,工厂模式的微妙实现,它移除了编码式单例的需要,并且可以把配置和依赖从实际编码逻辑中解耦。

  • context模块建立在由core和 beans 模块的基础上建立起来的,它以一种类似于JNDI注册的方式访问对象。Context模块继承自Bean模块,并且添加了国际化(比如,使用资源束)、事件传播、资源加载和透明地创建上下文(比如,通过Servelet容器)等功能。Context模块也支持Java EE的功能,比如EJB、JMX和远程调用等。ApplicationContext接口是Context模块的焦点。spring-context-support提供了对第三方库集成到Spring上下文的支持,比如缓存(EhCache, Guava, JCache)、邮件(JavaMail)、调度(CommonJ, Quartz)、模板引擎(FreeMarker, JasperReports, Velocity)等。

  • spring-expression模块提供了强大的表达式语言,用于在运行时查询和操作对象图。它是JSP2.1规范中定义的统一表达式语言的扩展,支持set和get属性值、属性赋值、方法调用、访问数组集合及索引的内容、逻辑算术运算、命名变量、通过名字从Spring IoC容器检索对象,还支持列表的投影、选择以及聚合等。。

数据访问/集成

数据访问/集成层包括 JDBC,ORM,OXM,JMS 和事务处理模块,它们的细节如下:

注:JDBC=Java Data Base Connectivity,ORM=Object Relational Mapping,OXM=Object XML Mapping,JMS=Java Message Service)

  • JDBC 模块提供了JDBC抽象层,它消除了冗长的JDBC编码和对数据库供应商特定错误代码的解析。

  • ORM 模块提供了对流行的对象关系映射API的集成,包括JPA、JDO和Hibernate等。通过此模块可以让这些ORM框架和spring的其它功能整合,比如前面提及的事务管理。

  • OXM 模块提供了对OXM实现的支持,比如JAXB、Castor、XML Beans、JiBX、XStream等。

  • JMS 模块包含生产(produce)和消费(consume)消息的功能。从Spring 4.1开始,集成了spring-messaging模块。。

  • 事务模块为实现特殊接口类及所有的 POJO 支持编程式和声明式事务管理。

    (注:编程式事务需要自己写beginTransaction()、commit()、rollback()等事务管理方法,声明式事务是通过注解或配置由spring自动处理,编程式事务粒度更细)

Web

Web 层由 Web,Web-MVC,Web-Socket 和 Web-Portlet 组成,它们的细节如下:

  • Web 模块提供面向web的基本功能和面向web的应用上下文,比如多部分(multipart)文件上传功能、使用Servlet监听器初始化IoC容器等。它还包括HTTP客户端以及Spring远程调用中与web相关的部分。

  • Web-MVC 模块为web应用提供了模型视图控制(MVC)和REST Web服务的实现。Spring的MVC框架可以使领域模型代码和web表单完全地分离,且可以与Spring框架的其它所有功能进行集成。

  • Web-Socket 模块为 WebSocket-based 提供了支持,而且在 web 应用程序中提供了客户端和服务器端之间通信的两种方式。

  • Web-Portlet 模块提供了用于Portlet环境的MVC实现,并反映了spring-webmvc模块的功能。

其他

还有其他一些重要的模块,像 AOP,Aspects,Instrumentation,Web 和测试模块,它们的细节如下:

  • AOP 模块提供了面向方面的编程实现,允许你定义方法拦截器和切入点对代码进行干净地解耦,从而使实现功能的代码彻底的解耦出来。使用源码级的元数据,可以用类似于.Net属性的方式合并行为信息到代码中。

  • Aspects 模块提供了与 AspectJ 的集成,这是一个功能强大且成熟的面向切面编程(AOP)框架。

  • Instrumentation 模块在一定的应用服务器中提供了类 instrumentation 的支持和类加载器的实现。

  • Messaging 模块为 STOMP 提供了支持作为在应用程序中 WebSocket 子协议的使用。它也支持一个注解编程模型,它是为了选路和处理来自 WebSocket 客户端的 STOMP 信息。

  • 测试模块支持对具有 JUnit 或 TestNG 框架的 Spring 组件的测试。


Spring开发流程

  • step1 引入相关依赖
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.3.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>4.3.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>4.3.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
<version>4.3.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>4.3.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>4.3.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>4.3.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>4.3.2.RELEASE</version>
</dependency>
  • step2 引入spring配置文件

    名称:任意,一般为applicationContext.xml
    位置:项目根目录下,一般放在resources下

  • step3 开发类对象

public class UserDaoImpl implements UserDao {
    @Override
    public void add(User user) {
        System.out.println("Dao 添加用户成功~~~~~~~");
    }

    @Override
    public void queryAll() {
        System.out.println("查询所有用户成功~~~~~~~~~");
    }

}
  • step4 在配置文件注册bean
    <bean id="userDao" class="cn.gjxblog.dao.UserDaoImpl"  />
  • .step5 测试


Spring容器

Spring容器(IOC容器)是Spring框架的核心,容器将创建对象,把它们连接在一起,配置它们,并管理它们的整个生命周期从创建到销毁,Spring容器使用依赖注入(DI)来管理组成一个应用程序的组件。这些对象被称为Spring Beans。

Spring容器分类

  1. BeanFactory
    这是一个最简单的容器,它主要的功能是为依赖注入 (DI) 提供支持
  2. ApplicationContext

    注:ApplicationContext容器包括BeanFacotry容器所有功能,且添加了许多功能。一般开发使ApplicationContext容器
    ApplicationContext(I)
    常用的接口实现:

    • FileSystemXmlApplicationContext
      该容器从从完整路径下加载xml文件已被定义的 bean
    • ClassPathXmlApplicationContext
      该容器从从类路径下加载xml文件已被定义的 bean
    • WebXmlApplicationContext
      该容器会在一个 web 应用程序的范围内加载在 XML 文件中已被定义的 bean


bean对象

bean对象是被实例化,组装,并通过springIoc容器所管理的对象 ,是构成应用程序的支柱。

bean类型,生命周期

bean类型创建时间销毁时间
单例工厂启动时工厂关闭时
多例每次使用时jvm负责销毁
<!--单例 默认-->
<bean class="ioc.UserServiceImpl" id="userService" scope="singleton">
<!--多例-->
<bean class="ioc.UserServiceImpl" id="userService" scope="prototype">

spring配置bean对象方式

  1. 基于Xml的配置文件
  2. 基于注解的配置*

依赖注入

Spring依赖注入方式

1 set注入

public class UserServiceImpl implements UserService {

    private UserDao userDao;

    //1 set注入
    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }

    @Override
    public void addUser(User user) {
        System.out.println("---业务逻辑---");
        userDao.add(user);
    }
}
  • applicationContext.xml
<!--配置userDaoImpl对象-->
    <bean id="userDao" class="cn.gjxblog.dao.UserDaoImpl"  />

    <!--配置UserServiceImpl对象 set注入-->
    <bean id="userService" class="cn.gjxblog.service.impl.UserServiceImpl">
        <property name="userDao" ref="userDao"/>
    </bean>

2 构造方法注入

public class UserServiceImpl implements UserService {

    private UserDao userDao;

    //2 构造方法注入
    public UserServiceImpl(UserDao userDao) {
        this.userDao = userDao;
    }

    @Override
    public void addUser(User user) {
        System.out.println("---业务逻辑---");
        userDao.add(user);
    }
}
  • applicatonContext.xml
<!--配置userDaoImpl对象-->
    <bean id="userDao" class="cn.gjxblog.dao.UserDaoImpl"  />

    <!--配置UserServiceImpl对象 构造方法注入-->
    <bean id="userService" class="cn.gjxblog.service.impl.UserServiceImpl">
       <constructor-arg  name="userDao" value="userDao"/>
    </bean>

3 自动装配 autowire

  • byName

    根据注入的属性名与配置文件中的id匹配,一致则注入,注入失败抛NPE

    <bean id="userService" class="包名.UserServiceImpl" autowire="byName"></bean>

  • byType

    根据注入的属性类型,与配置文件中的类型匹配,一致则注入,失败则抛NPE

    <bean id="userService" class="包名.UserServiceImpl" autowire="byType"></bean>


Spring基于注解的配置

由于Spring采用xml配置,一旦项目中存在大量bean对象,书写和维护都比较麻烦,所以有为了简化开发,提高效率,从Spring2.5后可以采用注解来实例化bean,DI….。

注解开发前置条件

当我们使用注解时,必须先在容器中声明
如@Autowired注解,必须事先在Spring容器中声明AutowiredAnnotationBeanPostProcessor的Bean:

<bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor "/>

如果使用的注解过多,这样声明未免过于繁琐,Spring为我们提供了2种方法来解决

方法1:配置文件引入 <context:annotation-config/>
方法2(推荐):开启包扫描,<context:component-scan/>
该配置项其实也包含了自动注入上述processor的功能,因此当使用<context:component-scan/>后,即可将<context:annotation-config/>省去。

<!-- 开启包扫描 package:将要扫描的包-->
<context:component-scan base-package="cn.gjxblog.service,cn.gjxblog.action"/>

常注解元素及属性

元素修饰范围作用属性
@Component对当前组件实例化[value]:用来指定当前创建的实例在工厂中的唯一标识
@Repository对当前DAO组件实例化[value]
@Service对当前Service组件实例化[value]
@Controller对当前Action组件实例化[value]
----
@scope决定当前组件是否为单例[value]: singleton/prototype
----
@Autorwired属性注入值:根据类型注入-
@Qualifier属性注入值:根据组件唯一标识注入[value]:组件在工厂中的唯一标识
@Resource属性注入值:先根据name寻找ID注入,再根据类型注入[name]:默认属性名

AOP

AOP是对OOP的补充和完善,OOP引入封装,继承,多态的概念来建立一种对象层次的结构,用以模拟公共行为的一个集合。
当我们需要为分散的对象引入公共的行为的时候,OOP则显的无能为力。
AOP技术则恰恰相反,它利用一种为’横切的技术’,破解开封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用的模块,并将其名为”Aspect”。

AOP术语

描述
通知(Advice)处理目标方法以外的操作都称之为通知
切入点(PointCut)要为那些类中的那些方法加入通知
切面(Aspect)通知+切入点

通知的类型

Spring方面可以使用下面提到的5种通知工作

通知描述
前置通知MethodBeforeAdvice在目标方法执行之前,执行通知
返回后通知AfterReturningAdvice目标方法正常结束时,执行通知。
后置通知AfterAdvice目标方法无论是否发生异常,都会执行该输出
环绕通知MethodInterceptor在目标方法调用之前和之后,执行通知
异常通知ThrowsAdvice如果目标方法抛出异常,执行通知。

切入点表达式

  • execution(返回值 包.类.方法(参数表))
    使用原则:切入尽量精确,避免不必要的切入
    eg1. execturion(* cn.gjxblog.service.impl.UserServiceImpl.*(..))
    返回值:任意
    包:cn.gjxblog.service.impl
    类:UserServiceImpl
    方法:任意
    参数:任意
  • within 针对方法的切入点表达式
    eg2. within(cn.gjxblog.service.impl.UserServiceImpl)
    效果等效于eg2,都是将通知加在UserserviceImpl下的所有方法

Spring中AOP开发步骤

基于xml配置文件开发
  1. 开发通知类并实现相应的通知接口
@Aspect
public class LogAdvice implements MethodBeforeAdvice,MethodInterceptor,AfterReturningAdvice {

    /**
     * 前置通知
     * @param method 目标类中当前调用的方法对象
     * @param args 当前调用方法的参数
     * @param target 目标对象
     */
    @Override
    public void before(Method method, Object[] args, Object target)
            throws Throwable {

        System.out.println("前置通知:目标类方法执行前执行该方法");
    }

    /**
     * 环绕通知
     * @param invocation
     * @return
     * @throws Throwable
     */
    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        System.out.println("前置通知");

        System.out.println("目标类:"+invocation.getThis());

        System.out.println("调用的方法:"+invocation.getMethod());

        invocation.proceed();//执行目标方法

        System.out.println("后置通知");
        return null;
    }

    /**
     * 返回后通知
     * @param returnValue 目标方法返回值,如果方法是void,则返回为null
     * @param method 目标方法
     * @param args 方法参数表
     * @param target 目标对象
     * @throws Throwable
     */
    @Override
    public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
        System.out.println("返回后通知:目标类方法正常结束后执行该方法");
    }
}
  1. xml中配置相应通知
 <!--AOP配置-->
    <aop:config>
        <!--配置切入点 expression:切入点表达式-->
        <aop:pointcut id="pc" expression="within(cn.gjxblog.service.impl.UserServiceImpl)"/>
        <!--组装切面 切入点+通知 -->
        <aop:advisor advice-ref="logBeforeAdvice" pointcut-ref="pc"/>
    </aop:config>
基于注解开发

1.引入相应的配置

 <!--开启代理标识,在程序运行期,动态创建目标对象代理对象  -->  
   <aop:aspectj-autoproxy/>
2.开发通知类
@Component
//切面注解,声明这个类为切面
@Aspect
public class CacheAdvice {

    //切入点注解,定义一个切入点
    @Pointcut("execution(* cn.gjxblog.service.impl.UserServiceImpl.*(..))")
    public void point(){}


    @Before(value = "point()")
    public void before(){
        System.out.println("前置通知:目标类方法执行前执行该方法");
    }

    @AfterReturning("within(cn.gjxblog.service.impl.UserServiceImpl)")
    public void afterReturn(){
        System.out.println("返回后通知:目标类方法正常结束后执行该方法");
    }

    @After("point()")
    public void after(){
        System.out.println("后置通知,方法无论是否发生异常,都会执行该输出");
    }


    @AfterThrowing(value = "point()",throwing = "e")
    public void afterThrow(Exception e){
        System.out.println("异常通知:如果目标方法执行发生异常,执行该输出"+e);
    }

    @Around("point()")
    public Object around(ProceedingJoinPoint pjp){
       Object result = null;

       System.out.println("环绕通知--前置通知");

        Object[] args = pjp.getArgs();
        if(null != args && args.length >0) {
            for (Object arg : args) {
                System.out.println(arg.toString());
            }
        }

        System.out.println("目标类"+pjp.getTarget());
        System.out.println("方法签名"+pjp.getSignature());

        try {
            result = pjp.proceed();//执行目标对象的方法            
            System.out.println("环绕通知--后置通知");
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
        return result;
    }

}

IOC容器创建复杂对象

  • 简单对象:含有无参构造方法,可以直接通过new创建的对象
    可以通过xml配置bean,或者组件注解,直接交给工厂管理
  • 复杂对象,不含无参构造方法,不能直接通过new创建的对象,不能直接交给工厂管理
    如:抽象类,接口

创建步骤

  • 创建一个类,并实现FactoryBean接口,泛型为复杂对象类型
  • 在xml文件注册bean,或者使用注解元素
@Component
public class CalendarFacotyBean implements FactoryBean<Calendar> {
    /**
     *
     * @return 返回创建的对象
     * @throws Exception
     */
    @Override
    public Calendar getObject() throws Exception {
        Calendar instance = Calendar.getInstance();
        return instance;
    }

    /**
     * @return 返回创建对象的类型
     */
    @Override
    public Class<?> getObjectType() {
        return Calendar.class;
    }

    /**
     * 创建对象是否为单例
     * @return true 单例
     */
    @Override
    public boolean isSingleton() {
        return false;
    }
}

其他

基于注解的Spring测试类

  • 前置条件:引入Spring-test模块和Junit4.12以上版本
//RunWith 注解指定JUnit使用的单元测试执行类
@RunWith(SpringJUnit4ClassRunner.class)
//指定Spring配置文件所在的路径,可以同时指定多个文件
@ContextConfiguration("/applicationContext.xml")
public class TestBean {
    @Autowired
    private UserService userService;

    @Test
    public void testUserService(){
        userService.addUser(new User());
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值