Spring-基础

本文详细介绍了Spring框架的IOC和AOP。IOC部分涵盖Bean装配,包括创建方式、作用域、生命周期等,还有依赖注入的两种方式及自动装配;Bean管理有XML和注解两种方式。AOP部分介绍了基本概念,如切面、连接点等,还提及使用AspectJ实现AOP及SpringAOP的使用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Spring框架的描述 ::  传送门 Spring-百度百科

目录

Spring IOC

Bean的装配

创建bean对象的三种方式

bean的作用域

bean的生命周期

bean的生命周期 -- 流程

bean的延迟加载

依赖注入DI

依赖注入的两种方式

自动装配配合Bean的DI注入(不推荐)

Bean的管理

XML配置方式

注解方式

Spring AOP

使用AspectJ实现AOP

AOP的基本概念

SpringAOP的使用


Spring是一个轻量级 控制反转(IoC) 面向切面(AOP) 容器框架

架构如图 : web层, 数据层,面向切面层,核心层,测试层

 

Spring IOC

IOC:控制反转(Inversion Of Control),原来创建和管理(维护)对象由程序代码完成,现在把创建和管理(维护)对象的权利交给Spring容器管理,我们把控制权的转移叫控制反转。

Spring Bean的简单使用

1、定义一个类HelloSpring

public class HelloSpring{
    public void sayHell(){
        System.out.println("Hello Spring!");
    }
}

2、编写配置文件

 <!-- bean的作用,实例化对象 -->
 <!-- class表示要实例化的类名 -->
 <!-- id表示获取bean对象的名称 -->
<bean id="hello" class="cn.tedu.demo.HelloSpring">
</bean>

3、初始化容器对象并获取bean对象

//ApplicationContext是接口
//ClassPathXmlApplicationContext是ApplicationContext实现类;
ApplicationContext ac = new ClassPathXmlApplicationContext("application.xml");
//获取bean对象-方式1
HelloSpring hs = (HelloSpring)ac.getBean("hello");
//获取bean对象-方式2
HelloSpring hs1 = ac.getBean("hello",HelloSpring.class);

 

Bean的装配

创建bean对象的三种方式

1.无参构造(默认的方式)

<bean id="bean的名字" class="xx.xx.ClassName"/>

2.静态工厂(简单工厂的设计模式)

对象是由静态方法获取的实例,把静态方法获取实例对象的模式,叫静态工厂方法实例化bean对象
Calendar cd = Calendar.getInstance();

//factory-method: 该属性指定实例工厂的工厂方法
<bean id="cl" class="java.util.Calendar" factory-method="getInstance"/>

3.实例工厂(工厂方法的设计模式)

在cn.tedu.demo包中,定义类
public class BeanFactory{
    public Calendar getCalendar(){
        return Calendar.getInstance();
    }
}

<bean id="beanFactory" class="xx.xx.BeanFactory"/>
<bean id="calendar" class="java.util.Calendar" factory-method="getCalendar" factory-bean="beanFactory" />

bean的作用域

作用域解释
singleton(默认)单例模式,在整个Spring IoC容器中,singleton作用域的Bean将只生成一个实例
prototype每次通过容器的getBean()方法获取prototype作用域的Bean时,都将产生一个新的Bean实例
request对于一次HTTP请求,request作用域的Bean将只生成一个实例,这意味着,在同一次HTTP请求内,程序每次请求该Bean,得到的总是同一个实例。只有在Web应用中使用Spring时,该作用域才真正有效
session对于一次HTTP会话,session作用域的Bean将只生成一个实例,这意味着,在同一次HTTP会话内,程序每次请求该Bean,得到的总是同一个实例。只有在Web应用中使用Spring时,该作用域才真正有效
global session每个全局的HTTP Session对应一个Bean实例。在典型的情况下,仅在使用portlet context的时候有效,同样只在Web应用中有效

设置作用域 用xml方式

<bean id ="" class="" scope="prototype"/>

如果不指定Bean的作用域,Spring默认使用singleton作用域。prototype作用域的Bean的创建、销毁代价比较大。而singleton作用域的Bean实例一旦创建成果,就可以重复使用。因此,应该尽量避免将Bean设置成prototype作用域。

bean的生命周期

bean的创建到销毁(从生到死)这个过程,叫生命周期,与servlet 基本一样

public class BeanLife{
    public BeanLife(){
        .....("BeanLife");
    }
    public void init(){
        .....("init");
    }
    public void destroy(){
        .....("destroy");
    }
}


配置文件

<!-- bean的生命周期 -->
   <!-- init-method 表示定义初始化方法的方法名 
        destroy-method 表示定义销毁方法的方法名  请注意 只有在singleton的作用域下才有效
   -->
   <bean id="beanLife" 
         class="cn.tedu.demo.BeanLife"
         init-method="init"
         destroy-method="destroy"/>

bean的生命周期 -- 流程

1. instantiate bean对象实例化

2. populate properties 封装属性

3. 如果Bean实现BeanNameAware 执行 setBeanName

