Spring framework
核心容器(放对象)
AoP,Abstract(AOP的实现)
Data Access
Web
test单元测试 集中测试
核心容器
IoC DI
- 为什么要提出控制反转这样的概念?
一旦新写了一个接口的类,那么就要new一个新的类的对象,导致耦合度高
解决方案:在程序中不主动new产生对象,转为外部提供
思想:控制反转,将对象的创建控制权转移到外部
- Spring怎么做的?
Spring提供IoC容器,用来充当IoC思想中的“外部”
IoC容器负责对象的创建、初始化,对象在IoC容器中统称为Bean
- DI(Dependency Injection)依赖注入是干什么的?
DI是IoC的一种实现方式
例:service对象依赖于dao对象运行,只生成service对象还是会报错
IoC容器发现service和dao对象都在容器里,那么IoC容器会把他们绑定(关系绑定)
- IoC quickStart
- 在pom.xml中导入spring-context依赖
- 定义Spring管理的接口和类
- 在resource目录下新建spring config的xml(applicationContext.xml),并配置bean为
name属性表示配置哪一个具体属性,这里就是尚未实例化的 private BookDao bookDao;
ref属性表示参照哪一个bean
� ## Bean 1. bean基础配置 起别名 name=”service1 service2”逗号 分号或者空格分隔
Spring默认生成的对象是单例模式singleton,可以修改 scope=”prototype” 非单例。因为Spring帮助管理的对象就是可以复用的对象(表现层,业务层,数据层,工具对象都适合,不适合的是那些有状态的、有具体数值的对象) 2. bean实例化 1. 使用构造方法,但是与普通的new不同之处在于 private构造方法也能被调用—>用了反射的机制 并且是无参的构造方法 2. 使用静态工厂,配置 使用工厂中的方法
java
//FactoryBean
public class UserDaoFactoryBean implements FactoryBean<UserDao> {
public UserDao getObject() throws Exception {
return new UserDaoImpl();
}
public Class<?> getObjectType() {
return UserDao.class;
}
//非单例:
//public boolean isSingleton() {
// return false;
//}
}
3.关闭/销毁容器,执行bean销毁方法 ## 依赖注入方式 1. setter注入 步骤1,在bean中定义引用/简单类型并提供可访问的set方法
步骤2,配置中使用property标签ref/value注入引用/简单类型数据 1. 引用类型:见quickStart 1. 基本类型➕String 不用ref,用value,不用告诉类型
- 构造器注入
步骤1,在bean中定义引用/简单类型并提供可访问的构造方法
步骤2,配置中使用constructor-arg标签ref/value注入引用/简单类型数据
但是这种写法使得配置文件中的name和代码 紧耦合,怎么办?
方法1: 不写name,写类型type
方法2: 不写name,写索引index
DI方式选择
- 强制依赖用构造器,因为setter可能不注入导致null对象出现
- 可选依赖用setter,灵活
- Spring框架倡导用构造器,严谨
- 两者可以同时使用
- 自己开发模块推荐用setter注入
自动装配
- 按类型(常用)
保留bookDao的bean配置,但是不能有多个(一般也不会写2个实现类)
保留set方法,但是在bean配置中不再写property标签
- 按名称
可以有多个(要保证bookDao和实例化代码中的对象名称一样)
注意:自动装配只能用于引用类型的DI;
byType必须保证容器中相同类型的bean唯一;
byName必须保证容器中有指定名称的bean,变量名与配置耦合 不推荐;
自动装配优先级低于setter注入和构造器注入
- 集合注入
加载properties文件
数据库配置信息(url,admin,password等)一般写在.properties文件中
所以要在applicationContext.xml中配置
步骤:
- 开启context命名空间
- 使用context命名空间,加载指定properties文件
- 使用${}读取加载的属性值
容器
总结
- 容器相关
- bean相关
- 依赖注入相关
注解开发
@Component
在配置文件中定义
为了区分,各层命名不同
业务层(service):@Service
数据层(dao):@Repository
表现层:@Controller
纯注解开发
使用Java类代替Spring核心配置文件
步骤1. 在com.abc.config.SpringConfig.java中写:
@Configuration
@ComponentScan({"com.abc","xxx"})
public class SpringConfig {
}
步骤2. 在应用中 导入ioc容器的方式改成
ApplicationContext app = new AnnotationConfigApplicationContext(SpringConfig.class);
bean的作用范围和生命周期
在impl.java中注解为非单例
@Scope(“protopype”)
生命周期:
@PostConstruct
public void init() {
sout…
}
@PreDestory
public void destory() {
sout…
}
DI
- 自动装配
@Autowired 解决引用类型注入
private BookDao bookDao;
��@Qualifier 指定注入的bean的id或名称,必须配合Autowired使用(用得少)
@Value 注入简单类型
- 读取properties文件
@PropertySource
管理第三方bean
使用@Bean配置第三方bean
将独立的配置类加入核心配置:使用@Import注解手动加入配置到核心配置
- 简单类型依赖注入
直接使用配置类的成员变量
- 引用类型依赖注入
@Bean想要注入引用类型,只需要在形参中定义引用类型
总结: XML配置与注解配置
Spring整合MyBatis
- 在依赖文件中增加坐标 spring-jdbc和mybatis-spring
- 增加配置类MybatisConfig,其中需要调用两个第三方Bean:SqlSessionFactoryBean(需要传形参), MapperScannerConfigurer
Spring整合JUnit
- 在依赖文件中增加坐标 junit和spring-test
- @RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = SpringConfig.class)
然后要测试谁就把它自动装配
AOP
简介
比较:OOP是一种垂直纵向的继承体系
OOP不足:事务控制、权限校验、日志等场景中,纵向流程中会出现相同的子流程代码,这部分重复代码也叫横切逻辑代码
一种编程思想,在不惊动原始设计的基础上做功能增强(无侵入式功能增强)
核心概念:通知类中定义共性方法,也就是通知。把需要执行共性方法的方法定义为切入点
连接点是所有方法
把切入点和通知关系绑定,就得到了切面(Aspect描述通知与切入点的对应关系)
quickStart
- pom文件导依赖
�
SpringConfig中添加@EnableAspectJAutoProxy
MyAdvice.java
@Component//1.告诉spring加载
@Aspect//2.告诉Spring这是用来做aop的
public class MyAdvice {
//3.定义切入点
@Pointcut("execution(void com.abc.dao.BookDao.update())")
private void pt() {
}
//5.绑定切入点和通知
@Before("pt()")
//4.定义通知
public void mtehod() {
System.out.println(System.currentTimeMillis());
}
}
AOP工作流程
- Spring容器启动
- 读取所有已经配置了的切入点
- 初始化bean,判定bean对应的类中的方法是否匹配到任意切入点
- 否:生成普通普通对象 -> 获取bean,调用方法并执行
- 是:创建原始对象(目标对象)的代理对象 -> 根据代理对象的运行模式(@Before)运行原始方法和增强内容
AOP切入点表达式
匹配任意*一个(至少一个)
.. 匹配任意数量个
AOP通知类型
- 前置通知 @Before(“pt”)
- 后置通知 @After(“pt”)
- 环绕通知 @Around(“pt”)
需要依赖形参
为了防止原始方法被隔离,需要在中间调用一下原始方法
需要抛异常
- void
- 有返回值 接住,然后返回 Object
- 返回后通知 @AfterReturning(“pt”)
- 抛出异常后通知 @AfterThrowing(“pt”)
总结
Spring事务管理
简介
事务:在数据层保障一系列的数据库操作同成功或同失败
Spring事务:在数据层或业务层。。。
Spring事务属性
事务角色:
Spring开启的事务叫做事务管理员
加入Spring的事务为事务协调员
传播行为:
事务协调员对事务管理员所携带事务的处理态度
@Transactional(propagation = Propagation.xxx)
是一个枚举类: