您的位置:首页 > 编程语言 > Java开发

Spring--基础入门开发

2019-06-13 13:18 169 查看

spring基于XML的IOC环境搭建和入门

ApplicationContext的三个实现类

  • ClassPathXmlApplicationContext 加载类路径的配置文件, 要求配置文件必须在类路径下
  • FileSystemXmlApplicationContext 加载磁盘任意路径的配置文件(必须有访问权限)
  • AnnotationConfigApplicationContext 用于读取注解创建容器的

接口BeanFactory和接口ApplicationContext的区别

  • ApplicationContext: 它在构建核心容器时, 创建对象采取的策略是采用立即加载的方式, 也就是说,只要一读取完配置文件马上就创建配置文件中配置的对象。 适用于单例对象。

  • BeanFactory: 它在构建核心容器时, 创建对象采取的策略是延迟加载的方式, 也就是说,什么时候根据id获取对象了什么时候才真正的创建对象。 适用于多例对象。 BeanFactory是个顶层接口, 功能不完善。 实际项目中采用ApplicationContext此接口来定义容器对象

spring中bean的细节之三种创建Bean对象的方式

spring 对bean的管理细节

创建Bean的三种方式:

  1. 第一种:使用默认构造函数创建.在spring的配置文件中使用bean标签,配以id和class属性之后,且没有其他属性和标签时采用的就是默认构造函数创建bean对象,
    此时如果类中没有默认构造函数,则对象无法创建
<bean id="accountService" class="com.qqlindy.Service.impl.AccountServiceImpl"></bean>
  1. 第二种: 使用普通工厂中的方法创建对象(使用某个类中的方法创建对象, 并存入Spring容器)。
<bean id="instanceFactory" class="com.qqlindy.factory.InstanceFactory"></bean>
<bean id="accountService" factory-bean="instanceFactory" factory-method="getAccountService"></bean>
  1. 第三种: 使用工厂中的静态方法创建对象(使用某个类中的静态方法创建对象, 并存入Spring容器)。
<bean id="accountService" class="com.qqlindy.factory.StaticFactory" factory-method="getAccountService"></bean>

第二种, 第三种,配置方法解决了某个第三方提供的jar包某个方法的返回值存入Spring容器。

Bean对象的作用范围

Spring容器默认创建的对象都是单例的。 通过bean标签的scope属性, 它的作用:用于指定bean的作用范围。
它的取值: singleton : 单例的(默认值)
prototype: 多例的
request: 作用于web应用的请求范围
session 作用于web应用的会话范围
global-session 作用于集群环境的会话范围(全局会话范围), 当不是集群环境时,它就是session .

Bean对象的生命周期

单例对象 出生(当容器创建时对象出生),活着(当容器创建时对象出生), 死亡(当容器销毁时对象消亡)
多例对象 出生(当我们使用对象时spring容器为我们创建),活着(对象只要在使用过程中就一直活着),死亡(当对象长时间不用,且没有别的对象引用时, 由Java的垃圾回收机制回收)

spring的依赖注入

依赖注入: Dependency Injection
IOC的作用: 降低程序见的耦合(依赖关系),依赖关系的管理以后都交给spring来管理, 在当前类需要用到其他类的对象,由spring为我们提供,我们只需要在配置文件中说明。

依赖关系的维护:就称之为依赖注入。
依赖注入:能注入的数据有三类。
基本类型和String.
其他bean类型(在配置文件中或者注解配置过的bean)
复杂类型/集合类型

注入的方式有三种:
第一种:使用构造函数提供
第二种:使用set方法提供
第三种:使用注解提供

构造函数注入 标签constructor-arg

使用构造函数注入:
使用的标签是constructor-arg,在bean标签的内部,
constructor-arg标签中的属性:
type: 用于指定要注入的数据的数据类型,该数据类型也是构造函数中某个或某些参数的类型
index:用于指定要注入的数据给构造函数中指定索引位置的参数赋值。索引的位置从0开始
name: 用于指定给构造函数中指定名称的参数赋值 常用这个就能具体指定参数
以上三个参数用于指定给构造函数中哪个参数赋值

value: 用于提供基本类型和String类型的数据
ref: 用于指定其他的bean类型数据,它指的就是在spring的IOC容器中出现过的bean对象.  引用关联的bean对象

优点:在获取bean对象时,注入数据是必须的操作,否则对象无法创建成功
缺点:改变了bean对象的实例化方式, 是我们在创建对象时,如果用不到这些数据,也必须提供。

