一.spring

1.spring体系结构

(1)核心容器(core container):由spring-core,spring-beans,spring-context和spring-expression(SpEL,Spring表达式语言,Spring Expression Language)等模块组成

(2)数据访问(data access):jdbc,orm(jpa,heribate),transactions

(3)web:web,web-mvc,web-socket

(4)其它:aop,AspectJ,测试模块(JUnit)

2.ApplicationContext三个常见实现类

(1).classPathXmlApplicationContext:加载类路径下的配置文件(要求配置文件必须在类路径下,不在的话就加载不了)

(2).FileSystemXmlApplicationContext:加载磁盘任意路径下的配置文件(必须有访问权限)

(3).AnnotationConfigApplicationContext:读取注解创建容器

3.BeanFactory和ApplicationContext区别?

ApplicationContext继承BeanFactory接口,是一种更高级的容器,提供了更多功能(Aop,国际化,消息发送)

区别:BeanFactory在启动的时候不会实例化Bean,从容器拿bean的时候才会实例化。ApplicationContext在启动的时候就把所有Bean实例化

4.配置详解

<?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 https://www.springframework.org/schema/context/spring-context.xsd"> <!--mybatis -->
<context:property-placeholder location="classpath:jdbc.properties" system-properties-mode="NEVER"/>
<bean name="dataSouce" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="url" value="${url}"/>
<property name="username" value="${user}"/>
<property name="password" value="${password}"/>
<property name="driverClassName" value="${driver}"/>
</bean> <bean class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSouce"/>
</bean> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.kkb.dao"/>
</bean>
<!--mybatis END --> <!--注解扫描 -->
<context:component-scan base-package="com.kkb.service"/> </beans>

(1)bean元素:使用该元素描述需要spring容器管理对象

(2)name属性:给被管理的对象起个名字,获得对象时getBean("name值")

(3)class属性:被管理对象的完整类名

(4)id属性:与name属性一模一样,名称不可重复,不能使用特殊字符

id与name的区别?

①id是唯一的,配置文件中不允许出现两个id相同的。中允许出现两个name相同的,在用getBean()返回实例时,后面一个Bean被返回

②如果没有配置id和name,则用类的全名作为name

(5)scope:singleton,prototype,request,session

绝大多数情况下,使用单例singleton(默认值),但是在与struts整合时候,务必要用prototype多例,因为struts2在每次请求都会创建一个新的Action,若为单例,在多请求情况下,每个请求找找spring拿的都是同一个action

(6)初始化和销毁:init-method,destory-method。spring会在对象创建之后立刻调用 init-method 对应注解为@PreDestory,spring容器在关闭并销毁所有容器中的对象之前调用destory-method对应注解为@PostConstruct

5.spring三种对象的创建方式

(1)空参构造

<!-- 使用无参构造函数创建对象 -->
<bean id="bean3" class="cn.itcast.beans.Bean3"></bean>

(2)静态工厂创建

<!-- 静态工厂创建(调用静态方法创建) -->
<bean name="user" class="cn.itcats.UserFactory" factory-method="createUser"></bean> public class Bean1_factory {
public static Bean1 getBean(){
return new Bean1();
}
}
public class Bean1 {
public void add(){
System.out.println("bean1 ........");
}
}

(3)实例工厂

需要配置两个bean,因为无法通过类名调用非静态方法

<!-- 使用实例工厂创建对象 -->
<bean id="bean2_fcty" class="cn.itcast.beans.Bean2_factory">
<bean id="bean2" factory-bean="bean2_fcty" factory-method="getBean"></bean>
public class Bean2_factory {
public Bean2 getBean(){
return new Bean2();
}
}
public class Bean2 {
public void add(){
System.out.println("bean2 ........");
}
}

6.spring注入方式

(1)构造方法注入

使用对象的话,应改用ref属性

<bean id="user" class="bean.User">
<constructor-arg index="0" name="username" value="zhangsan"></constructor-arg>
<constructor-arg index="1" name="password" value="1234"></constructor-arg>
</bean>

