Spring
Spring:
IoC
控制反转(Inversion of Control)
IoC 完成的事情原先由程序员主动通过 new 实例化对象事情,
转交给 Spring 负责.控制反转中控制指的是:控制类的对象.
控制反转中反转指的是转交给 Spring 负责.IoC 最大的作用:解耦
DI
依赖注入(Dependency Injection)
DI 和 IoC 是一样的,当一个类(A)中需要依赖另一个类(B)对象时,
把 B 赋值给 A 的过程就叫做依赖注入.
整合struts入门:
<packaging>war</packaging>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.2.8.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>4.2.8.RELEASE</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-core</artifactId>
<version>2.3.24</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>tomcat7-maven-plugin</artifactId>
<groupId>org.apache.tomcat.maven</groupId>
<version>2.2</version>
<configuration>
<path>/</path>
<port>9002</port>
</configuration>
</plugin>
</plugins>
</build>
</project>
web.xml:
<!--spring监听器 整合web项目-->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
<filter>
<!--指定struts2的核心过滤器-->
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
<!--通过init-param元素配置struts常量-->
<init-param>
<param-name>struts.i18n.encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
applicationContext.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="userDao" class="com.fly.daoimpl.UserDaoImpl"/>
</beans>
struts.xml:
<struts>
<package name="user" extends="struts-default" namespace="/">
<action name="user" class="com.fly.action.UserAction">
</action>
</package>
</struts>
test调用:
public class SpringTest {
@Test
public void demo(){
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
UserDaoImpl userDao = (UserDaoImpl) context.getBean("userDao");
userDao.hello();
}
}
UserAction:
整合web调用:
public class UserAction extends ActionSupport {
@Override
public String execute() throws Exception {
WebApplicationContext context = WebApplicationContextUtils.getWebApplicationContext(ServletActionContext.getServletContext());
UserDaoImpl userDao = (UserDaoImpl) context.getBean("userDao");
userDao.hello();
return NONE;
}
}
注解开发:
applicationContext.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
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/context http://www.springframework.org/schema/context/spring-context.xsd"
>
<!--组件扫描-->
<!--
@Value 用于注入普通类型
@Autowired 自动装配
默认按类型进行装配
@ Qualifier 强制使用名称注入
@Resource 按名称注入
-->
<context:component-scan base-package="com.fly.spring.demo"/>
</beans>
Dao:
//@Component(value = "userDao2")
@Repository(value = "userDao2")
//@Controller// web层
//@Service //业务层
//@Repository//持久层
public class UserDaoImpl2 {
public void hello(){
System.out.println("userDao2 spring...");
}
}
AOP开发:
AOP:面向切面编程(Aspect Oriented Programming)
正常程序执行流程都是纵向执行流程
面向切面编程,在原有纵向执行流程中添加横切面
不需要修改原有程序代码
高扩展性
原有功能相当于释放了部分逻辑.让职责更加明确
常用概念:
原有功能: 切点, pointcut
前置通知: 在切点之前执行的功能. before advice
后置通知: 在切点之后执行的功能,after advice
如果切点执行过程中出现异常,会触发异常通知.throws advice
所有功能总称叫做切面.
织入: 把切面嵌入到原有功能的过程叫做织入
spring 提供了 2 种 AOP 实现方式
Schema-based
每个通知都需要实现接口或类
配置 spring 配置文件时在<aop:config>配置
AspectJ
每个通知不需要实现接口或类
配置 spring 配置文件是在<aop:config>的子标签<aop:aspect>中配置
pom.xml:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>4.2.8.RELEASE</version>
</dependency>
<dependency>
<groupId>aopalliance</groupId>
<artifactId>aopalliance</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>4.2.8.RELEASE</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.8.9</version>
</dependency>
附:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.7.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
AspectJ方式:
applicationContext.xml:
<!--配置切面类-->
<bean id="myAspect" class="com.fly.spring.demo.MyAspect"/>
<!--aop配置-->
<aop:config>
<!--配置切入点表达式:哪些类的哪些方法需要增强-->
<aop:pointcut expression="execution(* com.fly.aop.AopService.*(..))" id="pointcut1" />
<!--配置切面-->
<aop:aspect ref="myAspect">
<aop:before method="before" pointcut-ref="pointcut1"/>
<aop:after method="after" pointcut-ref="pointcut1"/>
<aop:after-returning method="afterReturning" pointcut-ref="pointcut1"/>
<aop:after-throwing method="afterThrowing" pointcut-ref="pointcut1"/>
<aop:around method="around" pointcut-ref="pointcut1"/>
</aop:aspect>
</aop:config>
AopService:
public interface AopService {
void save();
}
AopServiceImpl:
public class AopServiceImpl implements AopService {
public void save(){
System.out.println("save...");
}
}
MyAspect:
public class MyAspect {
//前置通知
//指定该方法是前置通知,并制定切入点
public void before(){
System.out.println("这是前置通知!!");
}
//后置通知
public void afterReturning(){
System.out.println("这是后置通知(如果出现异常不会调用)!!");
}
//环绕通知
public Object around(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("这是环绕通知之前的部分!!");
Object proceed = pjp.proceed();//调用目标方法
System.out.println("这是环绕通知之后的部分!!");
return proceed;
}
//异常通知
public void afterThrowing(){
System.out.println("出事啦!出现异常了!!");
}
//后置通知
public void after(){
System.out.println("这是后置通知(出现异常也会调用)!!");
}
}
测试:
@Resource(name ="aopService")
private AopService aopService;
@Test
public void aopdemoTest(){
aopService.save();
}
切点有参数:
AopDemo:
/**
* 切点有参数
*/
public class AopDemo {
public void demo(String s,int i){
System.out.println("demo...");
}
}
MyAdvice:
public class MyAdvice {
public void myBefore(String name,int age){
System.out.println("前置:name:"+name+",age:"+age);
}
}
applicationContext.xml部分:
<bean id="aopDemo" class="com.fly.aop.AopDemo"/>
<!--aop配置-->
<aop:config>
<!--有参数情况-->
<aop:pointcut expression="execution(* com.fly.aop.AopDemo.demo(String,int)) and args(name,age)" id="pointcut2" />
<aop:aspect ref="myAdvice">
<aop:after method="myBefore" pointcut-ref="pointcut2" arg-names="name,age"/>
</aop:aspect>
</aop:config>
补充异常:
MyThrowAdvice:
/**
* AspectJ 方式
*/
public class MyThrowAdvice {
public void myexception(Exception e){
System.out.println("执行异常通知"+e.getMessage());
}
}
applicationContext.xml:
<bean id="mythrow" class="com.fly.advice.MyThrowAdvice"/>
<!--<aop:aspect ref="mythrow">-->
<!--<aop:after-throwing method="myexception" pointcut-ref="pointcut1" throwing="e"/>-->
<!--</aop:aspect>-->
Schema-based方式:
MyAfterAdvice:
public class MyAfterAdvice implements AfterReturningAdvice {
@Override
public void afterReturning(Object o, Method method, Object[] objects, Object o1) throws Throwable {
System.out.println("切点方法返回值"+o);
System.out.println("切点方法对象:"+method+",方法名:"+method.getName());
if (objects.length>0){
for (Object object : objects) {
System.out.println("切点方法参数"+object);
}
}else {
System.out.println("切点方法无参数");
}
System.out.println("切点方法所在类的对象:"+o1);
System.out.println("执行后置通知");
}
}
MyBeforeAdvice:
public class MyBeforeAdvice implements MethodBeforeAdvice {
@Override
public void before(Method method, Object[] objects, Object o) throws Throwable {
System.out.println("切点方法对象:"+method+",方法名:"+method.getName());
if (objects.length>0){
for (Object object : objects) {
System.out.println("切点方法参数"+object);
}
}else {
System.out.println("切点方法无参数");
}
System.out.println("切点方法所在类的对象:"+o);
System.out.println("执行前置通知");
}
}
MyArround:
/**
* 拦截器实现环绕
* Schema-based 方式
*/
public class MyArround implements MethodInterceptor {
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
System.out.println("环绕-前置");
Object proceed = invocation.proceed();//方行,调用切点方式
System.out.println("环绕-后置");
return proceed;
}
}
MyThrow:
/**
* schema-base 方式
*/
public class MyThrow implements ThrowsAdvice {
public void afterThrowing(Exception ex) throws Throwable{
System.out.println("执行异常通过-schema-base 方式"+ex.getMessage());
}
}
applicationContext.xml:
<!--Schema-based方式
每个通知都需要实现接口或类
-->
<bean id="mybefore" class="com.fly.advice.MyBeforeAdvice"/>
<bean id="myafter" class="com.fly.advice.MyAfterAdvice"/>
<bean id="myarround" class="com.fly.advice.MyArround"/>
<bean id="mythrow1" class="com.fly.advice.MyThrow"/>
<!--Schema-based方式-->
<!--<aop:advisor advice-ref="mybefore" pointcut-ref="pointcut1"/>-->
<!--<aop:advisor advice-ref="myafter" pointcut-ref="pointcut1"/>-->
<!--<aop:advisor advice-ref="mythrow1" pointcut-ref="pointcut1"/>-->
<!--<aop:advisor advice-ref="myarround" pointcut-ref="pointcut1"/>-->
AOP注解开发:
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.2.8.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>4.2.8.RELEASE</version>
</dependency>
<dependency>
<groupId>aopalliance</groupId>
<artifactId>aopalliance</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>4.2.8.RELEASE</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.8.9</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>4.2.8.RELEASE</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.7.0</version>
<configuration>
<target>1.8</target>
<source>1.8</source>
</configuration>
</plugin>
</plugins>
</build>
applicationContext.xml:
<!--aop注解自动代理-->
<aop:aspectj-autoproxy/>
<!--目标类-->
<bean id="userDao" class="com.fly.dao.UserDaoImpl"/>
<bean id="myAspect" class="com.fly.aspect.MyAspect"/>
MyAspect:
@Aspect //定义切面类的注解
public class MyAspect {
//定义切入点
@Pointcut("execution(* com.fly.dao.UserDao.save())")
private void pointcut1(){}
@Pointcut("execution(* com.fly.dao.UserDao.find())")
private void pointcut2(){}
@Before("MyAspect.pointcut1()")
public void before(){
System.out.println("前置通知...");
}
@After("MyAspect.pointcut1()")
public void after(){
System.out.println("最终通知...");
}
@AfterReturning("MyAspect.pointcut1()")
public void afterReturning(){
System.out.println("后置通知...");
}
@AfterThrowing("MyAspect.pointcut1()")
public void afterThrowing(){
System.out.println("后置有异常也通知...");
}
@Around("MyAspect.pointcut1()")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("环绕通知...");
Object o = joinPoint.proceed();
System.out.println("环绕通知...");
return o;
}
}
UserDaoImpl:
public class UserDaoImpl implements UserDao {
public void save(){
System.out.println("save...");
}
public void find(){
System.out.println("find...");
}
}
测试:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class AOPTest {
@Resource
private UserDao userDao;
@Test
public void demo(){
userDao.find();
userDao.save();
}
}
数据库连接:
/**
* 方式一:
*/
@Test
public void demo1(){
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql:///stus");
dataSource.setUsername("root");
dataSource.setPassword("root");
JdbcTemplate template = new JdbcTemplate(dataSource);
template.update("insert into words value (null,?)","AAA");
}
方式二:
<!--引入外部属性文件 方式一-->
<!-- <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="classpath:jdbc.properties"/>
</bean>-->
<!--引入外部属性文件 方式二-->
<context:property-placeholder location="classpath:jdbc.properties"/>
<!--spring内置连接池-->
<!--<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">-->
<!--配置dbcp连接池-->
<!--<bean id="dataSource" class="org.apache.tomcat.dbcp.dbcp.BasicDataSource">-->
<!-- <bean id="dataSource" class="org.apache.tomcat.dbcp.dbcp.BasicDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql:///stus"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</bean>-->
<!--配置c3p0连接池-->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${jdbc.driverClass}"/>
<property name="jdbcUrl" value="${jdbc.url}"/>
<property name="user" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
<!--配置jdbc模板-->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"/>
</bean>
jdbc.properties:
jdbc.driverClass=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql:///stus
jdbc.username=root
jdbc.password=root
测试:
@Resource
private JdbcTemplate jdbcTemplate;
@Test
public void demo2(){
jdbcTemplate.update("insert into words value (null,?)","AAAA");
}
补充:
<!--动态代理
true:cglib动态代理
false: jdk动态代理
-->
<!--<aop:aspectj-autoproxy proxy-target-class="true"/>-->
补充:静态代理设计模式:
fun:
/**
* 代理功能接口
*/
public interface fun {
void eat();
void meet();
}
boss:
public class boss implements fun{
@Override
public void eat() {
System.out.println("eat...");
}
@Override
public void meet() {
System.out.println("meeting...");
}
}
secretary:
/**
* boss代理类
*/
public class secretary implements fun {
private boss boss = new boss();
@Override
public void eat() {
System.out.println("before ..eat..");
boss.eat();
System.out.println("after ..eat..");
}
@Override
public void meet() {
System.out.println("before ..meet..");
boss.meet();
System.out.println("after ..meet..");
}
}
staff:
public class staff {
public static void main(String[] args){
secretary secretary = new secretary();
secretary.meet();
}
}
动态代理:jdk
真实对象必须实现接口
利用反射机制
fun:
public interface fun {
void eat(String name);
void meet();
}
boss:
public class boss implements fun{
@Override
public void eat(String name) {
System.out.println("eat..."+name);
}
@Override
public void meet() {
System.out.println("meeting...");
}
}
secretary:
public class secretary implements InvocationHandler {
private boss b = new boss();
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result;
if (method.getName().equals("eat")){
System.out.println("before..eat..");
result = method.invoke(b,args);
System.out.println("after..eat..");
}
else if (method.getName().equals("meet")){
System.out.println("before..meet..");
result = method.invoke(b);
System.out.println("after..meet..");
}else {
result = method.invoke(b,args);
}
return result;
}
}
staff:
public class staff {
public static void main(String[] args){
secretary secretary = new secretary();
//第一个参数:反射时使用的类加载器
//第二个参数:Proxy需要实现什么接口
//第三个参数:通过接口对象调用方法时,需要调用哪个类的invoke方法
fun f = (fun) Proxy.newProxyInstance(staff.class.getClassLoader(), new Class[]{fun.class}, secretary);
f.eat("aaa");
f.meet();
}
}
补充:cglib 动态代理
基于字节码,生成真实对象的子类
运行效率高于 JDK 动态代理
不需要实现接口
需要额外导入 jar
boss:
public class boss{
public void eat(String name) {
System.out.println("eat..."+name);
}
public void meet() {
System.out.println("meeting...");
}
}
secretary:
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
public class secretary implements MethodInterceptor {
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
Object result;
if (method.getName().equals("eat")){
System.out.println("before..eat..");
result = methodProxy.invokeSuper(o,objects);
System.out.println("after..eat..");
}else if (method.getName().equals("meet")){
System.out.println("before..meet..");
result = methodProxy.invokeSuper(o,objects);
System.out.println("after..meet..");
}else {
result = methodProxy.invokeSuper(o,objects);
}
return result;
}
}
staff:
import org.springframework.cglib.proxy.Enhancer;
public class staff {
public static void main(String[] args){
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(boss.class);
enhancer.setCallback(new secretary());
boss b = (boss) enhancer.create();
b.eat("aaa");
b.meet();
}
}
补充:获取配置文件的值
在被Spring管理的类中通过@Value(“${key}”)取出properties中内容
添加注解扫描
<context:component-scan base-package="com.bjsxt.service.impl"></context:component-scan>
在类中添加
@Value("${my.demo}")
private String test;
bean的scope 属性
scope 可取值:
singleton 默认值,单例
prototype 多例,每次获取重新实例化
request 每次请求重新实例化
session 每个会话对象内,对象是单例的. 4.5 application 在 application 对象内是单例
global session spring 推 出 的 一 个 对 象 , 依 赖 于spring-webmvc-portlet ,类似于 session
事务相关:
<bean id="userDao" class="com.fly.dao.UserDaoImpl"/>
<bean id="userService" class="com.fly.service.impl.UserServiceImpl"></bean>
<!--事务管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!--配置事务的增强-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<!--
isolation="DEFAULT"隔离级别
propagation="REQUIRED" 传播行为
read-only="false" 只读
timeout="-1" 过期时间
..
-->
<tx:method name="transfer" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
<!--配置aop事务-->
<aop:config>
<aop:pointcut id="pointcut1" expression="execution(* com.fly.dao.UserDaoImpl.find(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut1"/>
</aop:config>
<!--开启注解事务管理-->
<tx:annotation-driven transaction-manager="transactionManager"/>
UserServiceImpl:
@Transactional
public class UserServiceImpl implements UserService {
@Resource
private UserDao userDao;
@Override
public void sava(String v) {
userDao.save(v);
}
}
补充:
声明式事务中属性解释
name=”” 哪些方法需要有事务控制 支持*通配符
readonly=”boolean” 是否是只读事务.
如果为 true,告诉数据库此事务为只读事务.只要是查询的方法,建议使用此数据.
如果为 false(默认值),事务需要提交的事务.建议新增,删除,修改
propagation 控制事务传播行为.当一个具有事务控制的方法被另一个有事务控制的方法调用后,需要如何管理事务
* REQUIRED (默认值): 如果当前有事务,就在事务中执行,如果当前没有事务,新建一个事务
* SUPPORTS:如果当前有事务就在事务中执行,如果当前没有事务,就在非事务状态下执行.
* MANDATORY:必须在事务内部执行,如果当前有事务,就在事务中执行,如果没有事务,报错.
* REQUIRES_ NEW:必须在事务中执行,如果当前没有事务,新建务,如果当前有事务,把当前事务挂起
* NOT_ SUPPORTED:必须在非事务下执行,如果当前没有事务,正常执行,如果当前有事务,把当前事务挂起.
* NEVER:必须在非事务状态下执行,如果当前没有事务,正常执行, 如果当前有事务,报错.
* NESTED:必须在事务状态下执行.如果没有事务,新建事务,如果当前有事务,创建一个嵌套事务
isolation=”” 事务隔离级别,在多线程或并发访问下如何保证访问到的数据具有完整性的.
脏读:
一个事务(A)读取到另一个事务(B)中未提交的数据,另一个事务中数据可能进行了改变,此时 A事务读取的数据可能和数据库中数据是不一致的,此时认为数据是脏数据,读取脏数据过程叫做脏读
不可重复读:
主要针对的是某行数据.(或行中某列),操作是修改操作.
两次读取在同一个事务内
当事务 A 第一次读取事务后,事务 B 对事务 A 读取的数据进行修改,事务 A 中再次读取的数据和之前读取的数据不一致,过程不可重复读
幻读:
主要针对的操作是新增或删除
两次事务的结果.
事务 A 按照特定条件查询出结果,事务 B 新增了一条符合条件的数据.事务 A 中查询的数据和数据库中的数据不一致的,事务 A 好像出现了幻觉,这种情况称为幻读
DEFAULT: 默认值,由底层数据库自动判断应该使用什么隔离界别
READ_ UNCOMMITTED: 可以读取未提交数据,可能出现脏读,不重复读,幻读. 效率最高.
READ_ COMMITTED:只能读取其他事务已提交数据.可以防止脏读,可能出现不可重复读和幻读
REPEATABLE_ READ: 读取的数据被添加锁,防止其他事务修改此数据,可以防止不可重复读.脏读,可能出现幻读.
SERIALIZABLE: 排队操作,对整个表添加锁.一个事务在操作数据时,另一个事务等待事务操作完成后才能操作这个表.,最安全的,效率最低的
rollback-for=”异常类型全限定路径”当出现什么异常时需要进行回滚建议:给定该属性值.手动抛异常一定要给该属性值.
no-rollback-for=””,当出现什么异常时不滚回事务
@Resource(不需要写对象的 get/set)5.1 java 中的注解,默认按照 byName 注入,如果没有名称对象,按照 byType 注入,建议把对象名称和 spring 容器中对象名相同
@Autowired(不需要写对象的 get/set),spring 的注解,默认按照 byType 注入
补充:容器初始化流程
ContextLoaderListener/DispatcherServlet->WebApplicationContext
public abstract class AbstractApplicationContext extends DefaultResourceLoader
implements ConfigurableApplicationContext {
ApplicationContext 容器的初始化流程主要由 AbstractApplicationContext 类中的 refresh方法实现
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
prepareRefresh();
// 告诉子类刷新内部bean工厂
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);
try {
//在上下文子类中对bean工厂进行后处理。
postProcessBeanFactory(beanFactory);
//在上下文中调用注册为bean的工厂处理器。
//底层实质是在将 postProcessBeanFactory 中加载的内容包装成一个容器 ApplicationContext 可以管理的 bean 对象
invokeBeanFactoryPostProcessors(beanFactory);
//配置文件中配置的 bean 对象都创建并注册完成
registerBeanPostProcessors(beanFactory);
//i18n,国际化。初始化国际化消息源
initMessageSource();
// 注册事件多播监听。如 ApplicationEvent 事件。是 spring框架中的观察者模式实现机制
initApplicationEventMulticaster();
// In初始化主题资源(ThemeSource)
onRefresh();
// 创建监听器,并注册。
registerListeners();
// 实例化所有剩余(非延迟初始化)单例。
finishBeanFactoryInitialization(beanFactory);
// 最后一步。发布相应的事件
finishRefresh();
}
catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
// 摧毁已经创建的单例以避免悬空资源
destroyBeans();
// 重置'有效'标志。
cancelRefresh(ex);
//向调用者传播异常
throw ex;
}
finally {
// 重置Spring核心中的常见内省缓存
resetCommonCaches();
}
}
}

浙公网安备 33010602011771号