set方法注入 标签property

set方法注入 更常用的方式
使用的标签是property,在bean标签的内部
property标签中的属性:
name: 用于指定注入时所调用的set方法名称,且第一个字母小写
value: 用于提供基本类型和String类型的数据
ref: 用于指定其他的bean类型数据,它指的就是在spring的IOC容器中出现过的bean对象. 引用关联的bean对象

优点:创建对象时没有明确的限制,可以直接使用默认构造函数
缺点:如果有某个成员必须有值,则获取对象是有可能set方法没有执行

复杂类型/集合类型是需要借助其他标签的

注入集合数据

用于给List结构集合注入的标签 list array set
用于给Map结构集合注入的标签 map props
总结:结构相同,标签可以互用

Spring基于注解的IOC以及IOC的案例

Spring中ioc的常用注解
常用IOC注解按照作用分类


用于创建对象的注解: 他们的作用和XML配置文件中编写一个

<bean></bean>
标签实现的功能是一样的

用于注入数据的注解 他们的作用和XML配置文件中

<bean>
标签中编写一个
<property></property>
实现的功能是一样的

用于改变作用范围的注解 他们的作用和

<bean>
标签中编写scope属性功能是一样的

和生命周期相关的注解 他们的作用和

<bean>
标签中使用init-method和destroy-method的功能是一样的

用于创建对象的注解
用于创建对象的Component注解 : 作用: 用于把当前对象存入spring容器中。
属性: value:用于指定bean的id。 当我们不写时,它的默认值是当前类名,且首字母小写。

<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 https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">

<!--告知spring在创建容器时需要扫描的包,配置所需要的标签不是在beans约束中,而是一个名称为context名称空间和约束中-->

<context:component-scan base-package="com.qqlindy.Service"></context:component-scan>

Controller Service Repository
这三个注解他们的作用和属性与Component 是一模一样。 他们三个是spring框架为我们提供的三层使用注解, 使得我们的三层对象更加清晰。 Controller一般用于表现层。 Service 一般用于业务层。 Repository 一般用于持久层。

用于注入数据的注解
Autowired : 作用是自动按照类型注入。
只要容器中有唯一的一个bean对象类型和要注入的变量类型匹配,就可以注入成功。 出现位置可以是变量上,也可是方法上;
在使用注解注入时,set方法就不是必须的了。

如果容器中没有一个bean对象类型和要注入的变量类型匹配,则报错。

如果容器中有多个bean对象类型和要注入的变量类型匹配, 首先按照类型找到匹配的对象们, 接下来会使用变量名的名称作为bean的id在匹配的对象们里查找, 如果有一样的, 则注入成功,如果没有,则报错。

Qualifier: 作用是按照类中注入的基础之上再按照名称注入。 它给类成员注入时不能单独使用(必须和Autowired一起使用),但是给方法参数注入时可以。
属性: value: 用于指定注入bean的id。

Resource : 直接按照bean的id注入。它可以独立使用。
属性: name: 用于指定注入bean的id。

以上三个注入注解Autowired,Qualifier, Resource 都只能注入其他bean类型的数据,而基本类型和String类型无法使用上述注解实现。 另外, 集合类型的注入只能通过xml来实现。

基本类型和String类型使用@Value注解注入。
value: 用于注入基本类型和String类型的数据。
属性: value: 用于指定数据的值。 它可以使用spring中的SpEL(也是就spring的EL表达式), SpEL的写法: ${表达式}

用于改变作用范围的注解
Scope 作用用于指定bean的作用范围。
属性: value: 用于指定范围的取值。 常用取值: singleton prototype . 不写,默认时单例。

和生命周期相关的注解 了解
PreDestroy 用于指定销毁方法
PostConstruct 用于指定初始化方法

spring的新注解-Configuration和ComponentScan

/**

  • 该类是一个配置类,它的作用和bean.xml是一样的
  • spring中的的新注解
  • Configuration
  • 作用:指定当前类是一个配置类
  • ComponentScan
  • 作用:用于通过注解指定spring在创建容器时要扫描的包
  • 属性: value 和 basePackages的作用都是一样的,都是用于指定创建容器时要扫描的包
  • 使用此注解等于在xml中配置了 <context:component-scan base-package=“com.qqlindy”></context:component-scan>
  • com.qqlindy 这个路径应该是个类路径
  • @ComponentScan(basePackages = {“com.qqlindy”}) 标准写法是个数组,但是注解属性的值有且只有一个可以把数组括号去掉
    */
    @Configuration
    @ComponentScan(basePackages = {“com.qqlindy”})
    public class SpringConfiguration {
    }