(2)set注入

与构造器注入相比,只是少了index属性

<bean id="userService" class="com.lyu.spring.service.impl.UserService">
<property name="userDao" ref="userDaoMyBatis"></property>
</bean>

(3)注解注入

①引用类型注入:

@Autowired:spring注解,默认是以byType的方式去匹配,如果没有找到,就通过byName的方式去查找

@Resource:java的注解,默认以byName的方式去匹配,如果没有找到就会以byType的方式查找

@Qualifier:(spring注解)指定某个具体名称的bean(配合autowired和resource使用)

②值类型注入

@Value("kaka")

@Resource
@Qualifier("userDaoMyBatis")
private IUserDao userDao;
public UserService(){
@Autowired
@Qualifier("userDaoJdbc")
private IUserDao userDao;

7.复杂类型注入

<!-- 注入复杂类型属性 -->

<bean id="user" class="com.siwuxie095.property.User">

	<!-- 数组 -->
<property name="arr">
<list>
<value>小孙</value>
<value>小李</value>
</list>
</property> <!-- List 集合 -->
<property name="list">
<list>
<value>张三</value>
<value>李四</value>
<value>王五</value>
</list>
</property> <!-- Map 集合 -->
<property name="map">
<map>
<entry key="a" value="老大"></entry>
<entry key="b" value="老二"></entry>
</map>
</property> <!-- Properties 类型 -->
<property name="properties">
<props>
<prop key="username">root</prop>
<prop key="password">8888</prop>
</props>
</property>
</bean>

8.web.xml中spring的配置

<!--spring随项目的创建而创建,随项目的关闭而关闭,避免创建多个ApplicationContext-->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!--指定加载spring配置文件的位置-->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param>

9.spring整合junit

@RunWith(SpringJUnit4ClassRunner.class) //RunWith用于指定junit运行环境,是junit提供给其他框架测试环境接口扩展
@ContextConfiguration("classpath:applicationContext.xml") //配置xml文件
public class Demo { @Autowired
private User user; @Test
public void fun01() {
System.out.println(user);
}
}

10.spring的aop中名词解释

(1)JoinPoint(连接点):目标对象中,所有可以增强的方法,就是spring允许你是通知(Advice)的地方,那可就真多了,基本每个方法的前、后(两者都有也行),或抛出异常是时都可以是连接点,spring只支持方法连接点。

(2)Pointcut(切入点):目标对象中,已经被增强的方法。调用这几个方法之前、之后或者抛出异常时干点什么,那么就用切入点来定义这几个方法。

(3)Advice(通知/增强) :增强方法的代码、想要的功能

(4)Target(目标对象):被代理对象,被通知的对象,被增强的类对象

(5)Weaving(织入):将通知应用到连接点形成切入点的过程

(6)Proxy(代理):将通知织入到目标对象之后形成的代理对象

(7)aspect(切面):切入点+通知

11.aop实现(基于注解)

@Before 前置通知(Before advice) :在某连接点(JoinPoint)——核心代码(类或者方法)之前执行的通知,但这个通知不能阻止连接点前的执行。为啥不能阻止线程进入核心代码呢?因为@Before注解的方法入参不能传ProceedingJoinPoint,而只能传入JoinPoint。要知道从aop走到核心代码就是通过调用ProceedingJionPoint的proceed()方法。而JoinPoint没有这个方法。

这里牵扯区别这两个类:Proceedingjoinpoint 继承了 JoinPoint 。是在JoinPoint的基础上暴露出 proceed 这个方法。proceed很重要,这个是aop代理链执行的方法。暴露出这个方法,就能支持 aop:around 这种切面(而其他的几种切面只需要用到JoinPoint,这跟切面类型有关), 能决定是否走代理链还是走自己拦截的其他逻辑。建议看一下 JdkDynamicAopProxy的invoke方法,了解一下代理链的执行原理。这样你就能明白 proceed方法的重要性。

@After 后通知(After advice) :当某连接点退出的时候执行的通知(不论是正常返回还是异常退出)。

@AfterReturning 返回后通知(After return advice) :在某连接点正常完成后执行的通知,不包括抛出异常的情况。

@Around 环绕通知(Around advice) :包围一个连接点的通知,类似Web中Servlet规范中的Filter的doFilter方法。可以在方法的调用前后完成自定义的行为,也可以选择不执行。这时aop的最重要的,最常用的注解。用这个注解的方法入参传的是ProceedingJionPoint pjp,可以决定当前线程能否进入核心方法中——通过调用pjp.proceed();

@AfterThrowing 抛出异常后通知(After throwing advice) : 在方法抛出异常退出时执行的通知。

@Aspect //@Aspect注解代表该类是个通知类,书写切点表达式@Pointcut("execution(返回值 全类名.方法名(参数))")
public class LogAspect { //抽取公共的切入点表达式
//1、本类引用
//2、其他的切面引用
@Pointcut("execution(* com.gz.MathCalculator.*(..))")
public void pointCut(){}; @Before("pointCut()")
public void logStart(JoinPoint joinPoint){
Object[] args = joinPoint.getArgs();
System.out.println(""+joinPoint.getSignature().getName()+"运行。。。@Before:参数列表是:{"+Arrays.asList(args)+"}");
} @After("com.gz.LogAspect.pointCut()")
public void logEnd(JoinPoint joinPoint){
System.out.println(""+joinPoint.getSignature().getName()+"结束。。。@After");
} @AfterReturning(value="pointCut()",returning="result")
public void logReturn(JoinPoint joinPoint,Object result){
System.out.println(""+joinPoint.getSignature().getName()+"正常返回。。。@AfterReturning:运行结果:{"+result+"}");
} @AfterThrowing(value="pointCut()",throwing="exception")
public void logException(JoinPoint joinPoint,Exception exception){
System.out.println(""+joinPoint.getSignature().getName()+"异常。。。异常信息:{"+exception+"}");
} }

(1)@Before 前置通知(Before advice) :在某连接点(JoinPoint)之前执行的通知

(2)@After 后通知(After advice) :当某连接点退出的时候执行的通知(不论是正常返回还是异常退出)

(3)@AfterReturning 返回后通知(After return advice) :在某连接点正常完成后执行的通知,不包括抛出异常的情况

(4)@AfterThrowing 抛出异常后通知(After throwing advice) : 在方法抛出异常退出时执行的通知

(5)@Around 环绕通知(Around advice):包围一个连接点的通知,类似Web中Servlet规范中的Filter的doFilter方法。可以在方法的调用前后完成自定义的行为,也可以选择不执行

12.spring中事务

spring中事务可以分为编程式事务控制和声明式事务控制

编程式事务:自己手动控制事务,就叫做编程式事务控制。 【细粒度的事务控制: 可以对指定的方法、指定的方法的某几行添加事务控制】比较灵活,但开发起来比较繁琐: 每次都要开启、提交、回滚

声明式事务:Spring提供了对事务的管理, 这个就叫声明式事务管理【粗粒度的事务控制: 只能给整个方法应用事务,不可以对方法的某几行应用事务】 (因为aop拦截的是方法)

13.事务传播行为

事务传播行为(propagation behavior)指的就是当一个事务方法被另一个事务方法调用时,这个事务方法应该如何进行。

例如:methodA事务方法调用methodB事务方法时,methodB是继续在调用者methodA的事务中运行呢,还是为自己开启一个新事务运行,这就是由methodB的事务传播行为决定的。

(1)propagation_required:如果存在一个事务,则支持当前事务。如果没有事务则开启一个新的事务。



(2)propagation_supports:如果存在一个事务,支持当前事务。如果没有事务,则非事务的执行

@Transactional(propagation = Propagation.REQUIRED)
public void methodA() {
methodB();
// do something
} // 事务属性为SUPPORTS
@Transactional(propagation = Propagation.SUPPORTS)
public void methodB() {
// do something
}
单纯的调用methodB时,methodB方法是非事务的执行的。当调用methdA时,methodB则加入了methodA的事务中,事务地执行

(3)propagation_mandatory:如果已经存在一个事务,支持当前事务。如果没有一个活动的事务,则抛出异常

(4)propagation_requires_new:它会开启一个新的事务。如果一个事务已经存在,则先将这个存在的事务挂起(需要使用 JtaTransactionManager作为事务管理器)



(5)propagation_not_supported:总是非事务地执行,并挂起任何存在的事务。使用PROPAGATION_NOT_SUPPORTED(也需要使用JtaTransactionManager作为事务管理器)

(6)propagation_never:总是非事务地执行,如果存在一个活动事务,则抛出异常。

(7)propagation_nested: 如果一个活动的事务存在,则运行在一个嵌套的事务中。 如果没有活动事务, 则按propagation_required属性执行(嵌套事务一个非常重要的概念就是内层事务依赖于外层事务。外层事务失败时,会回滚内层事务所做的动作。而内层事务操作失败并不会引起外层事务的回滚)

14.propagation_nested 与propagation_requires_new的区别?

它们非常类似,都像一个嵌套事务,如果不存在一个活动的事务,都会开启一个新的事务。

(1)使用 PROPAGATION_REQUIRES_NEW时,内层事务与外层事务就像两个独立的事务一样,一旦内层事务进行了提交后,外层事务不能对其进行回滚。两个事务互不影响。两个事务不是一个真正的嵌套事务。同时它需要JTA事务管理器的支持。

(2)使用PROPAGATION_NESTED时,外层事务的回滚可以引起内层事务的回滚。而内层事务的异常并不会导致外层事务的回滚,它是一个真正的嵌套事务。DataSourceTransactionManager支持

15.aop管理事务(注解)

(1)开启注解

<tx:annotation-driven/>

(2)方法上增加@Transactional注解方法就可以被事务管理起来

@Transactional注解的属性:

readOnly : 是否仅仅只读。默认读写都可以

timeout : 事务超时时间,默认没有超时时间

isolation: 事务的隔离级别 默认:TransactionDefinition.ISOLATION_DEFAULT(大部分数据库的默认隔离级别是可重复读)

propagation :事务的传播属性 默认:TransactionDefinition.PROPAGATION_REQUIRED

最新文章

  1. Android Studio--学习系列(2)
  2. .NET在线培训 | C#在线培训 | .NET培训 | 最课程培训
  3. ubuntu 登录循环
  4. Cloudera CDH5 部署实战指南(离线安装)
  5. bootstrap 框架选型过程
  6. GeoServer地图开发解决方案
  7. 增加配置Apache2 管理 SVN 访问权限
  8. OKR 方法 学习笔记
  9. Excel 2010去掉网格线
  10. 第20月第9天 paddlepaddle
  11. HDU 2062:Subset sequence(思维)
  12. php动态获取常量
  13. ASP.NET Core 2.0 Preview 1 中贴心的新特性
  14. 处理AsyncTask的内存泄漏问题
  15. springboots Helloworld
  16. Struts,Spring,Hibernate优缺点
  17. BIOS设置图解教程-看完就没有不明白的了
  18. weui-switch开关控件,表单提交后如何取值
  19. Daily Scrum02 12.01
  20. Python 多继承(新式类) 的mro算法

热门文章

  1. MySql-8.0.x免安装版下载与配置,Navicat打开数据库链接报错1251的解决办法
  2. Java知识系统回顾整理01基础04操作符02关系操作符
  3. opencv中namedWindow( )函数
  4. 一键安装PyCharm
  5. 跟我一起学.NetCore之WebApi接口裸奔有风险(Jwt)
  6. Oracle 数据库导入数据和编码问题
  7. c++ 西安交通大学 mooc 第十三周基础练习&amp;第十三周编程作业
  8. git冲突的表现
  9. centos 6.4 配置本地yum源(iso镜像)
  10. java的各种集合为什么不安全(List、Set、Map)以及代替方案