02spring

一、概述

spring核心概念

  • IoC(核心中的核心):Inverse of Control,控制反转。对象的创建权力由程序反转给Spring框架。
  • DI:Dependency Injection,依赖注入。在Spring框架负责创建Bean对象时,动态的将依赖对象注入到
    Bean组件中!!
  • AOP:Aspect Oriented Programming,面向切面编程。在不修改目标对象的源代码情况下,增强IoC容器
    中Bean的功能。
  • Spring容器:指的就是IoC容器,底层也就是一个BeanFactory。

二、IOC

基于XML使用

IOC配置

bean实例化的三种方式

  • 第一种:使用默认无参构造函数(重点

    <bean id="userService" class="com.kkb.spring.service.UserServiceImpl/>
    
  • 第二种:静态工厂(了解

    实体类需创建createUserService的静态方法

    <bean id="userService" class="com.kkb.spring.factory.StaticFactory" factory-method="createUserService"></bean>
    
  • 第三种:实例工厂(了解

    实体类需创建createUserService的普通方法

    <bean id="instancFactory" class="com.kkb.factory.InstanceFactory"></bean>
        
    <bean id="userService" factory-bean="instancFactory" factory-
    method="createUserService"></bean>
    

DI依赖注入

  • 第一种:使用构造函数
<bean id="userService" class="com.kkb.spring.service.UserServiceImpl">
        <constructor-arg name="id" value="1"></constructor-arg>
        <constructor-arg name="name" value="zhangsan"></constructor-arg>
</bean>
  • 第二种:setter方法(重点

    //1.手动装配方式(XML方式)
    	- 需要配置bean标签的子标签property
    	- 需要配置的bean中指定setter方法。
    
    //2.自动装配方式(注解方式,后面讲解)
    	- @Autowired- 作用一:查找实例,从spring容器中根据Bean的类型(byType)获取实例。
      	- 作用二:赋值,将找到的实例,装配给另一个实例的属性值。
      	- 注意事项:一个java类型在同一个spring容器中,只能有一个实例
    	- @Resource- 作用一:查找实例,从spring容器中根据Bean的名称(byName)获取实例。
      	- 作用二:赋值,将找到的实例,装配给另一个实例的属性值。
    	- @Inject

    手动装配两种方式

    // 1.p名称空间注入数
    
    	//在schema的名称空间中加入该行:
        	xmlns:p="http://www.springframework.org/schema/p"
        //xml配置:
            <bean id="person" class="com.kkb.spring.demo.Person" p:pname="老王" p:car2-
    ref="car2"/>
    		<bean id="car2" class="com.kkb.spring.demo.Car2" />
    
    // 2. 依赖注入不同类型的属性
    
    	//简单类型(value)
    	<bean id="userService" class="com.kkb.spring.service.UserServiceImpl">
            <property name="id" value="1"></property>
            <property name="name" value="zhangsan"></property>
    	</bean>
            
        //引用类型(ref)
        <bean id="userService" class="com.kkb.spring.service.UserServiceImpl">
            <property name="userDao" ref="userDao"></constructor-arg>
    	</bean>
    	<bean id="userDao" class="com.kkb.spring.dao.UserDaoImpl"></bean>
            
        //集合类型(数组)
        <bean id="collectionBean" class="com.kkb.demo5.CollectionBean">
          <property name="arrs">
             <list>
             <!-- 如果集合内是简单类型,使用value子标签,如果是POJO类型,则使用bean标签 -->
                  <value>美美</value>
                  <value>小风</value>
             </list>
           </property>
        </bean>
        //如果是Properties集合的方式
        <property name="pro">
            <props>
                <prop key="uname">root</prop>
                <prop key="pass">123</prop>
            </props>
        </propert>
    

基于注解和XML混合使用

IOC配置

  • 第一步:spring配置文件中,配置context:component-scan标签

    // 第一种:扫描保证的注解
    <?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/beans 		 //需加
    		   http://www.springframework.org/schema/beans/spring-beans.xsd">  //需加
    <!--    自动扫描包中的注解-->
        <context:component-scan base-package="spring_01"/>  //需加
    </beans>
    
    
    // 第二种:声明加载的注解
    <?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">
    
        <bean class="org.springframework.context.annotation.CommonAnnotationBeanPostProcessor"/>
        <bean name="message" class="spring_01.test02.entity.Message">
            <property name="message" value="1111111"/>
        </bean>
    </beans>
    
  • 第二步:类上面加上注解@Component,或者它的衍生注解@Controller、@Service、@Repository

注意:

// IoC注解(创建对象)相当于
	<bean id="" class="">

DI依赖注入

注意:

//DI注解(依赖注入)相当于
	<property name="" ref="">
	<property name="" value="">    
1)注解介绍
  1. @Autowired

    • @Autowired默认按类型装配(byType)
    • @Autowired是由AutowiredAnnotationBeanPostProcessor类实现
    • @Autowired是spring自带的注解
    • @Autowired默认情况下要求依赖对象必须存在,如果需要允许null值,可以设置它的required属性为
      false,如:@Autowired(required=false)
    • 如果我们想按名称装配(byName)可以结合 @Qualifier 注解进行使用
  2. @Qualifier

    • 在自动按照类型注入的基础之上,再按照 Bean 的 id 注入。
    • 它在给字段注入时不能独立使用,必须和@Autowire 一起使用
    • 但是给方法参数注入时,可以独立使用。
  3. @Resource

    • @Resource默认按名称装配(byName),可以通过@Resource的name属性指定名称,如果没有指定name属性,当注解写在字段上时,默认取字段名进行按照名称查找,当找不到与名称匹配的bean时才按照类型进行装配

    • @Resource属于J2EE JSR250规范的实现

    • 但是需要注意的是,如果name属性一旦指定,就只会按照名称进行装配。

      推荐使用@Resource注解,因为它是属于J2EE的,减少了与spring的耦合。这样代码看起就比较优雅。

  4. @Inject

    • @Inject是根据类型进行自动装配的,如果需要按名称进行装配,则需要配合@Named
    • @Inject是JSR330中的规范,需要导入javax.inject.Inject;实现注入。
    • @Inject可以作用在变量、setter方法、构造函数上。
  5. @Value

    • 基本类型和String类型注入值

    • 可以使用占位符获取属性文件中的值。

      @Value(“${name})	//name是properties文件中的key
      private String name;
      

@Autowired、@Resource、@Inject区别

1. @Autowired是spring自带的,@Inject是JSR330规范实现的,@Resource是JSR250规范实现的,需要导入不
同的包
2. @Autowired@Inject用法基本一样,不同的是@Autowired有一个request属性
3. @Autowired@Inject是默认按照类型匹配的,@Resource是按照名称匹配的
4. @Autowired如果需要按照名称匹配需要和@Qualifier一起使用,@Inject@Name一起使用
2)改变Bean作用范围的注解
  • @Scope:指定 bean 的作用范围,相当于下面的配置:

    <bean id="" class="" scope="">
    
  • 属性:

    value:指定范围的值。取值:singleton prototype request session globalsession
    
3)生命周期相关注解
  • @PostConstruct
  • @PreDestroy

相当于:

<bean id="" class="" init-method="" destroy-method="">
  • @Scope
@Scope可选值描述
singleton在 spring 容器中的是单例,从容器中获取该 bean 时总是返回唯一的实例。不写时默认为 singleton
prototype每次获取 bean 时,都会生成一个新的对象,相当于 new 操作
request在一次 http 请求内有效(只适用于 web 应用)
session在一个用户会话内有效(只适用于 web 应用)
globalSession在全局会话内有效(只适用于 web 应用)
4)注解和XML的选择问题
  • 注解的优势:
    配置简单,维护方便(我们找到类,就相当于找到了对应的配置)。

  • XML 的优势:
    修改时,不用改源码。不涉及重新编译和部署。

  • Spring 管理 Bean 方式的比较:

    基于XML基于注解
    Bean定义@Component及衍生@Controller、@Service、@Repository
    Bean名称通过id或者name指定@Component(“name”)
    Bean注入p命名空间或者@Autowired@Resource
    Bean生命周期@PostConstruct 初始化@PreDestroy删除
    适合场景Bean来自第三方Bean的实现类由用户自己开发