spring的新注解-Bean

  • 作用:用于把当前方法的返回值作为bean对象存入spring的IOC容器中
  • 属性:用于指定bean的id. 当不写时,默认值是当前方法的名称
  • 细节:当我们使用注解配置时,如果方法有参数,spring框架会去容器中查找有没有可用的bean对象。
  • 查找的方式和Autowired注解的作用是一样的(自动按照类型匹配,如果有唯一的类型匹配就注入,如果没有匹配时就报错, 如果有多个类型匹配时, 首先按照类型找到匹配的对象们,接下来会使用变量名的名称作为bean的id在匹配的对象们里查找,如果有一样的, 则注入成功,如果没有,则报错。)


spring的新注解-Import

  • import
  • 作用: 用于导入其他的配置类
  • 属性: value用于指定其他配置类的字节码.当我们使用Import的注解之后,有Import注解的类就是父配置类,导入的都是子配置类

spring的新注解-PropertySource

  • PropertySource
  • 作用: 用于指定properties文件的位置
  • 属性:
  • value: 指定文件的名称和路径.
  • 关键字:classpath,表示类路径下, 如果有包,可以在classpath:后写包名config/spring

实际开发项目中到底使用注解还是xml配置?

首先看公司要求。

如果可以自选,使用纯xml配置, 配置复杂; 使用纯注解,配置也蛮烦。

Xml与注解相结合, 如果类是jar包中的,使用xml配置,直接省事。 如果类是自己写的, 使用注解更方便,因为直接在类上写一个注解就结束了配置; 所以选择的原则就是实际开发中使用哪个方便就选择哪种方式来配置

Qualifier注解的另一种用法

spring整合junit问题分析

spring整合junit完成

  1. 导入spring整合junit的jar
  2. 使用junit提供的一个注解把原有的main方法替换了,替换成spring提供的@RunWtih
  3. 告知spring的运行期,spring和ioc创建是基于xml还是注解的,并且说明位置ContextConfiguration,
    locations: 指定xml文件位置,加上classpath关键字,表示在类路径下;
    classes: 指定注解类所在位置
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>

Spring 第三天 AOP的相关概念

1 什么是AOP

2 AOP的作用及优势

3 AOP的实现方式:使用动态代理技术

Spring中的AOP

说明: 学习Spring中的AOP,就是通过配置的方式,实现上一章节的功能。

AOP 相关术语
连接点JoinPoint:(就是业务层(Service)接口中的所有方法都是连接点,连接业务和增强方法中的点)

切入点Pointcut: 被增强的方法。(不是所有方法都需要被增强。就像查询方法不需要验签一样, 它只是连接点,但不是切入点,因为没有被增强。)

Advice(通知/增强):是指拦截到JoinPoint之后所要做的事情就是通知。
通知的类型: 前置通知, 后置通知, 异常通知, 最终通知, 环绕通知。

其他:

Target(目标对象): 就是被代理对象;accoutService
Proxy(代理对象 ): 一个类被AOP织入增强后,就产生一个结果代理类;
这个return 的就是代理对象

学习Spring中的AOP要明确的事情
Spring中的AOP要明确的

Spring中选择AOP的准则:
框架会根据目标类是否实现了接口来决定采用哪种动态代理的方式。 是基于接口的动态代理还是子类的动态代理,
基于接口的动态代理要求被代理对象至少实现一个接口。
基于子类的动态代理要求被代理对象不能是最终类。
基于子类的动态代理也可以用于基于接口中的动态代理。所以,在SpringAop中,可以手动来控制是 基于接口的动态代理还是基于子类的动态代理。

spring基于XML的AOP-配置步骤

<!--配置spring的IOC, 把Service对象配置进来-->
<bean id="accountService" class="com.qqlindy.service.impl.AccountServiceImpl"></bean>

<!--spring 基于xml的AOP配置步骤
1. 把通知bean也交给spring来管理
2. 使用aop:config标签表明开始AOP的配置
3. 使用aop:aspect标签表明配置切面, id属性给切面提供一个唯一标识。 ref属性是指定通知类bean的Id.
4. 在aop:aspect标签内部使用对应标签来配置通知的类型。
我们现在的示例是让pringLog方法在切入点方法执行之前执行:所以是前置通知。
aop:before标签是表示配置前置通知,
method属性用于指定通知类(这里是Logger类)中哪个方法是前置通知
pointcut属性用于指定切入点的表达式,该表达式的含义是对业务层中哪些方法增强

