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");
}

补充:

<!--动态代理
truecglib动态代理
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();
      }
   }
}

 

posted @ 2018-12-20 18:09  fly_bk  阅读(96)  评论(0)    收藏  举报