基于纯注解使用

1 @Configuration

  • 作用:用于指定当前类是一个 spring 配置类, 当创建容器时会从该类上加载注解。 获取容器时需要使用 AnnotationApplicationContext(有@Configuration 注解的类.class)。

  • 属性:value,用于指定配置类的字节码文件

  • 注意事项:获取容器时需要使用AnnotationApplicationContext类,才可以加载@Configuration注解的类的字节码对象。相当于xml文件

2 @ComponentScan

  • 作用:用于指定 spring 在初始化容器时要扫描的包。和配置文件中的context:component-scan标签作用一样
  • 属性:basePackages:用于指定要扫描的包。和该注解中的 value 属性作用一样

3 @Bean

  • 作用:该注解只能写在方法上,@Bean 会自动把方法返回的结果加入ioc容器。同时将容器中的对象注入到方法参数中。

  • 属性:name:给当前@Bean 注解方法创建的对象指定一个名称(即相当于bean 标签的 id)。

    ​ initMethod:初始化方法

    ​ destroyMethod:销毁执行方法

  • @Bean 修饰的方法的参数:

    ​ 1.自动根据参数类型去容器中对象注入;
    ​ 2.如果类型有多个,就根据形参名称取容器找该名称对应的对象注入
    ​ 3.如果要根据指定名称在容器中找对象注入参数,需要用@Qualifier注解