切入点表达式的写法:关键字 execution(表达式)
表达式: 访问修饰符  返回值  包名.包名.包名.包名...类名.方法名(参数列表)
标准的表达式写法:
public void com.qqlindy.service.impl.AccountServiceImpl.saveAccount()
全通配的表达式写法:
* *..*.*(..)
访问修饰符可以省略                                      void com.qqlindy.service.impl.AccountServiceImpl.saveAccount()
返回值可以使用通配符表示任意返回值                       * com.qqlindy.service.impl.AccountServiceImpl.saveAccount()
包名可以使用通配符表示任意包名,但是有几级包就要写几个*.  * *.*.*.*.AccountServiceImpl.saveAccount()
包名可以使用..表示当前包及其子包                         * *..AccountServiceImpl.saveAccount()
类名和方法名都可以使用*来实现通配                        * *..AccountServiceImpl.*()
参数列表可以直接写数据类型,
基本类型直接写名称 int,                             * *..*.*(int)
引用类型写包名.类名的方式 java.lang.String
可以使用*来实现通配任意类型,但是必须有参数           * *..*.*(*)
可以使用..表示有无参数的任意配置                      * *..*.*(..)  实际开发中很少这么写,因为是全匹配
实际开发中切入点表达式的通常写法: 切到业务实现类下的所有方法 * com.qqlindy.service.impl.*.*(..)
-->
<!--1. 把通知bean也交给spring来管理 配置Logger类-->
<bean id="logger" class="com.qqlindy.utils.Logger"></bean>

<!--2. 使用aop:config标签表明开始AOP的配置 配置AOP-->
<aop:config>
<!--配置切面-->
<aop:aspect id="logAdvice" ref="logger">
<!--配置通知的类型,并且建立通知方法和切入点方法的关联-->
<!--<aop:before method="printLog" pointcut="execution(public void com.qqlindy.service.impl.AccountServiceImpl.saveAccount())"></aop:before>-->
<!--<aop:before method="printLog" pointcut="execution(* *..*.*(..))"></aop:before>-->
<aop:before method="printLog" pointcut="execution(* *..*.*(..))"></aop:before>
</aop:aspect>
</aop:config>

6 通知类型
四种常用通知类型

<!--配置前置通知: 在切入点方法执行之前执行(也就是业务方法执行之前执行)-->
<aop:before  method="beforePrintLog" pointcut="execution(* com.qqlindy.service.impl.*.*(..))"></aop:before>

<!--配置后置通知: 在切入点方法正常执行之后执行, 它和异常通知永远智只能执行一个-->
<aop:after-returning method="afterReturningPrintLog" pointcut="execution(* com.qqlindy.service.impl.*.*(..))"></aop:after-returning>

<!--配置异常通知: 在切入点方法产生异常之后执行,  它和后置通知永远智只能执行一个 -->
<aop:after-throwing method="afterThrowingPrintLog" pointcut="execution(* com.qqlindy.service.impl.*.*(..))"></aop:after-throwing>

<!--配置最终通知: 无论切入点方法是否正常执行它都会在其后面执行-->
<aop:after  method="afterPrintLog" pointcut="execution(* com.qqlindy.service.impl.*.*(..))"></aop:after>

配置切入点表达式

<!--配置切入点表达式, id属性用于指定表达式的唯一标识, expression 用于指定表达式内容
aop:pointcut此标签写在aop:aspect标签内部只能当前切面使用。
它还可以写在aop:aspect外面,此时就变成所有切面可用, 但是必须写在aop:aspect标签前
-->
<aop:pointcut id="pt1" expression="execution(* com.qqlindy.service.impl.*.*(..))"></aop:pointcut>

spring中的环绕通知

<!--配置环绕通知,
当配置了环绕通知后,切入点方法没有执行,而通知方法执行了。
分析: 通过对比动态代理中的环绕通知代码, 发现动态代理中的环绕通知有明确的切入点方法调用,而我们的代码中没有。
解决:
Spring框架提供了一个接口:ProceedingJoinPoint. 该接口有一个方法叫proceed(), 此方法就相当于明确调用切入点方法。
该接口可以作为环绕通知的方法参数,在程序执行时,Spring框架会为我们提供接口的实现类供我们使用。

