Spring-1-(简介及HelloWord)

本文深入探讨Spring框架的核心功能,包括IoC控制反转、DI依赖注入、AOP面向切面编程,以及Spring容器的详细解释。同时介绍了Spring的运行时环境、容器类型、配置方式、自动注入、事务管理等关键概念。

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

一:Spring简介

  Spring 框架宗旨:不重新发明技术,让原有技术使用起来更加方便.

  Spring核心功能:

    1.AOP:面向切面编程

    2.Ioc/Di:控制反转/依赖注入

    3.声明式事务

  Spring框架RunTime(运行时环境)

    

    Spring中的容器(Container):

       Spring 框架中重要概念

         容器(Container): Spring 当作一个大容器.

         BeanFactory 接口.老版本. 

         ApplicationContext 接口,新版本,是 BeanFactory 子接口

      BeanFactory 的功能在 ApplicationContext 中都有

    Spring拆分jar包:

      Spring3 开始把 Spring 框架的功能拆分成多个 jar. 7.1 Spring2 及以前就一个 jar(优点:可根据不同的需求导入不同的jar,而不需将Spring中的60多个jar都加载进去)

    解析框架:

      test: spring 提供测试功能

      Core Container:核心容器.Spring 启动最基本的条件. (将spring跑起来至少有这些东西)

        Beans : Spring 负责创建类对象并管理对象

        

        Core: 核心类(类库)

        

        Context: 上下文参数.获取外部资源或这管理注解等

        

        SpEl: expression.jar

        

      AOP: 实现 aop 功能需要依赖

      Aspects: 切面 AOP 依赖的包

      Data Access/Integration : spring 封装数据访问层相关内容

        JDBC : Spring 对 JDBC 封装后的代码. 5.5.2 ORM: 封装了持久层框架的代码.例如 Hibernate

        Transactions:对应 spring-tx.jar,声明式事务使用. 5.6 WEB:需要 spring 完成 web 相关功能时需要. 5.6.1 例如:由 tomcat 加载 spring 配置文件时需要有 spring-web包

   注意:Spring运行并不依赖与Web容器(tomcat等等),jar包依旧可以运行,但是spring提供了web的jar包,所以也可以使用web容器来运行

二:核心功能

   一)IoC

  1 中文名称:控制反转

  2.英文名称:(Inversion of Control)

  3.IoC 是什么?
    3.1 IoC 完成的事情原先由程序员主动通过 new 实例化对象事情,转交给 Spring 负责.

    3.2 控制反转中控制的是谁:

      控制类的对象.

    3.3 控制反转中反转指的是:

      原来有程序员管理的类的对象转交给 Spring 负责管理.

    3.4 IoC 最大的作用:解耦.

      3.4.1 程序员不需要管理对象.解除了对象管理和程序员之间的耦合.

//以往我们需要自己手动的创建对象,并进行使用
 User user = new User();
 String address = user.getAddress();
 

//现在我们只需要将spring容器中的对象拿出来使用就好了       
 @Autowired
 User user;
 String address1 = user.getAddress();

  IoC容器有两种:
    BeanFactory:
      简介:
        基础类型的IoC容器,由org.springframework.beans.factory.BeanFactory接口定义,并提供了完整的IoC服务支持;
        BeanFactory是一个管理Bean的工程,负责初始化各种Bean并调用他们的生命周期方法。
      实现:
        org.springframework.beans.factory.xml.XmlBeanFactory,根据xml配置文件中的定义来装配Bean

     ApplicationContext:(也就是我们配置的ApplicationContext.xml)
      简介:
        是BeanFactory的子接口,也被称为应用上下文,由org.springframework.context.ApplicationContext提供,
        他提供BeanFactory所有的功能,并且加强了BeanFactory的功能,体现在Context包使用分层和有继承关系的上下文类:
          1.MessageSource,提供对i18n消息的访问;
          2.资源访问,例如URL和文件
          3.事件传递给实现了ApplicationListener接口的Bean;
          4.载入多个有集成关系的上下文类,使每一个上下文类都专注于一个特定的层次,

        几乎所有的场合都是用ApplicationContext而非底层的BeanFactory
        创建ApplicationContext接口实例(创建IoC容器):
          方式一:(从类路径中的xml文件载入上下文定义信息)
            ApplicatonContext applicationcontext=new ClassPathXmlApplicationContext("applicationContext.xml")
          方式二:(从文件路径中的xml文件载入上下文定义信息)
            ApplicatonContext applicationcontext=new FileSystemXmlApplicationContext("F:\\workspace\\applicationContext.xml")

  这里创建的是一个web工程但是使用的main方法执行也可以放进tomcat中运行)

  所依赖的jar包(核心包之外还要加一个日志包commons-logging.jar):

  