4 @PropertySource

  • 作用:用于加载.properties 文件中的配置

  • 属性:value[],用于指定 properties 文件位置。如果是在类路径下,需要写上 classpath:

5 @Import

  • 作用:用于导入其他配置类,也就是建立各配置类与主配置类的关系。
  • 属性:value[]:用于指定其他配置类的字节码对象。
  • 注意事项:在引入其他配置类时,可以不用再写@Configuration 注解,也可以写

三、AOP

AOP简介

1)AOP介绍

特点
术语解释
  • Joinpoint(连接点)-------方法

    所谓连接点是指那些被拦截到的点。在spring中,这些点指的是方法,因为spring只支持方法类型的连接点
    
  • Pointcut(切入点)

    所谓切入点是指我们要对哪些Joinpoint进行拦截的定义
    
  • Advice(通知/增强)

    所谓通知是指拦截到Joinpoint之后所要做的事情就是通知.通知分为前置通知,后置通知,异常通知,最终通知,环绕
    通知(切面要完成的功能)
    
  • Introduction(引介)

    引介是一种特殊的通知在不修改类代码的前提下, Introduction可以在运行期为类动态地添加一些方法或Field
    
  • Target(目标对象)-----------

    代理的目标对象
    
  • Weaving(织入)

    是指把增强应用到目标对象来创建新的代理对象的过程
    
  • Proxy(代理)

    一个类被AOP织入增强后,就产生一个结果代理类
    
  • Aspect(切面)------------切点和通知集合

    是切入点和通知的结合,以后咱们自己来编写和配置的
    
  • Advisor(通知器、顾问)

    和Aspect很相似
    

2)AspectJ

  • AspectJ是一个Java实现的AOP框架,它能够对java代码进行AOP编译(一般在编译期进行),让java代码具
    有AspectJ的AOP功能(当然需要特殊的编译器)
  • 可以这样说AspectJ是目前实现AOP框架中最成熟,功能最丰富的语言。更幸运的是,AspectJ与java程序完全
    兼容,几乎是无缝关联,因此对于有java编程基础的工程师,上手和使用都非常容易。
    了解AspectJ应用到java代码的过程(这个过程称为织入),对于织入这个概念,可以简单理解为aspect(切
    面)应用到目标函数(类)的过程。
  • 对于织入这个过程,一般分为动态织入和静态织入,动态织入的方式是在运行时动态将要增强的代码织入到目
    标类中,这样往往是通过动态代理技术完成的,如Java JDK的动态代理(Proxy,底层通过反射实现)或者
    CGLIB的动态代理(底层通过继承实现),Spring AOP采用的就是基于运行时增强的代理技术
  • ApectJ采用的就是静态织入的方式。ApectJ主要采用的是编译期织入,在这个期间使用AspectJ的acj编译器
    (类似javac)把aspect类编译成class字节码后,在java目标类编译时织入,即先编译aspect类再编译目标
    类。

3)实现AOP原理

  • Spring AOP是通过动态代理技术实现的
  • 而动态代理是基于反射设计的。(关于反射的知识,请自行学习)
  • 动态代理技术的实现方式有两种:基于接口的JDK动态代理和基于继承的CGLib动态代理。

