目录
Spring框架
1、spring的简介
出现是在2002左右,解决企业开发的难度,减轻对项目模块之间的管理,类和类之间的管理,帮助开发人员创建对象,管理对象之间的关系。spring核心技术,ioc,aop.能实现模块之间,类之间的解耦合。 依赖:classa中使用classb的属性或者方法,叫做classa依赖classb。
2、使用注解进行创建对象
基于注解的di: 通过注解完成java对象创建,属性赋值。 使用注解的步骤: 1.加入maven的依赖 spring-context ,在你加入spring-context的同时, 间接加入spring-aop的依赖。使用注解必须使用spring-aop依赖 2.在类中加入spring的注解(多个不同功能的注解) 3.在spring的配置文件中,加入一个组件扫描器的标签,说明注解在你的项目中的位置 学习的注解: 1.@Component 2.@Respotory 3.@Service 4.@Controller 5.@Value 6.@Autowired 7.@Resource @Component:创建对象的,等用于<bean>的功能 属性:value就是对象的名称,也就是bean的id值 vlaue的值是唯一的,创建的对象在整个spring容器中就一个 位置:在类的上面 spring中和@Comonent功能一致,创建对象的注解还有: @Repository(用在持久层类的上面:)放在dao的实现类上面 表示创建dao对象,dao对象是能访问数据库的 @Service(用在业务层类的上面):放在service的实现类上面, 创建service对象,service对象是做业务处理,可以有事务等功能的。 @Controller(用在控制器的上面):放在控制器(处理器)类的上面,创建控制对象的, 控制器对象,能够接受用户提交的参数,显示请求的处理结果 以上三个注解的使用语法与@Comonent一样的,都能创建对象,但是这三个注解还有额外的功能。对项目的对象分层的。
创建的步骤:
1、导入meven依赖 spring 2、类上面写相应的注解 3、在xml中配置信息 组件扫描器(component-scan) base-package:指定注解在你的项目中的包名 component-scan工作方式:spring会扫描遍历base-package指定的包,把包中和子包中的所有类,找 到类中的注解,按照注解的功能创建对象,或给属性赋值 <context:component-scan base-package="包名"/> 4、在类中调用
指定多个包的三种方式
一、使用多次组件扫描器,指定不同的包 二、使用分隔符(;或,)分隔多个包名 三、指定父包
注解简单类型赋值
@Value:简单类型的属性值 属性:value是string类型的,表示简单类型的属性值 位置:1、在属性定义的上面,无需set方法,推荐使用。 2、在set方法的上面
注解引用类型赋值
引用类型:byType @Autowired:spring 框架提供的注解,实现引用类型的赋值 spring中通过注解给引用类型赋值,使用的是自动注入原理,支持byName,byType @Autowired:默认使用的是byType自动注入。 @Autowired的属性:required,是一个Boolean类型的,默认为true required=true:表示引用类型赋值失败,报错,终止执行 required=false:如果赋值失败,程序正常执行,引用类型为null 位置:1、在属性定义的上面,无需set方法,推荐使用 2、在set方法的上面 byName: 1、在属性上面加入@Autowired 2、在属性上面加入@Qualifier(value="bean的id"):表示使用指定bean值进行赋值
注解引用类型赋值(jdk的)
@Resource 来自于jdk中的注解,spring框架提供了对这个注解的功能支持,可以使用他对引用类型赋值。 使用的也是自动注入原理,支持byName,byType,默认是byName 位置:1、在属性定义的上面,无需set方法,推荐使用。 2、在set方法的上面 默认是buName:先使用byName自动注入,如果byName赋值失败,在使用byType。
3、IOC控制反转
IOC的技术实现
DI 是ioc的技术实现, DI(Dependency Injection) :依赖注入, 只需要在程序中提供要使用的对象名称就可以, 至于对象如何在容器中创建,赋值,查找都由容器内部实现。 spring是使用的di实现了ioc的功能, spring底层创建对象,使用的是反射机制。 spring是一个容器,管理对象,给属性赋值, 底层是反射创建对象。 spring-conetxt 和 spring-webmvc是spring中的两个模块 spring-context:是ioc功能的,创建对象的。 spring-webmvc做web开发使用的, 是servlet的升级。 spring-webmvc中也会用到spring-context中创建对象的功能的。 junit : 单元测试, 一个工具类库,做测试方法使用的。 单元:指定的是方法, 一个类中有很多方法,一个方法称为单元。
多配置优势
1.每个文件的大小比一个文件要小很多。效率高 2.避免多人竞争带来的冲突。 如果你的项目有多个模块(相关的功能在一起) ,一个模块一个配置文件。 学生考勤模块一个配置文件, 张三 学生成绩一个配置文件, 李四 多文件的分配方式: 1. 按功能模块,一个模块一个配置文件 2. 按类的功能,数据库相关的配置一个文件配置文件, 做事务的功能一个配置文件, 做service功能的一个配置文件等
4、AOP面向切面编程
1、动态代理
实现方式:jdk动态代理,使用jdk中的Proxy,Method,InvocaitonHanderl创建代理对象。 jdk动态代理要求目标类必须实现接口 cglib动态代理:第三方的工具库,创建代理对象,原理是继承。 通过继承目标类,创建子类。 子类就是代理对象。 要求目标类不能是final的, 方法也不能是final的 动态代理的作用: 1)在目标类源代码不改变的情况下,增加功能。 2)减少代码的重复 3)专注业务逻辑代码 4)解耦合,让你的业务功能和日志,事务非业务功能分离。
2、AOP面向切面编程,基于动态代理
Aop就是动态代理的规范化, 把动态代理的实现步骤,方式都定义好了, 让开发人员用一种统一的方式,使用动态代理。 Aspect: 切面,给你的目标类增加的功能,就是切面。 像上面用的日志,事务都是切面。 切面的特点: 一般都是非业务方法,独立使用的。 Orient:面向, 对着。 Programming:编程 oop: 面向对象编程
3、怎么理解面向切面编程
1)需要在分析项目功能时,找出切面。 2)合理的安排切面的执行时间(在目标方法前, 还是目标方法后) 3)合理的安全切面执行的位置,在哪个类,哪个方法增加增强功能
4、aop的实现
aop是一个规范,是动态的一个规范化,一个标准 aop的技术实现框架: 1.spring:spring在内部实现了aop规范,能做aop的工作。 spring主要在事务处理时使用aop。 我们项目开发中很少使用spring的aop实现。 因为spring的aop比较笨重。
5、AspectJ框架(AOP)
1、框架简介
一个开源的专门做aop的框架。spring框架中集成了aspectj框架,通过spring就能使用aspectj的功能。 aspectJ框架实现aop有两种方式: 1.使用xml的配置文件 : 配置全局事务 2.使用注解,我们在项目中要做aop功能,一般都使用注解, aspectj有5个注解。
2、aspectJ的使用
1)切面的执行时间, 这个执行时间在规范中叫做Advice(通知,增强) 在aspectj框架中使用注解表示的。也可以使用xml配置文件中的标签 1)@Before 2)@AfterReturning 3)@Around 4)@AfterThrowing 5)@After 2)表示切面执行的位置,使用的是切入点表达式。 com.service.impl com.bjpowrnode.service.impl cn.crm.bjpowernode.service execution(* *..service.*.*(..))
3、AspectJ的切入点表达式(掌握)
-
modifiers-pattern] 访问权限类型 ret-type-pattern 返回值类型 declaring-type-pattern 包名类名 name-pattern(param-pattern) 方法名(参数类型和参数个数) throws-pattern 抛出异常类型 ?表示可选的部分 以上表达式共 4 个部分。 execution(访问权限 方法返回值 方法声明(参数) 异常类型)
execution(public * *(..)) 指定切入点为:任意公共方法。 execution(* set*(..)) 指定切入点为:任何一个以“set”开始的方法。 execution(* com.xyz.service.*.*(..)) 指定切入点为:定义在 service 包里的任意类的任意方法。 execution(* com.xyz.service..*.*(..)) 指定切入点为:定义在 service 包或者子包里的任意类的任意方法。“..”出现在类名中时,后 面必须跟“*”,表示包、子包下的所有类。 execution(* *..service.*.*(..)) 指定所有包下的 serivce 子包下所有类(接口)中所有方法为切入点
4、AspectJ框架中的注解。
@AspectJ: 作用:表示当前类是切面类 切面类:是用来给业务方法增加功能的类,在这个类中有切面功能的代码 位置:在类定义的上面 @Before:前置通知注解 属性:value,是切入点表达式,表示切面的功能执行的位置 位置:在方法的上面 特点:1、在目标方法之前先执行的 2、不会改变目标方法的执行结果。 3、不会影响目标方法的执行。 <aop:aspectj-autoproxy/> :声明自动代理生成器:使用aspectj框架内部的功能,创建目标对象的代理对象。创建代理对象是在内存中实现的,修改目标对象的内存中的结构。创建为代理对象,所以目标对象就是被修改后的代理对象。 aspectj-autoproxy:会把spring容器中的所有目标对象,一次性都生成代理对象。 如果你期望的目标类有接口,想使用cglib代理 proxy-target-class="true":告诉框架,要使用cglib动态代理。这个要比jdk动态代理效率高 @AfterReturning:后置通知 属性:1、value切入点表达式 2、returning 自定义的变量,表示目标方法的返回值的。自定义变量名必须和通知方法的形参名一样 3、位置:在方法定义的上面 特点:1、在目标方法之后执行的 2、能够获取到目标方法的返回值,可以根据这个返回值做不同的处理功能。 3、可以修改这个返回值 @Around:环绕通知 定义格式: 1、public 2、必须有一个返回值,推荐使用object 3、方法名称自定义 4、方法有参数,固定的参数 ProceedingJoinPoint 属性:value 切入点表达式 位置:在方法定义什么 特点: 1、它是功能最强的通知 2、在目标方法的前和后都能增强功能。 3、控制目标方法是否被调用执行 4、修改原来的目标方法的执行结果,影响最后的调用结果。 环绕通知等同于jdk的动态代理,InvocationHandler接口 参数:ProceedingJoinPoint 等同于method 作用:执行目标方法的 返回值:就是目标方法的执行结果,可以被修改 环绕通知:经常做事务,在目标方法之前开启事务,执行目标方法,在目标方法之后提交事务。 @AfterThrowing异常通知 定义格式: 1、public 2、没有返回值 3、方法名称自定义 4、方法有个一个Exception,如果还要是jointPoint,Exception 属性:1、value 切入点表达式 2、throwing 自定义的变量,表示目标方法抛出的异常对象。 变量名必须和方法的参数名一样 特点:1、在目标方法抛出异常时执行的 2、可以做异常的监控程序,监控目标方法执行时是不是有异常。 如果有异常,可以发送邮件,短信进行通知 底层实现:也就是try()catch() @After:最终通知 定义格式: 1、public 2、没有返回值 3、方法名称自定义 4、方法没有参数,如果有就是joinPoint 属性:value 切入点表达式 位置:在方法的上面 特点:1、总是会执行 2、在目标方法执行之后执行。 底层:也就是try-catch后的finally,一定会执行。 pointcut:切入点,是一个或多个joinPoint的集合,表示切面功能执行的位置 如果你的项目中有多个切入点表达式是重复的,可以复用的,可以使用pointcut 属性:vlaue 切入点表达式 位置:在自定义的方法之上 特点:当使用@Pointcut定义在一个方法的上面,此时这个方法的名称就是切入点表达式的别名。其他的通知中,vlaue 属性就可以使用这个方法名称,代替切入点表达式了。 @Pointcut(value = "切入点表达式") private void 自定义名字(){无需代码} advice:通知,也叫增强。表示切面执行的时间,在方法前,方法后等等。 joinPoint:业务方法,要加入切面功能的业务方法 作用:可以在通知方法中获取方法执行时的信息,例如方法名称,方法的实参。如果你的切面功能中需要用到方法的信息,就加入joinPoint,这个joinPoint参数的值是由框架赋予的,必须是第一个位置的参数。
5、AOP的作用
1、在目标类不修改源代码的情况下,增加功能 2、减少重复的代码 3、专注业务功能的实现 4、解耦合:业务功能和日志,事务这些非业务功能的耦合。
6、什么时候考虑使用aop技术
1、当你要给一个系统中存在的类修改功能,但是原有类的功能不完善,但是你还有源代码,使用aop增加功能 2、你要给项目中的多个类,增加一个相同的功能,使用aop 3、给业务方法增加事务,日志的输出。
6、mybatis和spring集成
1、整合spring和mybatis的想法
使用spring的ioc核心技术,把mybatis框架中使用的对象交给spring统一创建和管理,存放你项目中要使用的各种对象,例如:service对象,dao对象,工具类对象等等。
2、交给spring的mybatis对象
第一步 <!--配置文件保存数据连接信息,这个是为了让spring知道连接信息--> <context:property-placeholder location="classpath:jdbc.properties"></context:property-placeholder>
第二步 <!-- 声明数据源DateSource,作用是连接数据库的--> <bean id="myDataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close"> <!--set注入给DruidDataSource提供连接数据库信息--> <property name="url" value="${jdbc.url}"></property> <property name="username" value="${jdbc.name}"></property> <property name="password" value="${jdbc.password}"></property> <property name="maxActive" value="${jdbc.max}"></property> </bean>
第三步 <!--声明的是mybatis中提供的SQLSessionFactoryBean类型--> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <!-- set注入,把数据库连接池付给了DataSource属性--> <property name="dataSource" ref="myDataSource"></property> <!--mybatis主配置文件的位置 configLocation属性是Resource类型,读取配置文件 他的赋值,使用value,指定文件的路径,使用classpath: --> <property name="configLocation" value="classpath:mybatis.xml"></property> </bean>
第四步 <!--创建dao对象,使用SqlSession的getMapper(StudentDao.class) MapperScannerConfigurer:在内部调用getMapper()生成每个dao接口的代理对象 --> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <!-- 指定SqlSessionFactory对象的id--> <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property> <!--指定包名,包名是dao接口所在的包名。 MapperScannerConfigurer会扫描这个包中的所有接口,把每个接口都执行一次 getMapper()方法,得到每个接口的dao对象 创建好的dao对象放入到spring容器中 --> <property name="basePackage" value="org.example.dao"></property> </bean> <!-- 声明service class:serviceImpl的实现类路径--> <bean id="studentService" class="org.example.service.serviceImpl.StudentServiceImpl"> <property name="studentDao" ref="studentDao"></property> </bean>
3、最终配置
7、spring的事务处理
@Transactional 注解方式
@Transactional 的所有可选属性如下所示: ➢ propagation:用于设置事务传播属性。该属性类型为 Propagation 枚举,默认值为 Propagation.REQUIRED。 ➢ isolation:用于设置事务的隔离级别。该属性类型为 Isolation 枚举,默认值为 Isolation.DEFAULT。 ➢ readOnly:用于设置该方法对数据库的操作是否是只读的。该属性为 boolean,默认值 为 false。 ➢ timeout:用于设置本操作与数据库连接的超时时限。单位为秒,类型为 int,默认值为 -1,即没有时限。 ➢ rollbackFor:指定需要回滚的异常类。类型为 Class[],默认值为空数组。当然,若只有 一个异常类时,可以不使用数组。 ➢ rollbackForClassName:指定需要回滚的异常类类名。类型为 String[],默认值为空数组。 当然,若只有一个异常类时,可以不使用数组。 ➢ noRollbackFor:指定不需要回滚的异常类。类型为 Class[],默认值为空数组。当然,若 只有一个异常类时,可以不使用数组。 ➢ noRollbackForClassName:指定不需要回滚的异常类类名。类型为 String[],默认值为空 数组。当然,若只有一个异常类时,可以不使用数组。 需要注意的是,@Transactional 若用在方法上,只能用于 public 方法上。对于其他非 public 方法,如果加上了注解@Transactional,虽然 Spring 不会报错,但不会将指定事务织入到该 方法中。因为 Spring 会忽略掉所有非 public 方法上的@Transaction 注解。 若@Transaction 注解在类上,则表示该类上所有的方法均将在执行时织入事务。
实现注解事务的步骤