• Java进阶笔记(三):Spring相关


    【总体部分】

    Spring框架的目的:让开发者专注于业务,而不是基本实现。

    ------------------

    Spring的优势:

    方便解耦,简化开发

    支持AOP编程

    支持声明式事务(@Transactional)

    方便程序测试(Junit)

    方便集成其它优秀框架

    降低JavaEE API的使用难度(spring封装了一些jdk中的方法)

    ------------------

    Spring可分为4个模块(开发时只需要引入需要的模块即可):

    Web(MVC、WebSocket、Servlet等)、Data Access(jdbc等数据操作相关)、Core Container(Core、Context等核心部分)、Test

    ==================

    【IoC部分】

    IoC(控制反转)的作用:解决对象之间的耦合问题。

    例子:直接new实现类(XXXServiceImpl),当需要变更实现类(例如名称发生变化,要使用XXXServiceImpl2),所有new的地方也需要修改,这是强耦合;

    而使用IoC后,不需要new实现类,只需要将接口类写入xml中,然后从工厂中获取即可,达到了解耦的目的。

    <beans>

      <bean id="xxxService" class="com.test.service.impl.XXXServiceImpl"></bean>

    </beans>

    只需要修改配置文件中的"XXXServiceImpl"为"XXXServiceImpl2"即可,只有一个地方。(其它地方是根据id从工厂中拿出来的,无需修改)

    ------------------

    IoC和DI的区别:

    DI:Dependency Injection(依赖注入)

    IOC和DI描述的是同一件事情,但是角度不一样;IoC是对象的角度(不用自己创建对象了),DI是容器的角度(容器把对象依赖的其它对象注入)

    ------------------

    spring中IoC的配置方式:

    1.使用xml

    2.使用xml+注解

    3.使用纯注解

    目的就是将类对象交给spring管理,将对象依赖关系交给spring实现。(@Component/@Controller/@Service/@Repository,@Autowired/@Resource)

    使用对象时,从spring工厂获取。

    ------------------

    Spring中Bean的生存周期(xml中可以用scope定义bean的作用范围):

    singleton:单例,IOC容器中只有一个该类对象【默认为这个】

    prototype:原型(多例),每次使用该类的对象(getBean),都返回一个新的对象【spring只负责创建,不负责管理这种类型的对象】

    request:web应用中使用,指明bean的生命周期为request;基本不用

    session:web应用中使用,指明bean的生命周期为session;基本不用

    application:web应用中使用,指明bean的生命周期为application;基本不用

    websocket:web应用中使用,指明bean的生命周期为websocket;基本不用

    ------------------

    使用xml注入bean,配置<bean>标签时:

    init-method:可以指定bean被初始化时调用的方法

    destroy-method:可以指定bean被销毁时调用的方法(只有当对象为singleton时才有效)

    ------------------

    使用xml注入bean,给bean中的变量设置值时,set注入方式需要使用property标签,注入普通属性使用value,注入另外一个bean使用ref。

    <bean id="..." class="...">

      <property name="username" value="abc"/>

      <property name="JavaBean" ref="javaBean"/>  

    </bean>

    构造器注入方式,需要使用constructor-arg标签,index可根据参数顺序传值,也可以使用name(同上)。

    <bean id="..." class="...">

      <constructor-arg index="0" value="abc"/>

      <constructor-arg index="1" ref="javaBean"/>  

    </bean>

    ------------------

    第三方jar包的bean可以定义在xml中,交给spring管理,例如Druid连接池。

    ------------------

    xml中用bean标签配置的对象,等价于用@Component写在相应的类文件中。

    @Component注解有三种别名,可以用来区分,分别是@Controller(控制层),@Service(服务层),@Repository(Dao层)

    ------------------

    @Autowired与@Resource:

    将类对象注入spring容器后,使用注解@Autowired,@Resource注入其它有依赖关系的对象。

    @Resource默认按照名称注入(id),【jdk11中移除了,想使用的话需要引入jar包,javax.annotation-api】

    @Autowired按照类型注入,如果按照类型无法锁定唯一对象,可以结合@Qualifier指定具体的id

    例子:

    @Autowired

    @Qualifier("xxxDao")

    private XXXDao xxxDao;

    ------------------

    spring扫描包语句样例:

    在applicationContext.xml中写:

    <!-- 开启注解扫描,base-package指定扫描的包路径 -->

    <context:component-scan base-package="com.xxx.test" />

    <!-- 引入外部资源文件 -->

    <context:property-placeholder location="classpath:jdbc.properties" />

    <!-- 第三方jar,druid连接池;配置了properties后就可以使用$占位符了 -->

    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">

     <property name="driverClassName" value="${jdbc.driver}"/>

     <property name="url" value="${jdbc.url}"/>

     <property name="username" value="${jdbc.username}"/>

     <property name="password" value="${jdbc.password}"/> 

    </bean>

    ------------------

    Spring包扫描语句样例2:

    如果是WEB应用,则在web.xml中使用以下语句:

    <!-- 注解模式需要的参数 -->

    <context-param>

      <param-name>contextClass</param-name>

      <param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>

    </context-param>

    <!-- 配置Spring配置类的类名 -->

    <context-param>

      <param-name>contextConfigLocation</param-name>

      <param-value>com.xxx.test.SpringConfig</param-value>

    </context-param>

    <!-- 使用监听器启动spring的IOC容器 -->

    <listener>

      <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>

    </listener>

    ------------------

    Spring中Bean对象的延迟加载(懒加载):配置某个对象的lazy-init,默认是false,创建容器后即初始化对象;设置为true后,当get对象时才初始化该对象。

    ------------------

    IoC容器包括map集合(单例池),beanfactory,BeanPostProcessor等,不只是map集合。

    ------------------

    spring循环依赖问题:(A->B->A)

    1.单例bean构造器参数循环依赖(无法解决)

    2.prototype原型bean循环依赖(无法解决)

    3.单例bean通过setXXX或者@Autowired进行循环依赖,可以解决。

    解决方法:三级缓存机制。

    (1)创建对象A时,实例化之后就立即放入三级缓存。

    (2)创建A途中发现依赖于对象B(A用到了B),查找一二三级缓存没有发现B,则开始创建B对象。

    (3)创建B对象途中(实例化后也立即放入三级缓存),发现依赖于对象A,从缓存中查找,在三级缓存中找到了。

    (4)从三级缓存找到A后,将A移入二级缓存,同时对A进行一些扩展操作,之后完成对象B的创建。

    (5)对象B创建完毕,把自己移入一级缓存。

    (6)继续创建对象A,直接拿到创建好的对象B(发现需要B时,缓存中没找到B,就执行创建B的方法,现在执行完毕了,所以直接拿到),之后完成A对象的创建。

    ========================

    【AOP部分】

    spring中AOP的配置方式:

    1.使用xml

    2.使用xml+注解

    3.使用纯注解

    spring使用动态代理实现AOP:

    spring实现AOP时,如果被代理对象有接口,会使用jdk动态代理;如果被代理对象没有接口,则使用cglib代理。

    使用xml配置AOP步骤:

    (1)导入2个jar包,spring-aop和aspectjweaver

    (2)创建一个XXXUtils.java,其中写好一些方法,当做切入点方法

    (3)在xml中使用bean标签引入XXXUtils.java

    (4)在xml中使用aop:config标签,配置切入点方法、方位信息(配置需要在哪个方法之前或之后执行切入的方法)

    (5)方位信息可以配置的类型有:前置、后置、异常、最终(无论是否异常都执行)、环绕(其中有个方法可以控制原有业务逻辑是否执行,类似invoke,因此比较灵活)

    (6)因此环绕通知不要与普通通知方式混用

    (7)aop:pointcut标签中,注意aspectj表达式的用法

    ---------------------------

    xml与注解配置AOP:

    1.xml中使用<aop:aspectj-autoproxy/>开启aop注解驱动

    2.XXXUtils.java中使用注解配置切面方法

    ---------------------------

    纯注解配置AOP:

    在配置类上使用@EnableAspectJAutoProxy注解开启AOP(代替<aop:aspectj-autoproxy/>)

    =============================

    【事务部分】

    Spring如何实现事务控制:

    使用动态代理与AOP思想实现控制,增加3个步骤:

    1.关闭jdbc connection自动提交(一个事务要使用一个connection);

    //然后执行被代理的事务步骤;

    2.发现执行异常则执行rollback();

    3.正常执行完毕则执行commit()。

    -----------------------------

    编程式事务:在业务代码中添加事务控制代码

    声明式事务:通过xml或者注解配置的方式达到事务控制的目的

    -----------------------------

    注解形式配置spring事务:

    1.spring配置类上加注解:@EnableTransactionManagement

    2.使用@Transactional,可以加在接口上、实现类上、方法上

    =============================

    【总结】

    Spring到底做了什么:

    1.使用反射,创建与管理类对象,配置好类对象之间的依赖关系。(IoC)

    2.使用动态代理,增强代码功能,实现事务。(AOP)

  • 相关阅读:
    GitHub地址汇总
    Jenkins相关
    兼容性测试相关
    测试开发中间件相关知识点
    QQ国际版安装
    ubuntu本機安裝软件
    从零开始ubuntu 安装ubuntu16.04
    docker 学习网站
    Apt-get 命令出现错误 python版本切换
    白盒测试系列(四)条件判定覆盖
  • 原文地址:https://www.cnblogs.com/codeToSuccess/p/13906208.html
Copyright © 2020-2023  润新知