Spring提供了两种类型的IOC容器实现,BeanFactory和ApplicationContext,前者面向Spring框架本身,后者变相开发者。
ApplicationContext提供了两种实现:
ClassPathXmlApplicationContext:从 类路径下加载配置文件
FileSystemXmlApplicationContext: 从文件系统中加载配置文件
ConfigurableApplicationContext 扩展于 ApplicationContext,新增加两个主要方法:refresh() 和 close(), 让 ApplicationContext 具有启动、刷新和关闭上下文的能力
<constructor-arg> 中没有 name 属性
若字面值中包含特殊字符,可以使用 <![CDATA[]]> 把字面值包裹起来。
自动装配:byType、byName、constructor(通过构造器自动装配,不推荐使用)
Spring 允许继承 bean 的配置, 被继承的 bean 称为父 bean. 继承这个父 Bean 的 Bean 称为子 Bean 子 Bean 从父 Bean 中继承配置, 包括 Bean 的属性配置 子 Bean 也可以覆盖从父 Bean 继承过来的配置 父 Bean 可以作为配置模板, 也可以作为 Bean 实例. 若只想把父 Bean 作为模板, 可以设置 <bean> 的abstract 属性为 true, 这样 Spring 将不会实例化这个 Bean 并不是 <bean> 元素里的所有属性都会被继承. 比如: autowire, abstract 等. 也可以忽略父 Bean 的 class 属性, 让子 Bean 指定自己的类, 而共享相同的属性配置. 但此时 abstract 必须设为 true
Spring 允许用户通过 depends-on 属性设定 Bean 前置依赖的Bean,前置依赖的 Bean 会在本 Bean 实例化之前创建好
如果前置依赖于多个 Bean,则可以通过逗号,空格或的方式配置 Bean 的名称
Bean的作用于:sigleton(单例)、prototype(原型)、request和session不常用。
Spring 提供了一个 PropertyPlaceholderConfigurer 的 BeanFactory 后置处理器, 这个处理器允许用户将 Bean 配置的部分内容外移到属性文件中.
可以在 Bean 配置文件里使用形式为 ${var} 的变量, PropertyPlaceholderConfigurer 从属性文件里加载属性, 并使用这些属性来替换变量
命名空间:
beans:基本的,需要有
util:如实例化一个list这种的时候需要
p:spring2.5之后加入的,简化属性注入
context:如引用外部文件的时候需要(<context:property-placeholder location="classpath:db.properties"/> ,spring2.5之后提供的,简化2.0)
Bean的生命周期:
IOC 容器中 Bean 的生命周期方法:
Spring IOC 容器可以管理 Bean 的生命周期, Spring 允许在 Bean 生命周期的特定点执行定制的任务.
Spring IOC 容器对 Bean 的生命周期进行管理的过程:
通过构造器或工厂方法创建 Bean 实例
为 Bean 的属性设置值和对其他 Bean 的引用
调用 Bean 的初始化方法
Bean 可以使用了
当容器关闭时, 调用 Bean 的销毁方法
在 Bean 的声明里设置 init-method 和 destroy-method 属性, 为 Bean 指定初始化和销毁方法.
创建 Bean 后置处理器:
Bean 后置处理器允许在调用初始化方法前后对 Bean 进行额外的处理.
Bean 后置处理器对 IOC 容器里的所有 Bean 实例逐一处理, 而非单一实例. 其典型应用是: 检查 Bean 属性的正确性或根据特定的标准更改 Bean 的属性.
对Bean 后置处理器而言, 需要实现 BeanPostProcessor 接口. 在初始化方法被调用前后, Spring 将把每个 Bean 实例分别传递给上述接口的两个方法.
添加 Bean 后置处理器后 Bean 的生命周期:
Spring IOC 容器对 Bean 的生命周期进行管理的过程:
通过构造器或工厂方法创建 Bean 实例
为 Bean 的属性设置值和对其他 Bean 的引用
将 Bean 实例传递给 Bean 后置处理器的 postProcessBeforeInitialization 方法
调用 Bean 的初始化方法
将 Bean 实例传递给 Bean 后置处理器的 postProcessAfterInitialization方法
Bean 可以使用了
当容器关闭时, 调用 Bean 的销毁方法
@Component: 基本注解, 标识了一个受 Spring 管理的组件
@Respository: 标识持久层组件
@Service: 标识服务层(业务层)组件
@Controller: 标识表现层组件
<context:component-scan> 元素还会自动注册 AutowiredAnnotationBeanPostProcessor 实例, 该实例可以自动装配具有 @Autowired 和 @Resource 、@Inject注解的属性.
默认情况下, 当 IOC 容器里存在多个类型兼容的 Bean 时, 通过类型的自动装配将无法工作. 此时可以在 @Qualifier 注解里提供 Bean 的名称. Spring 允许对方法的入参标注 @Qualifiter 已指定注入 Bean 的名称
@Qualifier可以放在bean的属性上面,也可以放在其set方法上面,也可以放在参数前面,比如set方法的参数前面
Spring 还支持 @Resource 和 @Inject 注解,这两个注解和 @Autowired 注解的功用类似,建议使用 @Autowired 注解
使用动态代理也可以实现aop,就是麻烦了点
该配置的作用是,使aspectJ注解起作用,为匹配的类自动生成代理对象。
AspectJ 支持 5 种类型的通知注解:
@Before: 前置通知, 在方法执行之前执行
@After: 后置通知, 在方法执行之后执行
@AfterRunning: 返回通知, 在方法返回结果之后执行
@AfterThrowing: 异常通知, 在方法抛出异常之后
@Around: 环绕通知, 围绕着方法执行
@Before,前置通知:
@After,后置通知:在目标方法执行之后(无论是否发生异常),执行的通知,在后置通知中还不能访问目标方法执行的结果,可以在结果通知中获得。
//@execution("execution(public int com.atguigu.spring.aop.ArithmeticCalculator.*(..))")
@AfterRunning & @AfterThrowing
异常通知,这里需要说明,Exception可以换成别的异常,如空指针异常,如果出发的是别的异常,则不会走异常通知
/** * 环绕通知需要携带 ProceedingJoinPoint 类型的参数. * 环绕通知类似于动态代理的全过程: ProceedingJoinPoint 类型的参数可以决定是否执行目标方法. * 且环绕通知必须有返回值, 返回值即为目标方法的返回值 */ @Around("execution(public int com.atguigu.spring.aop.ArithmeticCalculator.*(..))") public Object aroundMethod(ProceedingJoinPoint pjd){ Object result = null; String methodName = pjd.getSignature().getName(); try { //前置通知 System.out.println("The method " + methodName + " begins with " + Arrays.asList(pjd.getArgs())); //执行目标方法 result = pjd.proceed(); //返回通知 System.out.println("The method " + methodName + " ends with " + result); } catch (Throwable e) { //异常通知 System.out.println("The method " + methodName + " occurs exception:" + e); throw new RuntimeException(e); } //后置通知 System.out.println("The method " + methodName + " ends"); return result; }
如果有两个切面的话,就有切面的优先级问题,可以在@Aspect上面加个@order(1)来排优先级,值越小,优先级越高
定义一个方法,用来声明切入点表达式:
如果是在其他包,其他类里面的@Before这种通知里引用,需要加上全类名.方法名。
基于xml配置的方式实现aop
声明式事务:
1、
<!-- 配置事务管理器 -->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 启用事务注解 -->
<tx:annotation-driven transaction-manager="transactionManager"/>
2、在对应的数据方法上面,加上 @Transactional ,这样基本的事务可以了,之后就是根据需要,在这个标签里面加一些属性了。
事务的传播行为(propagation):
常用的有required(用已经有的事务,默认的)以及required_new(新建一个事务或者是用自己的事务,就是跟上个事务没关系了,如果出错,只回滚自己的事务,上个不回滚)
a 、b方法有事务,a方法调用b时,a是用b的事务还是新建一个?
买两本书,checkout有事务,purchase也有,
如果传播行为是required,则整个过程可以看成只有一个事务,事务过程中只要出错,就回滚所有
如果传播行为是required_new,purchase_1执行政策,purchase_2异常,则只回滚到purchase_2 之前,purchase_1已经成功了(required_new 在 purchase 方法上)
//添加事务注解 //1.使用 propagation 指定事务的传播行为, 即当前的事务方法被另外一个事务方法调用时 //如何使用事务, 默认取值为 REQUIRED, 即使用调用方法的事务 //REQUIRES_NEW: 事务自己的事务, 调用的事务方法的事务被挂起. //2.使用 isolation 指定事务的隔离级别, 最常用的取值为 READ_COMMITTED //3.默认情况下 Spring 的声明式事务对所有的运行时异常进行回滚. 也可以通过对应的 //属性进行设置. 通常情况下去默认值即可. //4.使用 readOnly 指定事务是否为只读. 表示这个事务只读取数据但不更新数据, //这样可以帮助数据库引擎优化事务. 若真的事一个只读取数据库值的方法, 应设置 readOnly=true //5.使用 timeout 指定强制回滚之前事务可以占用的时间,如果一个操作超过3秒,就强制回滚。然后报 //timeout异常。 //6.noRollbackFor通常不设置,默认就好 // @Transactional(propagation=Propagation.REQUIRES_NEW, // isolation=Isolation.READ_COMMITTED, // noRollbackFor={UserAccountException.class}) @Transactional(propagation=Propagation.REQUIRES_NEW, isolation=Isolation.READ_COMMITTED, readOnly=false, timeout=3)//单位:s @Override public void purchase(String username, String isbn) {
基于xml的方式配置事务:
<!-- 1. 配置事务管理器 --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"></property> </bean> <!-- 2. 配置事务属性 --> <tx:advice id="txAdvice" transaction-manager="transactionManager"> <tx:attributes> <!-- 根据方法名指定事务的属性,一般是将get这种只获取的设置为read-only,propagation一般默认即可,不需要配置 --> <tx:method name="purchase" propagation="REQUIRES_NEW"/> <tx:method name="get*" read-only="true"/> <tx:method name="find*" read-only="true"/> <tx:method name="*"/> </tx:attributes> </tx:advice> <!-- 3. 配置事务切入点, 以及把事务切入点和事务属性关联起来 --> <aop:config> <aop:pointcut expression="execution(* com.atguigu.spring.tx.xml.service.*.*(..))" id="txPointCut"/> <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"/> </aop:config>