4. 如果Bean实现BeanFactoryAware 或者 ApplicationContextAware 设置工厂 setBeanFactory 或者上下文对象 setApplicationContext

5. 如果存在类实现 BeanPostProcessor(后处理Bean) ,执行 postProcessBeforeInitialization 

6. 如果Bean实现InitializingBean 执行 afterPropertiesSet

7. 调用<bean init-method="init"> 指定初始化方法 init如果存在类实现 BeanPostProcessor(处理Bean) ,执行postProcessAfterInitialization

8. 执行业务处理

9. 如果Bean实现 DisposableBean 执行 destroy

10. 调用<bean destroy-method="customerDestroy"> 指定销毁方法 customerDestroy 

bean的延迟加载

1)、立即加载:默认情况下,当初始化容器对象时,所有的bean对象就会被实例化,这种的加载对象的方式,叫立即加载 。

为什么延迟加载:节省内存

2)、实现延迟加载:

<bean id="bean名" class="xx.xx.类名" lazy-init="true"/> 

 

依赖注入DI

通常情况下,一个类不能完成复杂的业务处理,会有多个类一起合作完成,就会出现一个类中会调用另外一个类的方法,就需要给依赖的对象赋值,所有在程序运行过程中动态给组件(成员变量)赋值,这种方式就叫依赖注入。

依赖注入的两种方式

1、属性setter方法注入

设值注入是指IoC容器通过成员变量的setter方法来注入被依赖对象。这种注入方式简单、直观,因而在Spring的依赖注入里大量使用。

2、构造函数注入

利用构造器来设置依赖关系的方式,被称为构造注入。通俗来说,就是驱动Spring在底层以反射方式执行带指定参数的构造器,当执行带参数的构造器时,就可利用构造器参数对成员变量执行初始化——这就是构造注入的本质。

xml配置如下:

1、setter方法依赖注入(建议)
 <!-- 
    1.实例化业务层的对象
    2.property表示给成员变量赋值(属性赋值)
    3.name表示属性名
    4.ref表示已经创建好的对象的id名
 -->
  <bean id="userDao" class="cn.tedu.dao.UserDaoImpl"/>
  <bean id="userService" 
        class="cn.tedu.service.UserServiceImpl">
        <!-- 相当于调用set方法 -->
        <property name="userDao" ref="userDao"/>
  </bean>


2、构造方法依赖注入
   <!-- 
    1.constructor-arg表示使用构造方法给成员变量赋值
    2.index表示构造方法参数的索引(从0开始)
    3.ref表示已经创建好的对象id
   -->
  <bean id="userService2" 
        class="cn.tedu.service.UserServiceImpl">
        <constructor-arg index="0" ref="userDao"/>
  </bean>

 

自动装配配合Bean的DI注入(不推荐)

Spring能自动装配Bean与Bean之间的依赖关系,即无须使用ref显式指定依赖Bean,而是由Spring容器检查XML配置文件内容,根据某种规则,为调用者Bean注入被依赖的Bean。
Spring自动装配可通过<beans/>元素的default-autowire属性指定,该属性对配置文件中所有的Bean起作用;也可通过对<bean/>元素的autowire属性指定,该属性只对该Bean起作用。

autowiredefault-autowire可以接受如下值

  • no: 不使用自动装配。Bean依赖必须通过ref元素定义。这是默认配置,在较大的部署环境中不鼓励改变这个配置,显式配置合作者能够得到更清晰的依赖关系
  • byName: 根据setter方法名进行自动装配。Spring容器查找容器中全部Bean,找出其id与setter方法名去掉set前缀,并小写首字母后同名的Bean来完成注入。如果没有找到匹配的Bean实例,则Spring不会进行任何注入
  • byType: 根据setter方法的形参类型来自动装配。Spring容器查找容器中的全部Bean,如果正好有一个Bean类型与setter方法的形参类型匹配,就自动注入这个Bean;如果找到多个这样的Bean,就抛出一个异常;如果没有找到这样的Bean,则什么都不会发生,setter方法不会被调用
  • constructor: 与byType类似,区别是用于自动匹配构造器的参数。如果容器不能恰好找到一个与构造器参数类型匹配的Bean,则会抛出一个异常
  • autodetect: Spring容器根据Bean内部结构,自行决定使用constructor或byType策略。如果找到一个默认的构造函数,那么就会应用byType策略

例子: ByName,ByType

byName,byType
<!-- 
    1.autowire表示自动装配
    2.byName表示匹配属性名,完成依赖注入
    (UserServiceImpl中有个属性userDao,byName方式赋值
        就是去找id="userDao"名字的实例化对象赋值)
   -->
  <bean id="userService3" 
        class="cn.tedu.service.UserServiceImpl"
        autowire="byName"/>
<!-- 
    1.byType表示按属性的类型匹配,实现依赖注入
    2.如果有两个对象同属于一个类型,那么使用byType会出现异常
   -->
  <bean id="userService4" 
        class="cn.tedu.service.UserServiceImpl"
        autowire="byType"/>

