Spring入门学习

一、Spring介绍

Spring是一个开源框架。并且是一个轻量级的框架,能够一站式的分层部署项目。能够整合现在主流框架起到一个粘合剂的作用。

轻量级
   空间占用角度:
        spring的核心包不到1MB,占用计算机的资源特别小
   对容器的依赖角度:
        对容器依赖性越低 越轻量


二、IOC

1、概念
    IOC就是控制反转将对象创建的权利交给Spring容器来管理。由容器来管理对象的生命周期。
    
2、SpringIOC的实现步骤:
    ★导入相关的JAR包
    ★编写实体类
    ★编写配置文件(1.编写配置文件的头    2.编写对象的具体映射关系)
    ★启动spring容器
    ★通过容器获取对象
    ★调用对象的方法完成相应的功能
    
3、SpringIOC的原理
    ★控制反转的过程:
        Spring容器在启动的时候,先去读取applicationContext.xml配置文件(读取顺序是按行读取)。
        每当读取到一个bean的时候就会按照bean中的class属性依据反射的方法创建出来对象,把创建
        出来的对象当做value值存储到MAP中,bean的ID当做Map中的key形成键值对的形式,保存到
        Spring容器中,方便以后调用。
    ★对象获取的方法
        a.通过bean中的id能够获取对象
            context.getBean("hello");
        b.通过class属性来获取
            Hello hello = context.getBean(Hello.class);
        注意:
            a.对象获取的时候尽量使用ID,不要用class,可能会由于类型不唯一报错。
            b.如果bean中的ID重复,那么Spring在创建对象时保存到map中的时候就会报错。会报ID已经存在的错误。
        原因:已经存在的bean不能被修改。

三、Spring bean中的属性

1、别名标签
    <alias name="TareneHello" alias="你好1607"/>
    
2、对象的单例和多例
    单例对象:spring容器内部只有一份
    ★Spring容器内部默认维护了一个单例对象。
    ★scope="prototype"
        当scope属性为prototype时根据bean生成的对象就是多例对象。
    ★scope="singleton"
        当scope属性为singleton和默认不写的时候对象创建都是单例的。
    使用场景:
        购物车需要是多例的,否则会造成混论。
    ★懒加载问题
        说明:理想状态下,我们需要什么对象容器帮我们生产什么对象,这是最合理的,这样做既能满足需求又能减少计算机压力
        
    ★什么是懒加载:
        懒加载就是在容器启动的时候不会创建对象,当通过容器getBean()的时候才会创建对象。这样做能实现最理想的状态。
    ★lazy-init="true" 实现懒加载
        lazy-init="false" 立即加载
        如果默认不写 也是立即加载
    ★全局的懒加载配置
        default-lazy-init="true" 就能实现懒加载
        default-lazy-init="false/default" 立即加载
        当bean中的懒加载为default 应该与全局的懒加载配置保持一致。
     ★自定义的初始化和销毁方法
        init-method="init" destroy-method="destroy"
        自定义的初始化和销毁可以手动配置。并且执行。

3、DI(依赖注入)
     可以通过Spring容器可以动态的注入属性
     依赖注入可以为简单类型赋值,也可以为引用类型赋值。
     但是前提条件是属性必须添加setXXX方法。如果没有set方法则不能实现注入。

四、SpringIOC和DI的意义

1、如果在架构中web、service、dao 应该尽可能的保持松耦合。如果各层之间紧耦合对于后期代码的维护,相当困难。
 
2、Spring可以通过配置文件的形式。动态的实现松耦合。如果将来具体的实现类发生了改变。只需要修改配置文件即可。无需手动
修改代码。提高了代码的开发效率和维护效率。并且其中所有的注入都是面向接口的,这样做能最大程度保证代码的灵活性。

五、自动的装配过程

如果类中的属性是引用类型,并且配置文件中有相应baen的配置。则能进行自动的装配。(自动的注入)
1、autowired
    ★spring中可以通过autowire属性实现自动装配。将来不需要手动的在写property能够节省代码。
    ★使用装配过程必须添加set方法。否则装配失败 对象属性为null。
        
2、装配的原理
    ★autowire="byName"
      使用spring在进行装配的时候会先检查所有的set方法
      setStudent====>student======>拿到student以后会根据bean中的ID进行匹配。如果匹配成功则能正确的注入。如果
匹配不成功则为null。
    
    ★autowire="byType"
      使用spring在进行装配的时候会先检查所有的set方法
      setStudent====>student===>拿到对应的Class形式====>根据bean中的class类型进行匹配。如果匹配成功则能正确注入。
        

六、类的注解

1、开启类扫描
    <context:component-scan base-package="domain"/>
    说明:开启类扫描以后会自动的扫描给定的包及其子包,如果是多个包之间用“,”号隔开
    
2、@Component注解使用的原理
    ★首先Spring在进行xml解析时 会解析包扫描的标签。根据标签指定的包进行扫描。然后会到指定的包下查找那些类上