基于AspectJ的AOP使用

1)使用

​ 其实就是指的Spring + AspectJ整合,不过Spring已经将AspectJ收录到自身的框架中了,并且底层织入依然是采
取的动态织入方式。

切入点表达式
execution([修饰符] 返回值类型 包名.类名.方法名(参数))

说明

  • execution:必须要

  • 修饰符:可省略

  • 返回值类型:必须要,但是可以使用*通配符

  • 包名 :

    ** 多级包之间使用.分割
    ** 包名可以使用*代替,多级包名可以使用多个*代替
    ** 如果想省略中间的包名可以使用.
    
  • 类名

    ** 可以使用*代替
    ** 也可以写成*DaoImpl
    
  • 方法名:

    ** 也可以使用*好代替
    ** 也可以写成add*
    
  • 参数:

    ** 参数使用*代替
    ** 如果有多个参数,可以使用 ..代替
    
通知类型

通知类型(五种):前置通知、后置通知、最终通知、环绕通知、异常抛出通知。

  • 前置通知

    	* 执行时机:目标对象方法之前执行通知
        * 配置文件:<aop:before method="before" pointcut-ref="myPointcut"/>
        * 应用场景:方法开始时可以进行校验
    
  • 后置通知

    	* 执行时机:目标对象方法之后执行通知,有异常则不执行了
        * 配置文件:<aop:after-returning method="afterReturning" pointcut-ref="myPointcut" returning="result"/>
        * 应用场景:可以修改方法的返回值
    
  • 最终通知:

    	* 执行时机:目标对象方法之后执行通知,有没有异常都会执行
        * 配置文件:<aop:after method="after" pointcut-ref="myPointcut"/>
        * 应用场景:例如像释放资源
    
  • 环绕通知(很强大,可以直接代替其他四个通知):

       	* 执行时机:目标对象方法之前和之后都会执行。方法执行前后分别执行,可以阻止方法的执行,必须手动执行目标方法
        * 配置文件:<aop:around method="around" pointcut-ref="myPointcut"/>
        * 应用场景:事务、统计代码执行时机
    
  • 异常抛出通知:

     	* 执行时机:在抛出异常后通知
        * 配置文件:<aop:after-throwing method=" afterThrowing " pointcut- 
    ref="myPointcut"/>
        * 应用场景:包装异常
    

2)XML实现

在pom.xml导入依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>groupId</groupId>
    <artifactId>spring-action</artifactId>
    <version>1.0-SNAPSHOT</version>
             
    <dependencies>
        <!--        aspect依赖-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aspects</artifactId>
            <version>5.0.7.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>aopalliance</groupId>
            <artifactId>aopalliance</artifactId>
            <version>1.0</version>
        </dependency>
    </dependencies>
</project>
xml配置
<?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: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/aop
	    http://www.springframework.org/schema/aop/spring-aop.xsd">

    <aop:aspectj-autoproxy expose-proxy="true"/>

    <bean id="customer" class="spring_02.test01.entity.CustomImpl"/>
    <bean id="aspect" class="spring_02.test01.entity.Aspect"/>

    <aop:config>
        <aop:aspect id="logAspect" ref="aspect">
<!--            <aop:pointcut id="aspectBefore" expression="execution(* spring_02.test01.entity.Custom.addCustomer(..))"/>-->
<!--            <aop:before method="logBefore" pointcut-ref="aspectBefore"/>-->
<!--           前置通知 -->
            <aop:before method="logBefore" pointcut="execution(* spring_02.test01.entity.Custom.addCustomer(..))"/>
<!--           最终通知,异常也执行-->
            <aop:after method="logAfter" pointcut="execution(* spring_02.test01.entity.Custom.addCustomer(..))"/>
<!--            后置通知,异常不执行-->
            <aop:after-returning method="logAfterReturning"
                                 pointcut="execution(* spring_02.test01.entity.Custom.addCustomerReturnValue(..))"
                                 returning="result1"/>
<!--            异常抛出通知,抛出异常后通知-->
            <aop:after-throwing method="logAfterThrowing"
                       pointcut="execution(* spring_02.test01.entity.Custom.addCustomerThrowException(..))"
                       throwing="error"/>
