Spring框架
- 怎么学框架
- 知道框架能做什么
- 框架的语法
- 会用后 以后在考虑内部实现
- 通过以上步骤 可以自己实现一个框架
一、概述
1. 框架是什么
-
Spring 是一个容器 管理对象,属性赋值,底层使用反射机制
-
主要是解决企业开发难度
-
模块之间,类之间的管理解耦合 解决对象之间的关系
-
核心技术 ioc aop
2. 优点
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-34D4uJcE-1631101190405)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20210904113452824.png)]
二、 IOC控制反转
1. 为什么使用IOC:
目的减少代码的改动,也能实现不同功能 解耦合
2. IOC(控制反转)是一个思想。
-
控制:对象的创建,赋值,对象关系之间的管理
-
反转:把开发人员new对象的权利 转移给容器实现
-
正转:开发人员使用代码中 new对象
-
容器:是一个服务器软件,一个框架(Spring)
3. IOC的技术实现:
DI实现IOC的功能
DI:依赖注入 只需提供对象的名称 对象创建、赋值等 由容器内部实现
三、 入门案例
1. 加入依赖
<!--//Spring依赖-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.5.RELEASE</version>
</dependency>
2.创建类(接口和实现类)
service包下创建接口 imp包下实现类
3. 创建Spring配置文件
<!--在资源目录下 要创建Spring的xml-->
<?xml version="1.0" encoding="UTF-8"?>
<!--beans:根标签 spring把java对象成bean-->
<!--spring-beans.xsd:格式约束文件-->
<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 告诉spring创建对象
id:自定义名 spring通过这个名找到对象
class:全限定名称(不能是接口 必须类)-->
<bean id="some" class="com.baidu.service.imp.SomeServiceImp"/>
</beans>
4. 测试使用对象
//ApplicationContext:是Spring的容器 通过容器获取对象
//ClassPathXmlApplicationContext:类路径加载Spring配置文件
ApplicationContext app =
new ClassPathXmlApplicationContext("beans.xml");
//getBean方法:获取
xxxx xx =
(xxxx)app.getBean("配置文件中的bean的id");
5. 注意点:
spirng: 创建对象的时间:创建spring的容器时,创建beans的所有对象
spring: 默认调用无参构造
获取容器中对象的信息api:
getBeanDefinitionCount(): 获取定义的对象数量
getBeanDefinitionNames():获取所有定义对象的名称
四、 DI实现语法
1. 通过spring完成 属性赋值
基本类型和String在这属于简单类型
引用
xml和注解注入区别:
经常需要修改的 xml否则 注解
xml 代码和值 完全分开
但是代码比较多 不够直观
注解 快 方便 可读好
但是在代码内 修改比较麻烦
1.1 基于XML的DI实现
spring 配置文件中,使用标签和属性
set注入
spring 调用类的set方法 必须有
//在spring配置文件bean中为属性赋值
//实际调用set方法
<property name="属性名" value="值 都要加引号"/>
//引用类型
<property name="属性名" ref="time"/>
<bean id="time" class="java.util.Date"/>
构造注入
调用类的有参构造方法
<constructor-arg
name="构造方法的新参名"
index="从0开始 构造方法参数位置"
ref="引用"
value="简单类型值"/>
//还有个省略index 但是要按方法参数位置
1.2 基于注解的DI实现
实现步骤
-
加依赖
-
创建类 加注解
-
创建spring配置文件 声明组件扫描器
//输入com 就会出来 <context:component-scan base- package="包名"/> //指定包 三种方式 //一个一个 // 分号;间隔 // 指定父包
注解
@Component 创建对象
-
类上使用
-
创建对象 value(可省略)= bean.id
-
不提供名称 默认首字符小写类名
@Respotory
- 持久层 dao
@Service
- 业务层 service
@Controller
- 控制器类
以上三种 跟Component一样创造对象 但是有额外含义
项目对象 分层的
@Value 简单赋值
- set或属性上使用 value = “值”
@Autowired 引用赋值
-
属性或set上
-
按类型自动注入
-
//按名自动注入 @Autowired @Qualifier("对象名") //如果对象名错了 required = true 赋值无 null //如果对象名错了 required = false 报错 @Autowired(required = false) @Qualifier("对象名")
@Resource
- 是JDK中的自动注入注解 需要加入依赖
- 自动先用byName再用byType
- 如果要知道注入方式 加 name属性= “方式”
set注入
spring 调用类的set方法 必须有
构造注入
调用类的有参构造方法
1.3 引用类型自动注入
byName(按名注入):
//类的属性名和spring配置文件bean id名一致 类型一致
<bean id=""class="" autowire="byName">
//简单类型赋值 引用自动
</bean>
byType(按类型注入):
//spring配置文件bean class类型一致或父子接口类关系
//唯一bean
<bean id=""class="" autowire="byType">
//简单类型赋值 引用自动
</bean>
1.4 多个配置
1.优点
- 文件小 效率高
- 避免多人使用冲突
-
按功能模块
-
按类的功能
2.使用
//创建一个Srping主配置文件total.xml//里面包含其他配置文件spring-*.xml//一般不定义对象<import resoutce = "classpath:路径.xml"> //可以使用通配符*//不能包含total.xml//需要在目录下才能使用<import resoutce = "classpath:spring-*.xml">
使用属性配置文件 注入
//主配置文件//${xxx}<context:property-placeholder location="classpath:xxx.properties"/>
五、 AOP (面向切面编程)
1. 动态代理
CGLIB代理 继承 类、方法不能final
JDK动态代理 必须实现接口
实现步骤:
1.创建目标类
2.创建InvocationHandler接口实现类
public class MyHandler implements InvocationHandler {
//目标对象
Object target = null;
public MyHandler(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//返回对象
Object res = null;
//方法执行前
MyTools.doTime();
//目标对象,方法集
ob = method.invoke(target,args);
//方法执行后
MyTools.doTrans();
return res;
}
}
3.实现目标类增加功能
4.使用jdk中Proxy 创建代理对象
接口 my = new 实现类();
InvocationHandler handler = new MyIncationHandler(my);
My proxy = (My) Proxy.newProxyInstance(my.getClass().getClassLoader(),
my.getClass().getInterfaces(),
handler);
proxy.xxx();
2. 作用
- 在代码不变的情况下 增加方法里面的功能
- 减少代码重复
- 解耦合
- 专注业务
总结:就是动态代理的规范化,让开发人员用统一的方法 使用动态代理
3. 理解面向切面编程
- A:切面 给方法增加的功能 非业务功能方法
- O:面向 对着
- P:编程
- 连接点 业务方法
- 切入点 连接点的集合
1)分析项目功能 找出切面
2)合理安排切面时间
3)合理安排切面位置 哪个类 哪个方法增
1.切面干什么 2. 执行位置 3. 执行时间
spring在内部实现了aop 但是比较繁琐 很少使用
4.aspectJ框架 专门做AOP
优秀的面向切面框架 通过spring就能使用它
1. 使用xml配置文件:配置全局事务
2. 使用注解 aspectJ有5个注解
- 切面的执行时间 在规范中叫做 通知
@Before 前置通知
- 方法上面 属性 value:切入点表达式
@AfterReturning 后置通知
-
方法是有参数的 建议Object 自定义名
-
属性value:切入点表达式
-
returning:自定义变量 Object 自定义名 跟方法参数名一样
-
获取方法返回值 可以修改返回值
@Around 环绕通知
-
必须有返回值 建议Object
-
固定参数ProceedingJoinPoint pjp
-
功能最强 方法前后都行
-
控制目标方法是否被执行
-
修改目标方法的执行结果 影响最后的调用结果
-
等同JDK invoke
-
最多 执行事务
@Around("execution(String doSome(..))")public Object doTime(ProceedingJoinPoint pjp) throws Throwable { Object result = null; System.out.println("hhh"); result = pjp.proceed(); return result;}
@AfterThrowing 了解 异常通知
- 属性throwing
- 方法参数 Exception 自定义名 要跟上面属性一致
@After 了解 最终通知
- 总是会被执行 类似finally
Pointcut辅助 定义切入点别名
@Pointcut("execution(String doSome(..))")private void 别名(){}@Around(value = "别名()")
3. Aspectj切入点表达式
execution
(访问类型? 返回类型 包类名?方法名(形参类型) 抛出异常?)
*:0-多个字符
…:方法参数中 多个参数
包名后 当前包及子包
+:类名后 当前类 子类
接口后 当前接口实现类
4. 使用步骤
1.加spring aspectJ依赖
<!--//Spring依赖-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.5.RELEASE</version>
</dependency>
<!--//aspectJ依赖-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>5.2.5.RELEASE</version>
</dependency>
2.目标类:接口和它的实现类
给类中的方法增加功能
3.创建切面类:普通类
在上面加@Aspectj:作用当前类是切面类
切面内定义方法 public void 自定义(不是自定义)
//JoinPoint参数 需要方法的信息
//必须是参数的第一个
public void doTime(JoinPoint jp){
//方法数字签名
System.out.println(jp.getSignature());
//方法名
System.out.println
(jp.getSignature().getName());
//方法参数
Object[] obj = jp.getArgs();
for(Object o:obj){
System.out.println(o);
}
System.out.println(new Date());
}
4.创建spring的配置文件
//创建目标类和切面类对象 bean
<aop:aspectj-autoproxy/>
//想用CGLIB代理 继承的方式 接口也能
<aop:aspectj-autoproxy proxy-target-class=“true”/>
六、集成mybatis spring框架
使用技术 aoc
1.加依赖
<!--Spring依赖-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.5.RELEASE</version>
</dependency>
<!--Spring事务-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>5.2.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.2.5.RELEASE</version>
</dependency>
<!--mybatis依赖-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.7</version>
</dependency>
<!--mysql驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.23</version>
</dependency>
<!--mybatis和Spring-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.1</version>
</dependency>
<!--阿里公司的数据库连接池-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.12</version>
</dependency>
<!-- pom.xml下的build中加入 -->
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>
2.创建实体类 Dao接口 sql映射文件
3.主配置文件mybatis
4.service 业务接口和实现类
5.创建spring配置文件
<?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 https://www.springframework.org/schema/context/spring-context.xsd">
<context:property-placeholder location="classpath:jdbc.properties"/>
<!--声明数据源DataSource-->
<bean id="myDataSource" class="com.alibaba.druid.pool.DruidDataSource"
init-method="init" destroy-method="close">
<!--set注入数据库信息 -->
<property name="url" value="${mysql.url}"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
<property name="maxActive" value="20"/>
</bean>
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!--set注入将数据库连接池交给dataSource属性-->
<property name="dataSource" ref="myDataSource"/>
<!--mybatis主配置文件的位置
configLocation属性是Resource类型 读取配置文件
value属性指定文件路径需要 classpath:
-->
<property name="configLocation" value="classpath:mybatis.xml"/>
</bean>
<!--创建dao对象 使用是sqlSession对象的getMapper方法(xxx.class)
生成每个dao接口的代理对象
-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!--指定SqlSessionFactory对象的id-->
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
<!--指定包名 dao接口所在的包名-->
<property name="basePackage" value="com.baidu.dao"/>
</bean>
<!--声明service对象-->
<bean id="studentService" class="com.baidu.services.impl.StudentServiceImpl">
<property name="studentDao" ref="studentDao"/>
</bean>
</beans>
6.测试
ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
StudentService studentService = (StudentService) app.getBean("studentService");
List<Student> students = studentService.sel();
//事务是自动提交的
7.资源配置文件
//spring配置文件中
<context:property-placeholder location="classpath:jdbc.properties"/>
七、spring事务
- 什么是事务?
- 一组sql语句的集合 我们希望多个sql语句能都成功或都失败
- 不同数据库有多个种处理方法
- spring提供一种统一模型 完成不同数据库的事务的处理方式
- 总结:
- spring的事务是统一模型
- 指定使用的事务管理器对象
- 指定类,那些方法加入事务的功能
- 指定事务隔离级别 传播方式 超时
- spring的事务是统一模型
接口PlatformTransactionManager 定义了commit rollback
实现类 mybatis DataSourceTransactionManager
1. 适合 中小型项目使用注解
<!--spring配置文件 声明事务管理器对象-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="myDataSource"/>
</bean>
<!--开启事务注解驱动 告诉spring 我要使用注解 管理事务-->
<!--赋值数据库信息-->
<tx:annotation-driven transaction-manager="transactionManager"/>
//在方法上加入@Transactional 默认就好 只能是public
2.适合大型项目 使用aspectj框架
-
很多类、方法配置事务
-
在spring配置文件中声明类、方法需要的事务
-
业务方法和事务配置完全分离
使用步骤
1.加入aspectj框架依赖
<!--//aspectJ依赖-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>5.2.5.RELEASE</version>
</dependency>
2.声明事务管理器对象
<!--spring配置文件 声明事务管理器对象-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="myDataSource"/>
</bean>
<tx:advice id="transactionInterceptor" transaction-manager="transactionManager">
<tx:attributes>
<!--完整的方法名 不带包和类 可以加通配符*-->
<!--属性propagation:传播方式
isolation:隔离级别
rollback-for:指定的异常类 发生异常一定回滚
-->
<tx:method name="buy"/>
</tx:attributes>
</tx:advice>
<!--配置aop*-->
<aop:config>
<!--配置切入点:指定包中那些类 使用事务
id:切入点表达式的自定义名
返回值 包名..方法-->
<aop:pointcut id="servicePt" expression="execution(* *..services..*.*(..))"/>
<!--关联advice和pointcut的id-->
<aop:advisor advice-ref="transactionInterceptor" pointcut-ref="servicePt"/>
</aop:config>
P97-102
web复习一下再看