1、Spring是什么?
Spring是轻量级的JAVAEE应用开源框架
2、Spring的好处?
IOC:控制反转
AOP:面向切面 粘合剂:整合其他技术和框架
1、耦合
耦合:对象之间的依赖关系(service依赖于dao),耦合度越高维护的成本越高
产生耦合的原因:硬编码
2、IOC
控制:控制对象的创建
IOC (Inverse of Control)即控制反转:正传是自己创建对象;反转是由工厂创建依赖对象
3、工厂模式的IOC解决程序耦合
1.把dao和service配置到beans.properties
2.读取beans.properties
3.通过反射创建对象,并装到容器中
4.在使用时,直接从容器中获得
4、spring的IOC解决程序耦合
1.pom.xml
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.1.8.RELEASE</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.30</version>
</dependency>
2.log4j.properties
复制mybatis
3.applicationContext.xml
<bean id="userDao" class="com.by.dao.UserDaoImpl" />
<bean id="userService" class="com.by.dao.UserServiceImpl" />
4、测试
//带IOC容器的工厂
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
ac.getBean("userService", UserService);
1、什么是DI?
DI(Dependency Injection)依赖注入:将依赖对象从容器中拿出来赋值给调用者
2、DI的方式
1、构造方法注入
public UserServiceImpl(UserDao userDao, String msg){
this.userDao=userDao
this.msg=msg
}
<bean id="userService" class="com.by.dao.UserServiceImpl" >
<!--
name="userDao":构造方法的参数名称
ref="userDao":另一个bean标签的id
-->
<constructor-arg name="userDao" ref="userDao"></constructor-arg>
<!--
index="userDao":构造方法的参数的索引位置
value="我靠":基本数据类型和String类型
-->
<constructor-arg index="0" value="我靠"></constructor-arg>
</bean>
2、set方法注入
public setUserDao(UserDao userDao){
this.userDao=userDao
}
public setMsg(String msg){
this.msg=msg
}
<bean id="userService" class="com.by.dao.UserServiceImpl" >
<property name="userDao" ref="userDao"></property>
<property name="msg" value="我操"></property>
</bean>
3、自动注入
//遍历map,并判断每个bean的类型,如果类型符合则赋值
<bean id="userService" class="com.by.dao.UserServiceImpl" autowire="byType"></bean>
ApplicationContext:子接口,加载配置文件时就创建对象
BeanFactory:顶级接口,使用对象时才创建
singleton:单例,ioc容器
prototype:多例,newInstance()
request:request域
session:session域
application:servletContext域
配置方式:<bean id="" class="" scope="prototype" />
单例和多例的使用场景?
单例:service、dao、sqlSessionFactroy
多例:connnect、sqlSession
1、案例:
public class UserServiceImpl{
private UserDao userDao;
public UserServiceImpl(){
}
public setUserDao(){
}
public void init(){
}
public void destroy(){
}
}
<bean id="" class="" scope="singleton"
init-method="init" destroy-method="destroy" autowire="byType">
2、实验
单例:
[容器启动]---->构造方法(实例化)---->set方法(注入)---->init方法(初始化)---->[容器关闭]---->destroy方法(销毁bean)
多例:
[使用对象]---->构造方法(实例化)---->set方法(注入)---->init方法(初始化)---->[JVM垃圾回收]---->destroy方法(销毁bean)
1、配置步骤
1)pom.xml
spring-context、slf4j-log4j12
2.log4j.properties
复制mybatis
3)applicationContext.xml
<context:component-scan base-package="com.by"></context:component-scan>
4、ioc
@Repository //<userDaoImpl, new UserDaoImpl()>
public class UserDaoImpl{
}
5、DI
public class UserServiceImpl{
@Autowired
private UserDao userDao;
}
2、常用注解
1)IOC
@Controller:web
@Service:service
@Repository:dao
@Component:三层架构之外
@Scope("prototype"):指定bean的作用域范围,eg:singleton、prototype、request、session、application
2)DI
@Resource(name=""):按名称注入
@Autowired:按类型
@Value("${}"):注入基本类型和String类
1、为什么要使用AOP?
有一万个service类,要求每个方法执行前打印日志,执行后打印日志
2、什么是AOP?
AOP(Aspect Oriented Programming)面向切面编程:把程序中重复的代码抽取出来,使用动态代理的技术去执行,
从而实现对方法的增强(不修改源代码对方法进行增强)
2、代理模式
1)静态代理
角色:
公共接口:Star
真实角色:RealStar(周杰伦.唱歌)
代理角色:ProxyStar(宋吉吉.面谈.订机票.签合同.[调周杰伦唱歌].收尾款)
客户类:Client(小孩.调宋吉吉)
缺陷:1.大量代码重复 2.只能代理Star类型的对象
2)jdk动态代理
角色:
公共接口:Star
真实角色:RealStar(周杰伦.唱歌)
代理工厂:ProxyFactroy{生成ProxyStar(宋吉吉.面谈.订机票.签合同.[调周杰伦唱歌].收尾款)}
客户类:Client(小孩.调宋吉吉)
3)Cglib动态代理
cglib和jdk动态代理的区别:cglib真实角色没有接口
3、aop的核心概念
切点(pintcut):要增强的方法,eg:add()、update()
通知/增强(advice):要搞的事情,eg:日志
前置通知:aop:before
后置通知:aop:after-returning【try】
最终通知:aop:after【finally】
异常通知:aop:after-throwing【catch】
环绕通知:aop:around
try{
...
return aop:after-returning
}catch(Exception e){
...
aop:after-throwing
}finally{
...
aop:after
}
切面(aspect):把增强应用到切点上
4、切点表达式
格式:execution([修饰符] 返回值 报名.类名.方法名(参数))
eg:execution(* com.by.service.*.*(..))
5、基于xml的aop配置
1)pom.xml
spring-context、spring-aspects、slf4j-log4j12
2)advice
public class MyLogAdvice {
public void before(){
System.out.println("前置通知....");
}
}
2)aop
<!--增强(advice)-->
<bean id="myLogAdvice" class="com.by.advice.MyLogAdvice"></bean>
<aop:config>
<!--切点(pintcut)-->
<aop:pointcut id="pointcut" expression="execution(* com.by.service.*.*(..))"/>
<aop:aspect ref="myLogAdvice">
<aop:before method="before" pointcut-ref="pointcut"></aop:before>
</aop:aspect>
</aop:config>
1)pom.xml
spring-context、spring-aspects、slf4j-log4j12
2)advice
@Component
@Aspect
public class MyLogAdvice {
@Before("execution(* com.by.service.*.*(..)")
public void before(){
System.out.println("前置通知....");
}
}
3、开启spring对aop注解的支持
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
1、pom.xml
参考6.1.1
2、applicationContext.xml
<!--加载db.properties-->
<context:property-placeholder location="classpath:db.properties"></context:property-placeholder>
<!--数据源-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close">
<property name="driverClassName" value="${jdbc.driverClass}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
<!--sqlSessionFactory-->
<bean id="sessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!--告诉mybatis扫描mapper接口生成代理类,并交给spring的ioc容器去管理-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.by.mapper"></property>
<property name="sqlSessionFactoryBeanName" value="sessionFactory"></property>
</bean>
1、pom.xml
spring-test、junit
2、test
@RunWith(SpringJUnit4ClassRunner.class) //单元测试运行时带上spring环境
@ContextConfiguration("classpath:applicationContext.xml")
public class Client {
@Autowired
private UserService userService;
}
1)什么是事务?
执行多条sql,要么全部执行,要么全部回滚
2)事务的特点
原子性:事务是最小执行单位
一致性:事务前后数据都是正确的
隔离性:事务之间看不到彼此的中间状态
持久性:事务一旦提交不可再回滚
3)mysql控制事务
START TRANSACTION;
sql1;
sql2;
COMMIT 或 ROLLBACK;
4)jdbc控制事务
try{
conn.setAutoCommit(false);
....
conn.commit();
}catch(Exception e){
conn.rollback();
}
1、PlatformTransactionManager
作用:是一个事务管理器,负责开启、提交或回滚事务
实现类:DataSourceTransactionManager(sqlSession)
2、TransactionDefinition
作用:定义事务的属性
实现类:DefaultTransactionDefinition
属性:
1)隔离级别【有默认值】
DEFAULT:默认值,等价于REPEATABLE_READ
READ_UNCOMMITTED x x x
READ_COMMITTED 脏读 x x
REPEATABLE_READ 脏读 不可重复度
SERIALIZABLE 脏读 不可重复度 幻读
2)事务的传播行为【有默认值】
REQUIRED:默认值,methodB()会加入到methodA()事务中
3)事务超时【有默认值】
默认-1:永不超时
4)是否只读【有默认值】
readOnly = false:默认值,适用于增删改
readOnly = true:不记录log(效率快),适用于查询
5)回滚规则
可省略:运行时异常回滚,编译时异常不回滚
3、TransactionStatus
作用:代表一个事务
<!--增强(advice):要搞的事情,eg:日志、事务-->
<tx:advice id="txManager" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="get*" propagation="SUPPORTS" read-only="true"/>
<tx:method name="select*" propagation="SUPPORTS" read-only="true"/>
<tx:method name="*"></tx:method>
</tx:attributes>
</tx:advice>
<aop:config>
<!--切点(pointcut):要增强的方法-->
<aop:pointcut id="pointcut" expression="execution(* com.by.service.*.*(..))"/>
<!--切面(aspect):把增强应用到切点上-->
<aop:advisor advice-ref="txManager" pointcut-ref="pointcut"></aop:advisor>
</aop:config>
注意:方法名必须和事务属性的配置保持一致,eg:get或select开头
<!--开启spring对事务注解的支持-->
<tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven>
@Transactional
public class UserServiceImpl implements UserService {
}