<!--            环绕通知-->
            <aop:around method="logAround"
                       pointcut="execution(* spring_02.test01.entity.Custom.addCustomerAround(..))"/>

        </aop:aspect>
    </aop:config>
</beans>

3)注解实现

在pom.xml导入依赖(同上)
注解替换
  • @Aspect:作用是把当前类标识为一个切面供容器读取

    <aop:aspect id="logAspect" ref="aspect"/>
    
  • @Before(value = “execution(* spring_02…CustomerBo.addCustomer(…))”)

    @After(value = “LoggingAspect.com()”)

    @AfterReturning(pointcut = “LoggingAspect.com()”, returning = “result”)

    @AfterThrowing(pointcut = “LoggingAspect.com()”, throwing = “error”)

    @Around(value = “LoggingAspect.com()” )

    @Pointcut(value = “execution(* spring_02.test02.entity.CustomerBo.*(…))”) #通用的切入点

    <!--           前置通知Before -->
    <aop:before method="logBefore" pointcut="execution(* spring_02..Custom.addCustomer(..))"/>
    
    <!--           最终通知,异常也执行After-->
     <aop:after method="logAfter" pointcut="execution(* spring_02..Custom.addCustomer(..))"/>
    
    <!--            后置通知,异常不执行AfterReturning-->
    <aop:after-returning method="logAfterReturning"
         pointcut="execution(* spring_02..Custom.addCustomerReturnValue(..))"
         returning="result1"/>
    
    <!--            异常抛出通知,抛出异常后通知AfterThrowing-->
    <aop:after-throwing method="logAfterThrowing"
         pointcut="execution(* spring_02..Custom.addCustomerThrowException(..))"
         throwing="error"/>
    
    <!--            环绕通知Around-->
    <aop:around method="logAround"
             pointcut="execution(* spring_02..Custom.addCustomerAround(..))"/>
    
  • @EnableAspectJAutoProxy 开启aspect注解

    <aop:aspectj-autoproxy expose-proxy="true"/>
    
实现
  • config配置

    @Configuration
    @ComponentScan(basePackages = "spring_02.test02")
    @EnableAspectJAutoProxy
    
  • 切面

    @Aspect
    @Component
    public class LoggingAspect {
        @Before(value = "LoggingAspect.com()")
        public void logBefore(JoinPoint joinPoint) {
        ...
        }
    
  • 测试单元

    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(classes=Config.class)
    public class Test {
    
        @Resource
        private CustomerBo customerBo;
    
        @org.junit.Test
        public void test(){
            customerBo.addCustomer();
            System.out.println("==============");
       }
    }
    

四、组件支撑篇

整合Junit

1)单元测试实现过程

  • 第一步:添加依赖

    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>RELEASE</version>
        <scope>compile</scope>
    </dependency>
    
  • 第二步:测试类

    package spring_02.test02.test;
    
    import org.junit.runner.RunWith;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.annotation.AnnotationConfigApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    import org.springframework.test.context.ContextConfiguration;
    import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
    import spring_02.test02.entity.Config;
    import spring_02.test02.entity.CustomerBo;
    import spring_02.test02.entity.CustomerBoImpl;
    
    import javax.annotation.Resource;
    
    /**
     * @Author monkey
     * @Date 2021/11/10 14:19
     */
    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(classes=Config.class)    //config配置类
    //@ContextConfiguration(locations="classpath:xxx.xml")    //xml配置文件
    public class Test {
    
        @Resource
        private CustomerBo customerBo;
    
        @org.junit.Test
        public void test(){
            System.out.println("==============");
        }
    }
    
    

事务支持

1)事务介绍
  • 事务特征(ACID):原子性,一致性,隔离性,持久性

  • 事务隔离级别

    -1 **原子性(atomicity)** :事务最小工作单元,要么全成功,要么全失败 。 
    -2 **一致性(consistency)**: 事务开始和结束后,数据库的完整性不会被破坏 。 
    -3 **隔离性(isolation)** :不同事务之间互不影响,四种隔离级别为RU(读未提交)、RC(读已提 交)、RR(可重复读)、SERIALIZABLE (串行化)。 
    -4 **持久性(durability)** :事务提交后,对数据的修改是永久性的,即使系统故障也不会丢失
    
2)事务相关接口和分类
3)事务xml实现
4)事务xml与注解混合使用
5)事务基于AspectJ纯注解使用
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值