有@Component注解,找到相应的注解后,会给这个类创建一个对象,创建好对象之后存入MAP中,会根据类的名称生成相应
的ID(首字母小写其他不变),当作KEY存入map中。
        
    ★ID生成的原则
      如果第二个字母是大写的   ABcc  ==> 转化以后的ID就是ABcc
      如果第二个字母小写    Abcc====>转化以后ID就是abcc
    ★@Value注解
      @Value注解可以注入字符串和基本类型只需要将注入的值写到
      @Value(value="张三")即可。就能完成注入。
      如果属性值只有value那么value可以省略不写。
    
3、复杂类型的注入
    父类类型的注入需要引入一个util这样的标签
    <util:map id="map">
        <entry key="1" value="一"></entry>
        <entry key="2" value="TOM猫"></entry>
        <entry key="3" value="Jerry老鼠"></entry>
    </util:map>
    要指明map的ID 这个ID就是通过@Value("#{@ID}") ID应该保持一致。

4、动态数据注入---引入外部配置文件
    <context:property-placeholder location="classpath:/tom.properties"/>
    原理说明:
    spring进行解析的时候会根据指定的路径扫描对应的配置文件,扫描完成以后将配置文件的键值对进行保存。保存到spring
容器中。需要使用的时候通过@Value("${key}")来获取相应的value值,实现了动态的注入效果。
    
5、类扫描的包容性
    在开启类扫描的时候,会默认的开启属性注解。所以属性注解可以省略。
    
6、类的注解指明ID
    @Component(value="TomDao")
    说明:使用这个注解的时候默认的条件下会根据类的名称按照首字母小写,自动的生成相应的Bean的ID,如果有value值,
那么就会按照value指定的名称当做bean的ID
    
7、Spring的分层标识的注解
    @Repository(value="TomDao")    dao层
    @Service("TomService")                 service层
    @Controller                                        控制层
    说明:Spring为了满足分层的需要 发明了三个注解 分别代码不同的层级        

七、SpringAOP(面向切面编程)

1、名词解释
    ★切面(Aspect):一个关注点的模块化,这个关注点可能会横切多个对象。
      一个切面就是在完成目标方法后再执行其操作的程序代码
    ★连接点(Joinpoint):在程序执行过程中某个特定的点
      就是客户端调用的目标方法。
    ★通知(Advice):在切面的某个特定的连接点上执行的动作。
      就是切面中的方法。
    ★切入点(Pointcut):匹配连接点的断言
      切入点就是一个匹配切面的过程
    ★目标对象(Target Object): 被一个或者多个切面所通知的对象。
      就是真正执行目标方法的对象
    ★织入(Weaving):把切面连接到其它的应用程序类型或者对象上,并创建一个被通知的对象。
      形成切面的过程就是织入
        
2、AOP的入门
    步骤:
        ★配置头文件 导入约束
          xmlns:aop="http://www.springframework.org/schema/aop"
        ★导入相关的开发jar包
        ★配置自定义的切面
        ★xml配置的顺序
          Content Model : (pointcut*, advisor*, aspect*)
          <aop:config>
              <!--配置切入点  -->
              <aop:pointcut expression="within(service.*)" id="pc"/>
              <aop:aspect ref="myAspect">
              <!--配置通知的方法  -->
              <aop:around method="around" pointcut-ref="pc"/>
              </aop:aspect>
          </aop:config>
    
3、AOP的原理
    当创建对象的时候首先spring和和切入点表达式进行匹配。如果匹配成功。则创建代理对象。我们客户端拿到代理对象
后看上去和目标对象一模一样。调用目标对象执行方法。就会执行切面中的通知(方法)。利用代理对象完成一些额外的操作,
最终执行目标方法。
    
4、通知的类型
    ★环绕通知(Around Advice):在目标方法执行之前。执行之后都需要执行额外操作的通知。
    ★前置通知(Before advice):在目标方法执行之前的操作。
    ★后置通知(After returning advice):在目标方法执行之后执行的通知
    ★异常通知(After throwing advice):在执行目标方法时,如果目标方法报错就会被异常通知拦截,这时异常通知才会执行。
    ★最终通知(After (finally) advice):不管如何都会执行最终通知。
    
5、异常的处理
    在Spring中异常的try--catch不能随便加,如果添加了try-catch那么spring容器就捕获不到。不能做出正确的处理。
如果想写try-catch那么异常捕获时要具体指明某一类的异常 不能使用Exception,因为这个异常捕获能力太强。
        
6、通知的处理顺序
    当目标方法执行抛出异常时 异常通知会被执行,后置通知不会被调用。
    