当一个Bean既使用自动装配依赖,又使用ref显式指定依赖时,则显式指定的依赖覆盖自动装配依赖;对于大型的应用,不鼓励使用自动装配。虽然使用自动装配可减少配置文件的工作量,但大大将死了依赖关系的清晰性和透明性。依赖关系的装配依赖于源文件的属性名和属性类型,导致Bean与Bean之间的耦合降低到代码层次,不利于高层次解耦

 

Bean的管理

XML配置方式

上文都是用XML来管理Bean

注解方式

Spring提供如下几个Annotation来标注Spring Bean

  • @Component: 标注一个普通的Spring Bean类
  • @Controller: 标注一个控制器组件类
  • @Service: 标注一个业务逻辑组件类
  • @Repository: 标注一个DAO组件类

在Spring配置文件中做如下配置,指定自动扫描的包

<context:component-scan base-package="包名"/>

使用@Resource配置依赖(建议使用)

@Resource位于javax.annotation包下,是来自JavaEE规范的一个Annotation,Spring直接借鉴了该Annotation,通过使用该Annotation为目标Bean指定协作者Bean。使用@Resource<property.../>元素的ref属性有相同的效果。
@Resource不仅可以修饰setter方法,也可以直接修饰实例变量,如果使用@Resource修饰实例变量将会更加简单,此时Spring将会直接使用JavaEE规范的Field注入,此时连setter方法都可以不要。

使用@Autowired配置依赖(不推荐使用)

@Autowired为Spring包下的一个Annotation@Autowired注解来指定自动装配,@Autowired可以修饰setter方法、普通方法、实例变量和构造器等。当使用@Autowired标注setter方法时,默认采用byType自动装配策略。在这种策略下,符合自动装配类型的候选Bean实例常常有多个,这个时候就可能引起异常,为了实现精确的自动装配,Spring提供了@Qualifier注解,通过使用@Qualifier,允许根据Bean的id来执行自动装配。

使用@PostConstruct和@PreDestroy定制生命周期行为

@PostConstruct@PreDestroy同样位于javax.annotation包下,也是来自JavaEE规范的两个Annotation,Spring直接借鉴了它们,用于定制Spring容器中Bean的生命周期行为。它们都用于修饰方法,无须任何属性。其中前者修饰的方法时Bean的初始化方法;而后者修饰的方法时Bean销毁之前的方法。

推荐传统XML配置和注解配置混合使用

XML方式的优势
–  结构清晰,易于阅读

注解方式的优势
–  开发便捷,属性注入方便

XML与注解的整合开发
–  1、引入context命名空间
–  2、在配置文件中添加context:annotation-config标签

<context:annotation-config/>

 

Spring AOP

AOP(Aspect Orient Programming)也就是面向切面编程,作为面向对象编程的一种补充,已经成为一种比较成熟的编程方式。其实AOP问世的时间并不太长,AOP和OOP互为补充,面向切面编程将程序运行过程分解成各个切面。

AOP专门用于处理系统中分布于各个模块(不同方法)中的交叉关注点的问题,在JavaEE应用中,常常通过AOP来处理一些具有横切性质的系统级服务,如事务管理、安全检查、缓存、对象池管理等,AOP已经成为一种非常常用的解决方案。

AOP实现可分为两类

  1. 静态AOP实现: AOP框架在编译阶段对程序进行修改,即实现对目标类的增强,生成静态的AOP代理类,以AspectJ为代表
  2. 动态AOP实现: AOP框架在运行阶段动态生成AOP代理,以实现对目标对象的增强,以Spring AOP为代表

使用AspectJ实现AOP

AspectJ是一个基于Java语言的AOP框架,提供了强大的AOP功能,其他很多AOP框架都借鉴或采纳其中的一些思想。其主要包括两个部分:一个部分定义了如何表达、定义AOP编程中的语法规范,通过这套语法规范,可以方便地用AOP来解决Java语言中存在的交叉关注点的问题;另一个部分是工具部分,包括编译、调试工具等。

一般来说,静态AOP实现具有较好的性能,但需要使用特殊的编译器。动态AOP实现是纯Java实现,因此无须特殊的编译器,但是通常性能略差。

AOP的基本概念

关于面向切面编程的一些术语

  • 切面(Aspect): 切面用于组织多个Advice,Advice放在切面中定义
  • 连接点(Joinpoint): 程序执行过程中明确的点,如方法的调用,或者异常的抛出。在Spring AOP中,连接点总是方法的调用
  • 增强处理(Advice): AOP框架在特定的切入点执行的增强处理。处理有“around”、“before”和“after”等类型
  • 切入点(Pointcut): 可以插入增强处理的连接点。简而言之,当某个连接点满足指定要求时,该连接点将被添加增强处理,该连接点也就变成了切入点

SpringAOP的使用

传送门-----------》 Spring-AOP 面向切面(基础用法)

传送门-----------》  Spring-AOP 面向切面(AspectJ)

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值