<bean class="com.xpl.model.User" id="user">
public class Text {
    public static void main(String[] args) {
//        将applicationContext加载进去,初始化spring容器
//        spring初始化的时候就会将容器中的所有组件初始化,这个时候对象已将创建
//        他是通过类的无参构造进行初始化的
        ClassPathXmlApplicationContext cxt = new ClassPathXmlApplicationContext("applicationContext.xml");
//        获取spring容器中的组件
//        方式有三种:
//            方式一:通过id获取,但是要强转
//        User user = (User) cxt.getBean("user");
//            方式二:通过id和类获取
        User user = cxt.getBean("user4", User.class);
        System.out.println(user);
//            方式三:通过class类获取,有个缺陷,加入spring中使用这个类创建了多个实例,就会冲突,找不到
        User bean = cxt.getBean(User.class);
        String[] beanDefinitionNames = cxt.getBeanDefinitionNames();
//        可以看到spring容器中所有的组件名字
        for(int i=0;i<beanDefinitionNames.length;i++){
            System.out.println(beanDefinitionNames[i]);
        }
    }
}  

  Spring创建实例的三种方式:

  1).构造器创建

    1.1.无参构造器(默认)

    1.2.有参构造

          具体使用参照下边的代码注释

          

          

  2).实例工厂

  3).静态工厂.

<!--通过构造器注入bean-->
    <bean class="com.xpl.model.User" id="user">
        <constructor-arg index="0" value="张三"/>
        <constructor-arg index="1" value="27"/>
    </bean>
    <!--结果-->
    <!--有参构造String name, int age-->
    <!--User{name='张三', age=27}-->
    <bean class="com.xpl.model.User" id="user1">
        <constructor-arg name="name" value="李四"/>
        <constructor-arg name="age" value="27"/>
    </bean>
    <!--结果-->
    <!--有参构造int age,String name-->
    <!--User{name='李四', age=27}-->
    <!--发现:走的是后边(有两个有参构造,第二个有参构造)-->
    <!--是因为通过有参构造,name属性赋值时候,执行参数相同的构造器的最后一个)-->
    <!--这个时候就需要使用参数中的index或者type来精准定位-->
    <!--注意不需要全都写,配合使用只要能定位到某个构造器就可以-->
    <bean class="com.xpl.model.User" id="user2">
        <constructor-arg name="name" index="0" value="王五"/>
        <constructor-arg name="age" value="27"/>
    </bean>
    <!--结果-->
    <!--有参构造String name, int age-->
    <!--User{name='王五', age=27}-->

<!--实例工厂创建--> <!--实例工厂需要实例化,所以先注入进来--> <bean class="com.xpl.model.UserFactory" id="userFactory"/> <!--指定实例工厂是哪一个,在指定工厂方法是哪一个--> <bean factory-bean="userFactory" factory-method="creatPeople" id="user3"/>

<!--静态工厂创建--> <bean class="com.xpl.model.UserStaticFactory" factory-method="creatPeople" id="user4"/>

  对象属性赋值:

   1).构造方法注入(上边已经演示过了参考)

   2).通过set方法注入

       基本数据类型:

       复杂数据类型:

        