7、通知的使用场景
    ★环绕通知:我是不需要目标方法执行,并且执行前后有必要的操作。
    ★前置通知:日志收集 前置通知执行不能影响目标方法是否被执行 与它毫无关系。
    ★后置通知:如果需要对目标方法的返回值结果做操作 可以使用后置通知。通知通知也不能影响目标方法的执行。
    ★异常通知:可以对异常做收集 以后使用异常通知。
    ★最终通知:可以用来关闭一些链接或者释放资源。
    
8、通知中的参数
    除了环绕通知之外其他的通知都是JoinPoint。并且所有的参数都必须位于第一位。
    而环绕通知中 必须添加ProceedingJoinPoint 因为 只有ProceedingJoinPoint类中有proceed方法。才能让目标方法执行。
        
9、关于表达式的写法
    within(service.*)
    它是一个类级别的表达式,可以按照类型来匹配。匹配的规则包名+类名。
    如果想匹配该包下的所有子类 用*代替。 如果想匹配该包下的所有子孙类用..*表示。
    execution(返回值结果 包名.类名.方法名(参数名))
    execution(* service..*(..))
    表达式创建代理对象的原理:只有满足表达式要求的才会被创建代理对象,能够精确到方法和参数级别。

八、Spring和JDBC整合
    

1、第一步导入jar包
    
2、配置数据源
    <!--spring和JDBC进行整合  -->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="${c3p0.driver}"></property>
        <property name="jdbcUrl" value="${c3p0.url}"></property>
        <property name="user" value="${c3p0.user}"></property>
        <property name="password" value="${c3p0.password}"></property>
    </bean>
    
3、配置JDBCTemplate
    这个是jdbc模板类,可以通过Spring为我们提供的版本进行快速的增删改操作。不需要像原生的jdbc那样复杂的代码。
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <!--配置数据源  -->
        <property name="dataSource" ref="dataSource"></property>
    </bean>
        
4、模板类的使用
    JdbcTemplate jdbcTemplate = (JdbcTemplate) context.getBean("jdbcTemplate");
    String sql = "insert into user values(null,?,?)";
    int row = jdbcTemplate.update(sql, "白骨精",5000);
    System.out.println("影响的行数"+row);
        
    说明:模板类自动的会使用预编译的方式。保证数据的安全。
    使用预编译时 参数用“?”代替。具体的参数赋值 在执行模板方法时指定
    jdbcTemplate.update(sql, "白骨精",5000);
    所有的增删改操作 都用jdbcTemplate.update(sql,arg0,arg1);
    
5、JDBC模板类中的查询方法
    通常情况下 查询的结果结通过List进行封装。每一个list中的元素都是一个对象(实体类对象),而原始的模板对象
    方法jdbcTemplate.queryForList(sql);返回一个List<Map<key,value>>的形式 这样不符合我们的习惯。并且处理起来很麻烦。
    
6、说明
    虽然jdbcTemplate在使用上比jdbc原生的简单。可是在现实的开发中几乎不用。
 
7、Spring的声明式的事务处理
    ★可以指定具体的方法来控制事务。例如增删改 添加事务,而查询方法和其他方法都不需要事务。
    ★只要在Spring中使用了声明式的事务处理,将来所有的事务都不需要程序员自己维护。spring会非常智能帮你维护数据库事务。
    
    分析:
    问题:如果控制事务。
    专门的事务管理器。专门负责数据源的管理。
 
    步骤:
        ★修改配置文件的头
        ★配置事务管理器
        <!--事务管理器的id 默认都叫 transactionManager  -->
            <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
                <property name="dataSource" ref="dataSource"></property>
            </bean>
        ★配置事务通知
            <!-- method  name="事务指定的方法"
            propagation = REQUIRED (必须的)    将来执行addUser方法的时候就是添加事务。
            propagation="SUPPORTS" 事务可有可无。
            read-only="true"  spring会自动优化 查询效率更高
            -->
            <tx:method name="update*" propagation="REQUIRED"/>
            <tx:method name="find*" propagation="SUPPORTS" read-only="true"/>
            <tx:method name="*" propagation="SUPPORTS"/>
        ★配置切面
            <aop:config>
                    <aop:pointcut expression="execution(* service..*(..))" id="pc"/>
                    <aop:advisor advice-ref="tx" pointcut-ref="pc"/>
            </aop:config>
 
8、传播属性
    propagation="REQUIRED"
    propagation="SUPPORTS"
    实现事务的传播属性REQUIRED,可以做到多表操作时事务的一致性。
    propagation="SUPPORTS"
    如果一直操作有事务。那么当执行find()时,这个方法也会添加事务。
    
9、事务的回滚策略
    ★当程序执行遇到运行时异常时 事务会回滚。
    ★当程序执行遇到检查异常时 事务不会回滚
    ★修改回滚策略
    rollback-for="java.sql.SQLException"  遇到那种异常 事务回滚
    no-rollback-for="java.lang.Exception" 遇到所有的异常都不回滚

欢迎大家和帝都的雁积极互动,头脑交流会比个人埋头苦学更有效!共勉!

公众号:帝都的雁

  • 3
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值