Spring
IOC
IOC 概念
对象创建交给spring,降低耦合度。
类之间相互依赖,如果某个类路径变化,另一个类也会受影响,所以IOC能降低耦合。
IOC 过程
通过xml解析,工厂模式,发射创建对象
-
xml 配置
<bean id="dao" class="com.xxx.spring.UserDao"/>
-
有service类和dao类,创建工厂类
class UserFactory { public static UserDao getDao() { String classValue = class 属性值; Class clazz = Class.forName(classValue); //通过反射创建对象 return (UserDao) clazz.newInstance(); } }
IOC 接口
Spring提供了IOC容器两种实现方式 两个接口:都可以加在配置文件
- BeanFactory:spring内部使用接口,一般开发不用,加载配置文件的时候不会创建对象,使用的时候才会创建对象。
- ApplicationContext:BeanFactory接口的子接口,提供更多更强大功能。加载配置文件的时候就创建好了对象。
BeanFactory
- ConfigurableApplicationContext
具体实现类:
- XmlBeanFactory
ApplicationContext
有两个主要的实现类:
- FileSystemXmlApplicationContext
- ClassPathXmlApplicationContext
IOC 操作 Bean 管理
Bean管理指的是:创建对象 和 注入属性
基于xml配置
<bean id="dao" class="com.xxx.spring.UserDao"/>
- id : 名称
- class : 类名
- name : 和id差不多,name中可以添加特殊符号
创建对象默认执行无参数构造方法
DI:依赖注入,就是注入属性,需要在创建对象基础上进行。
-
set方法注入:(需要有有参构造函数)
<bean id="user" class="com.xxx.spring.bean.User"> <property name="name" value="set"/> </bean>
-
接口注入:有参构造函数 (需要注掉无参构造函数)
<bean id="user" class="com.xxx.spring.bean.User"> <constructor-arg name="name" value="args-construct"></constructor-arg> </bean>
-
传入null
<bean id="user" class="com.xxx.spring.bean.User" > <property name="name"> <null/> </property> </bean>
-
包含特殊符号
<![CDATA[]]
-
集合 数组 map
<property name="name"> <list> <value></value> <value></value> </list> <map> <entry key="" value=""></entry> </map> </property>
基于注解
- @Component
- @Service
- @Controller
- @Repository:一般用在Dao层
功能是一样的,都能创建bean实例
-
倒入spring-aop包
-
开启spring扫描
xmlns:context="http://www.springframework.org/schema/context" <context:component-scan base-package="com.xxx.spring"/>
-
添加注解
只扫描特定的组件,这里只扫描Component组件
<context:component-scan base-package="com.xxx.spring"> <context:include-filter type="annotation" expression="org.springframework.stereotype.Component"/> </context:component-scan>
属性注入:
-
@AutoWired:根据属性类型自动装配
@Qualifier 和 @AutoWired一起使用 @AutoWired private UserService userService; 如果多个Service实现类UserService接口,那么使用Qulifier @AutoWired @Qualifier(value = "dao1") //根据名称进行注入 private UserService userService;
-
@Qualifier:根据属性名称进行注入
-
@Resource:可以根据名称注入,也可以根据属性注入
import javax.annotation.Resource @Resource(name = "dao1")
-
@Value : 注入普通类型属性
@Value(value = "abc") private String name; // name = "abc";
p名称空间注入
xmlns:p="http://www.springframework.org/schema/p"
<bean id="user" class="com.xxx.spring.bean.User" p:name="p namespace"/>
IOC Bean 管理
Spring 有两种bean,普通bean和工厂bean
- 普通bean:就是平时创建的bean
- 工厂bean:在配置文件定义bean类型可以和返回类型不一样
- 创建类,实现接口 FactoryBean
- 实现接口的方法,在实现的方法中定义返回的bean类型
IOC Bean 作用域
- 单例模式:单例的情况下,spring容器启动的时候就会创建bean
- 多例模式:spring容器启动的时候先不创建bean
IOC Bean 生命周期
概念:
从对象创建到销毁的过程
- 通过构造器创建bean实例
- 为bean属性设置值和对其他bean的引用
- 把bean实例传给bean的后置处理器的方法
- 初始化bean的方法(需要进行配置)
- 把bean实例传递给bean后置处理器
- bean可以使用
- 容器关闭的时候,调用bean销毁的方法(需要进行配置销毁方法)
演示:
<bean id="myBean" class="com.xxx.spring.bean.Test" init-method="init" destroy-method="destory">
<property name="name" value="life-cycle" />
</bean>
public class Test {
private String name;
Test() { System.out.println("non args construction function"); }
public void setName(String name) {
System.out.println("using set function");
this.name = name; }
public String getName() { return name; }
public void init() { System.out.println("init......"); }
public void destory() { System.out.println("destroying .... "); }
}
后置处理器
public class MyPostBean implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("post before init");
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("post after init");
return bean;
}
}
<bean id="myBeanPost" class="com.xxx.spring.bean.MyPostBean"></bean>
会自动处理该xml定义的bean
自动装配
@Autowire 属性两个常用值, “byName” : 名字一一对应。 “byType”:根据类型自动注入
外部配置
<context:property-placeholder location="classpath:jdbc.properties"/>
完全注解开发
-
创建配置类
@Configuration @ComponentScan(basePackages = "com.xxx.spring") public class SpringConfig { }
-
测试代码
ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class); UserS test = context.getBean("a", UserS.class);
AOP
概念
Aspect-Oriented Programming:面向切面编程,降低程序耦合度。不通过修改代码就能修改业务逻辑。
AOP代理情况
- 有接口使用JDK代理:创建接口实现类的代理对象,增强类中的方法
- 无接口使用cglib代理:创建当前类子类的代理对象,增强方法
Spring 动态代理
调用 Object 的newProxyInstance
- 参数1 类加载器
- 参数2 接口
- 参数3 InvocationHandler
AOP 术语
- 连接点:能被增强的方法
- 切入点:实际真正被增强的方法
- 通知(增强):
- 实际增强的逻辑部分称为通知(增强)
- 通知类型:
- 前置通知 @Before
- 后置通知 @After
- 环绕通知 @Around
- 异常通知 @AfterThrowing
- 最终通知 @AfterReturning
- 切面:是动作,把通知应用到切入点称为切面
AOP 操作
-
AspectJ 使用
-
切入点表达式:
execution([权限修饰符,*][返回类型][类全路径][方法名称]([参数列表]))
@Around(value = "execution(* com.xxx.spring.aop.MyImpl.myFun(..))")
public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
System.out.println("around before");
proceedingJoinPoint.proceed();
System.out.println("around after");
}
环绕在函数执行前后都执行,中间需要proceed()函数来区分。
运行顺序区分:
try{
try{
//@Before
method.invoke(..);
}finally{
//@After
}
//@AfterReturning
}catch(){
//@AfterThrowing
}
提取相同切入点
//提取相同切入点
@Pointcut(value = "execution(* com.xxx.spring.aop.MyImpl.myFun(..))")
public void pointDemo() {}
@Component
// 同一个类的不同增强类,数字越小优先级越高,优先执行
@Order(value = 1)
@Aspect
完全注解开发
@Configuration
@ComponentScan(basePackages = "com.xxx.spring")
@EnableAspectJAutoProxy(proxyTargetClass = true)
public class SpringConfig {
}
JdbcTemplate
概念
Spring对Jdbc进行封装,方便对数据库操作
@Autowired
private JdbcTemplate jdbcTemplate;
String sql = "insert into book values(?,?)";
String[] args = {"a", "b"};
int result = jdbcTemplate.update(sql, args);
查询数量
jdbcTemplate.queryForObject(sql, Integer.class);
查询返回对象
jdbcTemplate.queryForObject(String sql, RowMapper<T> rowMapper, Object... args)
// 实际使用 BeanPropertyRowMapper
// new BeanPropertyRowMapper<Book>(Book.class)
查询返回对象集合,使用 query 方法
批量操作:
jdbcTemplate.batchUpdate(String sql, List<Object[]> batchArgs)
事务
概念
事务是数据库操作最基本单元,逻辑上一组操作,要么都成功,要么都失败。
ACID
- 原子性
- 一致性
- 隔离性
- 持久性
try {
// 开启事务
//出现异常
//没出现异常,提交事务
} catch (Exception e) {
// 回滚异常
}
Spring事务管理操作
一般事务加在 Service 层,业务逻辑层
-
编程式事务管理
例如上述的代码操作()
-
声明式事务管理
- 基于注解
- 基于xml配置文件
Spring声明式事务管理,底层使用了AOP
Spring事务管理API
-
提供了一个接口,代表事务管理器,这个接口针对不同的框架提供了不同的实现类
/** * This is the central interface in Spring's transaction infrastructure. * Applications can use this directly, but it is not primarily meant as API: * Typically, applications will work with either TransactionTemplate or * declarative transaction demarcation through AOP. * * <p>For implementors, it is recommended to derive from the provided * {@link org.springframework.transaction.support.AbstractPlatformTransactionManager} * class, which pre-implements the defined propagation behavior and takes care * of transaction synchronization handling. Subclasses have to implement * template methods for specific states of the underlying transaction, * for example: begin, suspend, resume, commit. * * <p>The default implementations of this strategy interface are * {@link org.springframework.transaction.jta.JtaTransactionManager} and * {@link org.springframework.jdbc.datasource.DataSourceTransactionManager}, * which can serve as an implementation guide for other transaction strategies. * * @author Rod Johnson * @author Juergen Hoeller * @since 16.05.2003 * @see org.springframework.transaction.support.TransactionTemplate * @see org.springframework.transaction.interceptor.TransactionInterceptor */ public interface PlatformTransactionManager extends TransactionManager { /** * Return a currently active transaction or create a new one, according to * the specified propagation behavior. * <p>Note that parameters like isolation level or timeout will only be applied * to new transactions, and thus be ignored when participating in active ones. * <p>Furthermore, not all transaction definition settings will be supported * by every transaction manager: A proper transaction manager implementation * should throw an exception when unsupported settings are encountered. * <p>An exception to the above rule is the read-only flag, which should be * ignored if no explicit read-only mode is supported. Essentially, the * read-only flag is just a hint for potential optimization. * @param definition the TransactionDefinition instance (can be {@code null} for defaults), * describing propagation behavior, isolation level, timeout etc. * @return transaction status object representing the new or current transaction * @throws TransactionException in case of lookup, creation, or system errors * @throws IllegalTransactionStateException if the given transaction definition * cannot be executed (for example, if a currently active transaction is in * conflict with the specified propagation behavior) * @see TransactionDefinition#getPropagationBehavior * @see TransactionDefinition#getIsolationLevel * @see TransactionDefinition#getTimeout * @see TransactionDefinition#isReadOnly */ TransactionStatus getTransaction(@Nullable TransactionDefinition definition) throws TransactionException; /** * Commit the given transaction, with regard to its status. If the transaction * has been marked rollback-only programmatically, perform a rollback. * <p>If the transaction wasn't a new one, omit the commit for proper * participation in the surrounding transaction. If a previous transaction * has been suspended to be able to create a new one, resume the previous * transaction after committing the new one. * <p>Note that when the commit call completes, no matter if normally or * throwing an exception, the transaction must be fully completed and * cleaned up. No rollback call should be expected in such a case. * <p>If this method throws an exception other than a TransactionException, * then some before-commit error caused the commit attempt to fail. For * example, an O/R Mapping tool might have tried to flush changes to the * database right before commit, with the resulting DataAccessException * causing the transaction to fail. The original exception will be * propagated to the caller of this commit method in such a case. * @param status object returned by the {@code getTransaction} method * @throws UnexpectedRollbackException in case of an unexpected rollback * that the transaction coordinator initiated * @throws HeuristicCompletionException in case of a transaction failure * caused by a heuristic decision on the side of the transaction coordinator * @throws TransactionSystemException in case of commit or system errors * (typically caused by fundamental resource failures) * @throws IllegalTransactionStateException if the given transaction * is already completed (that is, committed or rolled back) * @see TransactionStatus#setRollbackOnly */ void commit(TransactionStatus status) throws TransactionException; /** * Perform a rollback of the given transaction. * <p>If the transaction wasn't a new one, just set it rollback-only for proper * participation in the surrounding transaction. If a previous transaction * has been suspended to be able to create a new one, resume the previous * transaction after rolling back the new one. * <p><b>Do not call rollback on a transaction if commit threw an exception.</b> * The transaction will already have been completed and cleaned up when commit * returns, even in case of a commit exception. Consequently, a rollback call * after commit failure will lead to an IllegalTransactionStateException. * @param status object returned by the {@code getTransaction} method * @throws TransactionSystemException in case of rollback or system errors * (typically caused by fundamental resource failures) * @throws IllegalTransactionStateException if the given transaction * is already completed (that is, committed or rolled back) */ void rollback(TransactionStatus status) throws TransactionException; }
事务操作
-
spring配置事务管理器
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"; </bean>
-
开启事务注解
xmlns:tx="http://www.springframework.org/schema/tx" 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/tx http://www.springframework.org/schema/tx/spring-tx.xsd
<!-- 开启事务注解,指定事务管理器 --> <tx:annotation-driven transaction-manager="transactionManager"/>
-
在Service类或方法上面添加事务注解
事务配置参数
-
propagation:事务传播行为
-
isolation:隔离级别
多事务操作之间可能会影响
- 脏读:一个未提交事务读到另一个未提交事务的数据 (读未提交)
- 不可重复读:一个未提交事务读到另一个提交事务的数据 (读已提交)
- 幻读:一个未提交事务读到另一个提交事务添加数据 (可重复读)
-
timeout:超时时间
-
readOnly:是否只读
-
rollbackFor:回滚
-
noRollbackFor:不回滚
指定哪些异常不回滚
完全注解开发
package com.xxx.spring;
@Configuration
@ComponentScan(basePackages = "com.xxx.spring")
@EnableAspectJAutoProxy(proxyTargetClass = true)
@EnableTransactionManagement //开启事务
public class SpringConfig {
// 创建数据库连接池
@Bean
public DruidDataSource getDruidDataSource() {
DruidDataSource dataSource = new DruidDataSource();
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://192.168.157.2:3306/mq");
dataSource.setUsername("admin");
dataSource.setPassword("admin");
return dataSource;
}
// 创建jdbcTemplate
@Bean
public JdbcTemplate getJdbcTemplate(DataSource dataSource) {
// 从IOC容器中根据类型找到 datasource
JdbcTemplate jdbcTemplate = new JdbcTemplate();
jdbcTemplate.setDataSource(dataSource);
return jdbcTemplate;
}
// 创建事务管理器对象
@Bean
public DataSourceTransactionManager getDataSourceTransactionManager(DataSource dataSource) {
DataSourceTransactionManager transactionManager =
new DataSourceTransactionManager();
transactionManager.setDataSource(dataSource);
return transactionManager;
}
}