<bean class="com.xpl.model.User" id="user">
        <!--基本数据类型-->
        <property name="name" value="赵六"/>
        <!--数组-->
        <property name="arr">
            <array>
                <value>1</value>
                <value>2</value>
                <value>3</value>
            </array>
        </property>
        <!--如果list中只有一个值也可以这样写-->
        <!--<property name="arr" value="1"/>-->
        <!--引用数据类型,引用上边的cat-->
        <property name="cat" ref="cat"/>
        <!--list-->
        <property name="list">
            <list>
                <value>5</value>
                <value>6</value>
                <value>7</value>
            </list>
        </property>
        <!--如果list中只有一个值也可以这样写-->
        <!--<property name="list" value="1"/>-->
        <!--map-->
        <property name="map">
            <map>
                <entry key="1" value="2"/>
                <entry key="2" value="2"/>
                <entry key="3" value="2"/>
            </map>
        </property>
        <property name="set">
            <set>
                <value>1</value>
                <value>2</value>
                <value>3</value>
            </set>
        </property>
        <property name="properties">
            <props>
                <prop key="1">1</prop>
                <prop key="2">2</prop>
                <prop key="3">3</prop>
            </props>
        </property>
   </bean>

  二)DI

  1. DI:中文名称:依赖注入

    2. 英文名称((Dependency Injection)

    3. DI 是什么?

      3.1 DI 和 IoC 是一样的

      3.2 当一个类(A)中需要依赖另一个类的对象时,把 B 赋值给 A 的过程就叫做依赖注入.(注入:就是给spring容器中的bean赋值的过程;当Bean中的某个属性是另一个Bean时,把这个Bean以属性的方式注

      入进去就是依赖注入,广义上描述他就是Aop,狭义上描述就是将一个Bean作为了另外一个Bean的属性)

//首先有一个bean,这个Bean就是下边Bean的一个属性   
  <bean class="com.xpl.model.User" id="user">     
     <property name="cat" ref="cat"/>
   </bean>    
    <bean class="com.xpl.model.Cat" id="cat">
        //这个Bean中的属性是一个Bean
       <property name="name" value="小白猫"/>
   </bean>
public class User {
      private Cat cat;
      private Properties properties;
  }

  public class Cat {
      private String name;
  }

  三)AOP  

    1.AOP:中文名称面向切面编程

    2.英文名称:(Aspect Oriented Programming)

    3.正常程序执行流程都是纵向执行流程

      3.1 又叫面向切面编程,在原有纵向执行流程中添加横切面

      3.2 不需要修改原有程序代码

        3.2.1 高扩展性

        3.2.2 原有功能相当于释放了部分逻辑.让职责更加明确.

    概念:(原理:动态代理)

    在程序原有纵向执行流程中,针对某一个或某一些方法添加通知,形成横切面过程就叫做面向切面编程.

    主要体现在事务处理,日志管理,权限控制,异常处理等方面,提高代码的可维护性。

 

    原有功能: 连接点, pointcut(在某个方法前织入,这个方法就叫连接点)

    增加的部分叫做通知(增强Advice)

      前置通知: 在切点之前执行的功能. before advice

      后置通知: 在切点之后执行的功能,after advice

      异常通知.throws advice

      环绕通知:

    所有切点+通知叫做切面.

    织入: 把切面嵌入到原有功能的过程叫做织入

    重要:spring声明式事务是基于aop实现的,事务一般是用在service上的,有了事务service中一旦出现异常就会回滚,

         所以不建议在service中使用try-catch,因为使用try-catch之后aop就捕获不到异常,声明式事务就失效了

  java原生动态代理:

public interface Calculate {  
    public int add(int a,int b);
    public int min(int a,int b);
}

public class Calculateimpl implements Calculate {
    @Override
    public int add(int a, int b) {
        return a+b;
    }

    @Override
    public int min(int a, int b) {
        return a-b;
    }
}

public class ProxyFactory {
    //创建代理对象
    public Object createMyCalculate(Object obj){
        //Proxy是java反射中的一个类  obj.getClass().getClassLoader()获取类加载器  实现的接口
        return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), new InvocationHandler() {
            @Override
            //代理的那个对象(传入的) 要处理的方法  传入的参数
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                System.out.println("star");
                //调用方法并执行
                Object invoke = method.invoke(obj, args);
                System.out.println("end");
                return invoke;
            }
        });
    }
}
public class Text {
public static void main(String[] args) {
ProxyFactory proxyFactory=new ProxyFactory();
Calculateimpl calculateimpl=new Calculateimpl();
Calculate calculate=(Calculate)proxyFactory.createMyCalculate(calculateimpl));
calculate.add(1,3);
}
}

  Spring中aop实现:

  XML方式配置:

/**
 * 定义advice
 */