前面讲的四中通知类型都是通过配置的方式来指定增强代码何时执行。
Spring中的环绕通知:它是Spring框架为我们提供的一种可以在代码中手动控制增强方法何时执行的方式。
-->
<aop:around method="aroundPrintLog" pointcut-ref="pt1"></aop:around>

/**
* 环绕通知
*/
public Object aroundPrintLog(ProceedingJoinPoint pjp){
try {
Object[] args = pjp.getArgs(); //获取方法参数

System.out.println("环绕通知--aroundPrintLog。。。。。。。1");
Object proceed = pjp.proceed();//明确调用业务层方法,即切入点方法
System.out.println("环绕通知--aroundPrintLog。。。。。。。2");
return proceed;
}catch (Throwable t){       //注意这里要写Throwable, 不能写Exception
System.out.println("环绕通知--aroundPrintLog。。。。。。。3");
throw new RuntimeException(t);
}finally {
System.out.println("环绕通知--aroundPrintLog。。。。。。。4");
}
}

spring基于注解的AOP


JdbcTemplate的概述:

JdbcTemplate的作用: 用于和数据库交互的, 实现对表的CRUD操作。

临时杂记:
可变参数 Object… args 在JDK1.5之后才有, Object[] args 所有版本均可。

Spring中事务控制的需要明确的

Spring中事务控制的API介绍


我们开发中都是使用它的实现类:



事务隔离级别: 四个。 Spring默认使用的是数据库的默认隔离级别。




基于XML的声明式事务控制(配置方式)重点

<!--Spring中基于xml的声明式事务控制步骤配置
1. 配置事务管理器
2. 配置事务的通知,此时我们需要导入事务的约束:tx名称空间和约束,同时也需要AOP的
使用tx:advice标签配置事务通知
属性id:给事务通知起一个唯一标志
属性transaction-manager:给事务通知提供一个事务管理器引用
3. 配置AOP中的通用切入点表达式
4. 建立事务通知和切入点表达式的对应关系
5. 配置事务的属性,在事务的通知tx:advice标签的内部配置
isolation:用于指定事务的默认级别,默认值是DEFAULT,表示使用数据库的默认隔离级别
propagation:用于指定事务的传播行为,默认值是REQUIRED,表示一定会有事务(增,删,改), 查询可以选择SUPPORTS.
timeout:用于指定事务的超时时间, 默认值是"-1",表示永不超时。如果指定了数值,以秒为单位。
read-only:用于指定事务是否只读,只要查询方式才能设置为"true"。 默认值是"false".表示读写。
rollback-for:用于指定一个异常,当产生该异常时,事务回滚。 产生其他异常时,事务不回滚。    没有默认值,表示任何异常都回滚。
no-rollback-for:用于指定一个异常,当产生该异常时,事务不回滚。 产生其他异常时,事务回滚。  没有默认值,表示任何异常都回滚。
-->
<!--1.配置事务管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!--注入DataSource-->
<property name="dataSource" ref="dataSource"></property>
</bean>

<!--2. 配置事务的通知-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<!--配置事务的属性-->
<tx:attributes>
<tx:method name="*"  propagation="REQUIRED" read-only="false"/>
<!--注意查询的方法一定要遵循这个规定find开头,底下的优先级比上面的高-->
<tx:method name="find*"  propagation="SUPPORTS" read-only="true"/>
</tx:attributes>
</tx:advice>

<!--3. 配置AOP中的通用切入点表达式-->
<aop:config>
<!--配置切入点表达式-->
<aop:pointcut id="pt1" expression="execution(* com.qqlindy.service.impl.*.*(..))"></aop:pointcut>
<!--建立事务通知和切入点表达式的对应关系-->
<aop:advisor advice-ref="txAdvice" pointcut-ref="pt1"></aop:advisor>
</aop:config>

基于注解的配置方式

<!--Spring中基于注解的声明式事务控制步骤配置
1. 配置事务管理器
2. 开启Spring对注解事务的支持
使用tx:annotation-driven
3. 在需要事务支持的地方使用@Transactional注解
-->
<!--1.配置事务管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!--注入DataSource-->
<property name="dataSource" ref="dataSource"></property>
</bean>

<!--2. 开启Spring对注解事务的支持-->
<tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven>

Spring5的新特性:




内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: