Spring 001
<!-- SET 注入 bean 必须有默认无参数构造器
特殊字符 可用 <value><![CDATA[<jack>]]></value> 注入
-->
<bean id="test" class="spring.test">
<property name="name" >
<value><![CDATA[<jack>]]></value>
</property>
</bean>
bean 和 bean 之间相互访问
在配置bean property 时 可用ref="id" 配置
<bean id="test" class="spring.test">
<property name="name" ref ="school"></property>
</bean>
或者采用内部bean 内部bean 不能被外部引用,
<bean id="test" class="spring.test">
<property name="school">
<bean class="com.spring.xxxx">
<property name="name" value="嘿嘿"></property>
</bean>
</property>
</bean>
spring 自动转配 autowire
<bean id="address" class="autowire.Address"
p:city="北京" p:num="1314"></bean>
<bean id="car" class="autowire.Car"
p:carNam="奔驰" p:price="210000000"></bean>
<!-- 自动转配 -->
<bean id="persion" class="autowire.Person"
p:name="jack" autowire="byName"></bean>
#autowire="byName" 按照名字自动装配
byType 按照类型自动装配, 若IOC 容器中存在同一类型的 不同bean, 那么按照类型自动装配会抛出异常
使用bean 的 scope 属性来配置bean 的作用域
singleton: 默认值. 容器初始时创建bean 实例, 在整个容器的生命周期内只创建一个bean 单例;
prototype: 原型的. 容器初始时不创建bean 实例, 而是在每次调用时都创建一个新的bean 实例 并返回.
spring ioc 容器中的bean 生命周期
配置文件
<bean id="stu" class="shengmingzhouqi.Stu"
init-method="init" destroy-method="destroy">
<property name="name" value="你好"></property>
</bean>
java代码
public Stu() {
System.out.println("构造器");
}
private String name;
public void setName(String name) {
System.out.println("set Name...");
this.name = name;
}
public void init(){
System.out.println("初始化方法");
}
public void destroy(){
System.out.println("销毁方法执行");
}
console
构造器
set Name...
初始化方法
八月 21, 2017 10:40:07 上午 org.springframework.context.support.ClassPathXmlApplicationContext doClose
信息: Closing org.springframework.context.support.ClassPathXmlApplicationContext@779cc1e3: startup date [Mon Aug 21 10:40:06 CST 2017]; root of context hierarchy
销毁方法执行
bean 后置处理器 新建一个类 实现 BeanPostProcessor
实现后需要重写一个Before(在bean init-method 方法之前调用) 和 After (在bean init-method方法之后调用)方法
Java 类
public class HouZhi implements BeanPostProcessor{
@Override
public Object postProcessAfterInitialization(Object bean, String benaName)
throws BeansException {
System.out.println("After:"+benaName);
return bean;
}
@Override
public Object postProcessBeforeInitialization(Object bean, String benaName)
throws BeansException {
System.out.println("Before:"+benaName);
return bean;
}
}
配置文件中
<!-- 配置bean后置处理器 -->
<bean class="houzhi.HouZhi"></bean>
console 打印
构造器
set Name...
Before:stu
初始化方法
After:stu
八月 21, 2017 10:58:36 上午 org.springframework.context.support.ClassPathXmlApplicationContext doClose
信息: Closing org.springframework.context.support.ClassPathXmlApplicationContext@779cc1e3: startup date [Mon Aug 21 10:58:35 CST 2017]; root of context hierarchy
销毁方法执行
静态工厂
java 代码
/**
* @author Administrator
* 静态工厂方法: 直接调用某一个类的静态方法就可以返回 bean 实例
*/
public class StaticCarFactory {
private static Map<String, Car> cars = new HashMap<String, Car>();
static{
cars.put("benchi", new Car("奔驰", 1999));
cars.put("bmw", new Car("宝马王", 7897879));
}
// 静态工厂方法
public static Car getCar(String name){
return cars.get(name);
}
}
配置文件
<!-- 通过静态工厂方法来配置 bean , 不是配置静态工厂法实例, 是配置 bean 实例 -->
<!--
calss 属性: 指向静态工厂方法的全类名
factory-method: 指向静态工厂方法的名字
constructor-arg: 如果方法需要传入参数, 则使用constructor-arg 来配置参数
-->
<bean id="car" class="faction.StaticCarFactory"
factory-method="getCar">
<constructor-arg value="bmw"></constructor-arg>
</bean>
测试类:
ApplicationContext ctx = new ClassPathXmlApplicationContext("staticFactory.xml");
Car car = (Car) ctx.getBean("car");
System.out.println(car);
console 打印:
Car [carNam=宝马王, price=7897879.0]
实例工厂
配置文件
<!-- 配置实例工厂 -->
<bean id="carFactory" class="faction.InstanceCarFactory"></bean>
<!-- 通过实例工厂方法配置bean -->
<bean id="car2" factory-bean="carFactory" factory-method="getCar">
<constructor-arg value="jack"></constructor-arg>
</bean>
java 代码
/*
* 实例工厂方法: 实例工厂的方法, 即先需要创建工厂本身, 再调用工厂的实例方法返回bean实例
*/
public class InstanceCarFactory {
private Map<String, Car> cars = null;
public InstanceCarFactory(){
cars = new HashMap<String, Car>();
cars.put("bmw", new Car("宝马", 1314));
cars.put("jack", new Car("jack", 211314));
}
public Car getCar(String name){
return cars.get(name);
}
}
自定义实现 Spring 的 FactoryBean接口 实现配置Bean
Java 代码
import org.springframework.beans.factory.FactoryBean;
public class CarFactoryBean implements FactoryBean<Car>{
private String name;
public void setName(String name) {
this.name = name;
}
@Override
public Car getObject() throws Exception {
return new Car(name, 1314);
}
@Override
public Class<?> getObjectType() {
return Car.class;
}
@Override
public boolean isSingleton() {
return true;
}
}
配置文件
<!--
通过FactoryBean 来配置Bean 实例
class : 指向 FactoryBean 的全类名
property: 配置 FactoryBean 的属性
但 实际返回的实例却是 FactoryBean 的 getObject() 方法返回的实例!!!
-->
<bean id = "car" class="factoryBean.CarFactoryBean">
<property name="name" value="BMW"></property>
</bean>
使用注解
组件扫描
@Component: 基本注解, 标识了一个受Spring管理的组件
@Respository: 标识持久层组件
@Service: 标识服务层
@Controller: 标识表现层
<!-- 指定Spring IOC 扫描包 --> 自动扫描包下面注解的类
<context:component-scan base-package="zhujie"></context:component-scan>
@Autowired
泛型依赖注入
public interface BaseService <T>{
public void add();
}
@Service
public class BaseServiceImpl<T> implements BaseService<T>{
@Override
public void add() {
System.out.println("add");
}
}
public interface UserService extends BaseService<User> {
}
@Service("userService")
public class UserServiceImpl extends BaseServiceImpl<User> implements UserService {
}
@Controller
public class UserContorller {
@Autowired
public UserService userService;
public void addUser(){
userService.add();
}
}
Spring AOP
通知
public interface Cals {
int add(int i, int j);
int sub(int i, int j);
int cheng(int i, int j);
int chu(int i, int j);
}
@Component("cals")
public class CalsImpl implements Cals {
@Override
public int add(int i, int j) {
int result = i+j;
return result;
}
@Override
public int sub(int i, int j) {
int result = i-j;
return result;
}
@Override
public int cheng(int i, int j) {
int result = i*j;
return result;
}
@Override
public int chu(int i, int j) {
int result = i/j;
return result;
}
}
import java.util.Arrays;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
/**
* @author Administrator
* 日志切面
*/
@Aspect
@Component
public class LoggingAspect {
// 声明该方法是一个前置通知, 在目标方法开始之前执行
@Before("execution(public int com.aop.CalsImpl.*(..))")
public void beforeMethod(JoinPoint joinPoint){
String methodName = joinPoint.getSignature().getName();
Object[] args = joinPoint.getArgs();
System.out.println("The method "+methodName+" begins "+Arrays.asList(args));
}
// 声明该方法是一个后置通知, 在目标方法开始之后执行 异常也会赤星
@After("execution(public int com.aop.CalsImpl.*(..))")
public void afterMethod(JoinPoint joinPoint){
String methodName = joinPoint.getSignature().getName();
System.out.println("The method "+methodName+" end ");
}
// 返回通知, 可以访问到方法的返回值
@AfterReturning(value="execution(public int com.aop.CalsImpl.*(..))",returning="result")
public void afterReturn(JoinPoint joinPoint,Object result){
String methodName = joinPoint.getSignature().getName();
System.out.println(""+methodName+"运行结果:"+result);
}
// 异常通知 可以访问异常对象
@AfterThrowing(value="execution(public int com.aop.CalsImpl.*(..))",throwing="ex")
public void afterThrowing(JoinPoint joinPoint,Exception ex){
String methodName = joinPoint.getSignature().getName();
System.out.println(""+methodName+"运行异常:"+ex);
}
/**
* 环绕通知需要携带 ProceedingJoinPoint 类型的参数
* 环绕通知类似于动态代理的全过程: ProceedingJoinPoint 类型的参数可以决定是否执行目标方法
* 必须有返回值 返回值必为目标方法的返回值
*/
@Around(value="execution(public int com.aop.CalsImpl.*(..))")
public Object roundMethod(ProceedingJoinPoint pjp){
String methodName = pjp.getSignature().getName();
Object proceed = null;
try {
System.out.println("前置通知: "+methodName+" 准备执行,参数为:"+Arrays.asList(pjp.getArgs()));
proceed = pjp.proceed();
System.out.println("返回通知: "+methodName+" 执行结束,结果为:"+proceed);
} catch (Throwable e) {
System.out.println("异常通知: "+methodName+" 执行异常,异常为:"+e);
e.printStackTrace();
}
System.out.println("后置通知: "+methodName+" 执行结束,结果为:"+proceed);
return proceed;
}
}
验证参数
@Aspect
@Component
@Order(1)
public class Yanzheng {
@Before(value="execution(public int com.aop.CalsImpl.*(..))")
public void yanzheng(JoinPoint joinPoint){
System.out.println("验证参数通知 "+Arrays.asList(joinPoint.getArgs()));
}
}
和前置通知一样, 不加@Order(1) 时候, 发现日志打印出来的先是前置通知和后置通知, 然后是验证通知, 可以添加优先级
切面优先级 @Order(1) 数字越小优先级越高
声明切入点表达式
/**
* 定义一个方法, 声明切入点表达式,一般的 该方法中不需要添加其他代码
*/
@Pointcut("execution(public * com.aop.CalsImpl.*(..))")
public void getJoinPoint(){
}
后面的通知方法中的切入点就可以直接引用
例如:
@AfterThrowing(value="getJoinPoint()",throwing="ex")
public void afterThrowing(JoinPoint joinPoint,Exception ex){
String methodName = joinPoint.getSignature().getName();
System.out.println(""+methodName+"运行异常:"+ex);
}
Spring 事务管理
事务: 一系列的动作 它们当做一个独立的工作单元, 这些动作要么全部完成, 要么全部失败
事务的四个属性ACID
1.原子性(atomicty): 事务是一个原子操作,由一系列动作组成,事务的原子性确保动作要么全部完成,要么全部不起作用;
2.一致性(consistency):一旦所有事务动作完成,事务就被提交,数据和资源就处于一种满足业务规则的一致状态中;
3.隔离性(isolation):可能有许多事务会同事处理相同数据,因此每个事务都应该与其他事务隔离开来,防止数据损坏;
4.持久性(durability):一旦事务完成,无论发生什么系统作物,它的结果都不应该收到影响,通常情况下,事务的结果被写到持久化存储器中;
Spring 事务管理器
一.编程式事务
二.声明式事务
demo: spring3 -tx Test1
配置事务管理器
<!-- 配置事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 启动事务注解 -->
<tx:annotation-driven transaction-manager="transactionManager"/>
逻辑处理类加入注解
@Transactional
事务传播属性
当事务方法被另外一个事务方法调用时, 必须制定事务应该如何传播;
1.事务默认情况下是 @Transactional(propagation=Propagation.REQUIRED)
默认情况:使用调用方法的事务(A调用B B中存在事务但是A有事务, 那就使用A的事务)
2.@Transactional(propagation=Propagation.REQUIRES_NEW)
使用新事务,调用方法的事务挂起(A调用B B中存在事务,B新建事务并使用, 出现异常回滚到B事务前)
事务的隔离级别
使用 isolation 设置事务隔离级别 常用isolation=Isolation.READ_COMMITTED;
@Transactional(isolation=Isolation.READ_COMMITTED)
默认情况下Spring 的声明式事务 对所有运行时异常进行回滚,也可以通过对应的属性进行设置
1.@Transactional(noRollbackFor={CustomerBalanceException.class}) 发生此异常不回滚
2.@Transactional(readOnly=true )指定事务是否为只读,
3.@Transactional(timeout=1) 单位"秒", 指定强制回滚事务之前 事务可以占用的时间