public class Advice {
    public void before(){
        System.out.println("前");
    }
    public void mythrow(Exception e){
//        还需要配置xml才可以打印出异常信息
        System.out.println("异常"+e.getMessage());
    }
    public void  after(){
        System.out.println("后");
    }
    public void aftering(){
        System.out.println("aftering");
    }
    public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        System.out.println("执行环绕通知");
        System.out.println("环绕-前置");
//        返回值
        Object proceed = proceedingJoinPoint.proceed();
        System.out.println(proceed);
        System.out.println("环绕-后置");
        return proceed;
    }
}
public class Demo {
    public int min(int i,int j){
        return i+j;
    }
}
public class Text {
    public static void main(String[] args) {

        ClassPathXmlApplicationContext cxt = new ClassPathXmlApplicationContext("applicationContext.xml");
        Demo demo = cxt.getBean("demo", Demo.class);
        demo.min(1,5);
    }
}
<!--将要被增强的对象注入进来-->
<bean class="com.xpl.test.Demo" id="demo"/>
<!--将advice注入进来-->
<bean class="com.xpl.advice.Advice" id="advice"/>
<aop:config>
    <!--定义切点:就是要在哪个方法上增强-->
    <aop:pointcut id="min" expression="execution(int com.xpl.test.Demo.min(int ,int ))"/>
    <!--定义切面:切点+增强-->

    <!--引用的就是上边注入进来的增强Bean-->
    <aop:aspect ref="advice">
        
        <!--这几个增强是有顺序的特别是异常aftering和after-->
        <!--通知类型    增强方法名(增强类中的)    被增强的方法(上边定义的切点)-->
        
        <!--after和after-returning的区别:-->
                <!--after无论是否抛出异常都会执行-->
                <!--after-returning必须正确执行才会执行-->
        <aop:after method="after" pointcut-ref="min"/>
        <aop:after-returning method="aftering" pointcut-ref="min"/>
        <aop:after method="before" pointcut-ref="min"/>
        <!--必须和增强类中异常方法中参数的异常名相同-->
        <aop:after-throwing method="mythrow" pointcut-ref="min" throwing="e"/>
       
        <aop:around method="around" pointcut-ref="min"/>
    </aop:aspect>
</aop:config>

    通配符*

    在定义切点的时候可以使用*通配符精确定位切点

    他支持一级包名

<aop:pointcut id="min" expression="execution(int com.xpl.test.Demo.min(int ,int ))"/>

表示com包下的所有包中的所有方法
<aop:pointcut id="min" expression="execution(* com.*.*.*.*(* ,* ))"/>

   四)自动注入

  前提:Spring全局配置文件中

   看代码理解:

    两个类A和B需要交给Spring管理

    B中有个属性是对象A

    非自动注入:自己写自己的property给属性赋值,或使用ref

    自动注入:在bean标签上使用autowire属性

   原理:Byname去判断我需要注入的属性名在spring容器中是否存在id名称一样的,存在就直接注入给他,

      Bytype是去找class

      Constructor:需要实体类中有有参构造方法,并且参数名称要和xml中的name一样

public class B {
    private String name;
    private A a;

public class A {
    private String name;

 

没有自动注入
<
bean class="com.xpl.model.A" id="a"> <property name="name" value="aaa"/> </bean>--> <bean class="com.xpl.model.B" id="b"> <property name="name" value="bbbbb"/> <property name="A" ref="a"/> </bean>

自动注入 <bean class="com.xpl.model.A" id="a"> <property name="name" value="aaa"/> </bean> <bean class="com.xpl.model.B" id="b" autowire="byName"> <property name="name" value="bbbbb"/> </bean>

 

 

    也可以配置为全局的

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

 

五:加载配置文件

  注意:通过配置文件健在内容的时候要注意使用下边高亮部分

  原因是:实例化先后顺序造成的,以免在实例化完成之后加载配置文件就加载不进去了

db.driver=com.mysql.jdbc.Driver
db.username=root
db.password=root
db.url=jdbc:mysql:///test?useUnicode=true&characterEncoding=UTF-8

 

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

    <context:property-placeholder location="classpath:db.properties"/>
    <!--配置数据源-->
    <bean class="org.springframework.jdbc.datasource.DriverManagerDataSource" id="dataSource">
        <property name="driverClassName" value="${db.driver}"/>
        <property name="username" value="${db.username}"/>
        <property name="password" value="${db.password}"/>
        <property name="url" value="${db.url}"/>
    </bean>
    <!--创建sqlSessionFactory-->
    <bean class="org.mybatis.spring.SqlSessionFactoryBean" id="factory">
        <!--创建sqlSession需要有数据库连接,na那么就引用上边的数据源-->
        <property name="dataSource" ref="dataSource"/>
        <property name="typeAliasesPackage" value="com.xpl.model"/>
    </bean>
  //扫描配置mapper.xml文件
   <bean class="org.mybatis.spring.SqlSessionFactoryBean" id="sqlSessionFactory">      <property name="dataSource" ref="dataSource"/>      <property name="typeAliasesPackage" value="com.xpl.model"/>      <property name="mapperLocations">       <list>         <value>classpath*:com/xpl/mapper/*.xml</value>       </list>     </property>    </bean> <!--扫描器,加载mapper接口--> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">       //配置这一句就可以mapper接口和mapper.xml不写在一个文件夹了 <property name="basePackage" value="com.xpl.mapper"/> <property name="sqlSessionFactoryBeanName" value="factory"/> <!--<property name="sqlSessionFactory" ref="factory"/>--> </bean> </beans>

 

六:从配置文件中取值

people.name=xupeilei
两种方式,将bean交给Spring容器!!!这是关键,要想去spring容器中的全局的值,就一定要把这个Bean交给Spring管理!!!!!
方式一:直接配置进去

<
bean class="com.xpl.model.People" id="people"/>

方式二:通过包扫描
<context:component-scan base-package="com.xpl.model"/>

 

public class People {
  name这个属性名和取值时的name名没有必然关系,可以不一样 @Value(
"${people.name}") private String name;

 

七:Scope属性

  默认单例

八:声明式事务

  1.编程式事务:

    1.1 由程序员编程事务控制代码. 1.2 OpenSessionInView 编程式事务

  2.声明式事务:

    2.1 事务控制代码已经由 spring 写好.程序员只需要声明出哪些方法需要进行事务控制和如何进行事务控制.

  3.声明式事务都是针对于 Service 类下方法的.

  4.事务管理器基于通知(advice)的.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans 
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
    http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
    http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"
>                  <!--配置数据库链接--> <!--引入数据库连接信息--> <context:property-placeholder location="classpath:db.properties"/> <!--配置数据库里连接池--> <bean class="com.alibaba.druid.pool.DruidDataSource" id="dataSource"> <property name="url" value="${db.url}"/> <property name="username" value="${db.username}"/> <property name="password" value="${db.password}"/> </bean>
                   <!--配置mybatis--> <!--配置mapper--> <bean class="org.mybatis.spring.SqlSessionFactoryBean" id="sqlSessionFactory"> <property name="dataSource" ref="dataSource"/> <property name="typeAliasesPackage" value="com.xpl.model"/> <property name="mapperLocations"> <list> <value>classpath*:com/xpl/mapper/*.xml</value> </list> </property> </bean> <!--自动获取getXXX(mapper.xlass)--> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <!--获取那个接口 value就是上边配的SqlSessionFactoryBean--> <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/> <!--接口所在的文件夹 这里配置完了就不需要将接口和mapper文件放一个文件夹了--> <property name="basePackage" value="com.xpl.mappering"/> </bean>                   <!--配置事务--> <bean class="org.springframework.jdbc.datasource.DataSourceTransactionManager" id="dataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean> <tx:advice id="txAdvice" transaction-manager="dataSourceTransactionManager"> <tx:attributes> <tx:method name="add*"/> <tx:method name="upd*"/> <tx:method name="del*"/> <tx:method name="sel*"/>
       <tx:method name="*" read-only="true"/>  </tx:attributes> </tx:advice> <aop:config> <aop:pointcut id="pc1" expression="execution(* com.xpl.service.*.*(..))"/> <aop:advisor advice-ref="txAdvice" pointcut-ref="pc1"/> </aop:config> </beans>

 

九:事务传播行为

<tx:method name="add*" read-only="" propagation=""/>

 

  readonly=”boolean” 是否是只读事务.

     1 如果为 true,告诉数据库此事务为只读事务.数据化优化,会对性能有一定提升,所以只要是查询的方法,建议使用此数据.

     2 如果为 false(默认值),事务需要提交的事务.建议新增,删除,修改.

  propagation 控制事务传播行为.

    1当一个具有事务控制的方法被另一个有事务控制的方法调用后,需要如何管理事务(新建事务?在事务中执行?把事务挂起?报异常?)

      REQUIRED (默认值): 如果当前有事务,就在事务中执行,如果当前没有事务,新建一个事务.

      SUPPORTS:如果当前有事务就在事务中执行,如果当前没有事务,就在非事务状态下执行.

      MANDATORY:必须在事务内部执行,如果当前有事务,就在事务中执行,如果没有事务,报错.

      REQUIRES_NEW:必须在事务中执行,如果当前没有事务,新建事务,如果当前有事务,把当前事务挂起.

      NOT_SUPPORTED:必须在非事务下执行,如果当前没有事务,正常执行,如果当前有事务,把当前事务挂起.

      NEVER:必须在非事务状态下执行,如果当前没有事务,正常执行, 如果当前有事务,报错.

      NESTED:必须在事务状态下执行.如果没有事务,新建事务,常执行,如果当前有事务,把当前事务挂起.

十:事务隔离级别 

<tx:method name="add*" isolation="DEFAULT"/>

 

    脏读:

      一个事务(A)读取到另一个事务(B)中未提交的数据,另一个事务中数据可能进行了改变,此时 A事务读取的数据可能和数据库中数据是不一致的,此时认为数据是脏数据,读取脏数据过程叫做脏读

      解释:A从数据库读出一条数据(aaa),并修改为(bbb)没有提交只是flush到内存中,这时B读到了内存中的数据(bbb),但是数据库中数据依旧是(aaa),B读到的就是脏数据

.     不可重复读:

      主要针对的是某行数据.(或行中某列)

      主要针对的操作是修改操作.

      两次读取在同一个事务内

      当事务 A 第一次读取事务后,事务 B 对事务 A 读取的淑君进行修改,事务 A 中再次读取的数据和之前读取的数据不一致,过程不可重复读. 

      解释:张三盘点了仓库现存50吨大豆,然后他准备卖给特朗普,这时他老婆在他不知道的情况卖给了金三胖,张三合同签回来准备发货发现大豆没有了

    幻读:

      主要针对的操作是新增或删除

      两次事务的结果.

      事务 A 按照特定条件查询出结果,事务 B 新增了一条符合条件的数据.事务 A 中查询的数据和数据库中的数据不一致的,事务 A 好像出现了幻觉,这种情况称为幻读. 

  isolation=”” 事务隔离级别在多线程或并发访问下如何保证访问到的数据具有完整性的.

    DEFAULT:

      默认值,由底层数据库自动判断应该使用什么隔离界别

    READ_UNCOMMITTED: 可以读取未提交数据,可能出现脏读,不重复读,幻读.

       效率最高.

    READ_COMMITTED:只能读取其他事务已提交数据.可以防止脏读,可能出现不可重复读和幻读.

    REPEATABLE_READ: 读取的数据被添加锁,防止其他事务修改此数据,可以防止不可重复读.脏读,可能出现幻读.

    SERIALIZABLE: 排队操作,对整个表添加锁.一个事务在操作数据时,另一个事务等待事务操作完成后才能操作这个表.

      最安全的

      效率最低的.

十一:事务回滚

<tx:method name="add*"rollback-for="" no-rollback-for=""/>

 

   rollback-for=”异常类型全限定路径”

      当出现什么异常时需要进行回滚

      建议:给定该属性值.

        手动抛异常一定要给该属性值.

   no-rollback-for=””

      当出现什么异常时不滚回事务.

十二:注解

1. @Component 创建类对象,相当于配置<bean/>
2. @Service 与@Component 功能相同.

  2.1 写在 ServiceImpl 类上.

3. @Repository 与@Component 功能相同.

  3.1 写在数据访问层类上.

4. @Controller 与@Component 功能相同.

  4.1 写在控制器类上.

5. @Resource(不需要写对象的 get/set)(其实相当于对自动注入的补充:因为使用注解的方式auto就不生效了,但是我们还要在类中放入属性,就将这个类放进去)
  5.1 java 中的注解
  5.2 默认按照 byName 注入,如果没有名称对象,按照 byType 注入
    5.2.1 建议把对象名称和 spring 容器中对象名相同
6. @Autowired(不需要写对象的 get/set)
  6.1 spring 的注解
  6.2 默认按照 byType 注入.

7. @Value() 获取 properties 文件中内容
8. @Pointcut() 定义切点
9. @Aspect() 定义切面类
10. @Before() 前置通知
11. @After 后置通知
12. @AfterReturning 后置通知,必须切点正确执行
13. @AfterThrowing 异常通知
14. @Arround 环绕通知

十三:java配置类

  可以不使用applicationContext.xml来配置属性而是使用一个java类来替代

  @Configuration

  @Componentscan:默认扫描当前包及子包的子包。。

  @Componentscan(basePackages=“com.xpl.model”)设置扫描哪一个包

  @Bean

十四:多数据源

 

转载于:https://www.cnblogs.com/a103007/p/9755005.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值