Spring 核心组件总结

spring核心组件总结

spring介绍

2018-09-29_114847

spring概念

IOC: Inverse Of Control 控制反转

​ 将我们创建对象的方式反转了,以前创建对象是由我们开发人员自己维护,包括依赖注入关系也是自己注入。

​ 使用了spring之后,对象的创建以及依赖关系,由spring完成创建以及注入。

​ 控制反转就是反转了对象的创建方式。从我们自己创建反转给了spring

2018-09-29_112547

DI: Dependency Injection 依赖注入

​ 实现ioc思想需要 DI提供支持

​ 注入方式:1)set方式注入 2) 构造方法注入 3) 字段注入(不推荐)

​ 注入类型:1) 值类型注入 2)引用类型注入

AOP 面向切面的编程 (横向重复,纵向抽取)

举例:拦截器(身份校验)、过滤器(编码处理)、动态代理(事务)

spring aop实现原理

动态代理(优先):被代理对象必须要实现接口,才能产生代理对象.如果没有接口将不能使用动态代理技术

cglib代理(没有接口):第三方代理技术,cglib代理.可以对任何类生成代理.代理的原理是对目标对象进行继承代理. 如果目标对象被final修饰.那么该类无法被cglib代理.

spring名词解释

2018-09-29_183858

aop依赖所需包

2018-09-29_233628

aop代码演示(xml配置)

//通知类
public class MyAdvice {
	//前置通知	
	//	|-目标方法运行之前调用
	//后置通知(如果出现异常不会调用)
	//	|-在目标方法运行之后调用
	//环绕通知
	//	|-在目标方法之前和之后都调用
	//异常拦截通知
	//	|-如果出现异常,就会调用
	//后置通知(无论是否出现 异常都会调用)
	//	|-在目标方法运行之后调用
	//----------------------------------------------------------------
	//前置通知
	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 afterException(){
		System.out.println("这是异常通知,出现异常执行!");
	}
	//后置通知
	public void after(){
		System.out.println("这是后置通知(出现异常也会调用)!!");
	}
}
	<!-- 1.配置目标对象 -->
	<bean name="userService" class="com.yoci.service.UserServiceImpl"></bean>

	<!-- 2.配置通知对象 -->
	<bean name="myAdvice" class="com.yoci.springaop.MyAdvice"></bean>

	<!-- 3.配置将通知织入目标对象 -->
	<aop:config>
		<!-- 配置切入点 
			public void cn.itcast.service.UserServiceImpl.save() 
			void cn.itcast.service.UserServiceImpl.save()
			* cn.itcast.service.UserServiceImpl.save()
			* cn.itcast.service.UserServiceImpl.*()
			* cn.itcast.service.*ServiceImpl.*(..)
			* cn.itcast.service..*ServiceImpl.*(..)
		-->
		<aop:pointcut expression="execution(* com.yoci.service.*ServiceImpl.*(..))" id="pc"/>
		<aop:aspect ref="myAdvice">
			<!-- 指定名为before方法作为前置通知 -->
			<aop:before method="before" pointcut-ref="pc"/>
			<!-- 后置 -->
			<aop:after-returning method="afterReturning" pointcut-ref="pc" />
			<!-- 环绕通知 -->
			<aop:around method="around" pointcut-ref="pc"/>
			<!-- 异常拦截通知 -->
			<aop:after-throwing method="afterException" pointcut-ref="pc"/>
			<!-- 后置 -->
			<aop:after method="after" pointcut-ref="pc"/>
		</aop:aspect>
	</aop:config>

aop代码演示(注解配置)

//通知类
@Aspect
public class MyAdvice {

	@Pointcut("execution(* com.yoci.service.*ServiceImpl.*(..))")
	public void pointcut(){}
	
	@Before("MyAdvice.pointcut()")
	public void before(){
		System.out.println("这是前置通知");
	}
	@AfterReturning("execution(* com.yoci.service.*ServiceImpl.*(..))")
	public void afterReturning(){
		System.out.println("这是后置通知(出现异常不执行)!!");
	}

	@Around("execution(* com.yoci.service.*ServiceImpl.*(..))")
	public Object around(ProceedingJoinPoint pjp) throws Throwable {
		System.out.println("这是环绕通知之前的部分!");
		Object proceed = pjp.proceed();//调用目标方法
		System.out.println("这是环绕通知之后的部分");
		return proceed;
	}
	
	@AfterThrowing("execution(* com.yoci.service.*ServiceImpl.*(..))")
	public void afterException(){
		System.out.println("这是异常通知,出现异常执行!");
	}

	@After("execution(* com.yoci.service.*ServiceImpl.*(..))")
	public void after(){
		System.out.println("这是后置通知(出现异常也会调用)!!");
	}
}
	<!-- 1.配置目标对象 -->
	<bean name="userService" class="com.yoci.service.UserServiceImpl"></bean>

	<!-- 2.配置通知对象 -->
	<bean name="myAdvice" class="com.yoci.annotationaop.MyAdvice"></bean>

	<!-- 3.开启使用注解完成织入 -->
	<aop:aspectj-autoproxy></aop:aspectj-autoproxy>

spring 中的工厂(容器)

2018-09-29_144133

​ ApplicationContext接口由两个实现类:

​ 1) ClassPathXmlApplicationContext: 加载类路径下的spring的配置

​ 2)FilesSystemXmlApplicationContext:加载本地磁盘下的spring的配置

​ BeanFactrory(过时)

BeanFactory和ApplicationContext的区别:

​ 1)BeanFactory:是在getBean的时候才会生成类的实例

​ 2)ApplicationContext:是在加载applicationContext.xml(容器启动)时就会创建

spring配置详解

Bean元素

	<!-- 将User对象交给spring容器管理 -->
	<!-- Bean元素:使用该元素描述需要spring容器管理的对象
			class属性:被管理对象的完整类名.
			name属性:给被管理的对象起个名字.获得对象时根据该名称获得对象.  
					可以重复.可以使用特殊字符.
			id属性: 与name属性一模一样. 
					名称不可重复.不能使用特殊字符.
			结论: 尽量使用name属性.
	  -->
	<bean  name="user" class="cn.itcast.bean.User" ></bean>

	<!-- 导入其他spring配置文件 -->
	<!-- 分模块配置 -->
	<import resource="cn/itcast/b_create/applicationContext.xml"/>

Bean元素进阶

​ scope属性(作用域)

1)singleton(默认值):单例对象.被标识为单例的对象在spring容器中只会存在一个实例

2)prototype:多例原型.被标识为多例的对象,每次再获得才会创建.每次创建都是新的对象.整合struts2时,ActionBean必须配置为多例的.

​ 3)request:web环境下.对象与request生命周期一致.

​ 4)session:web环境下,对象与session生命周期一致.

​ 5)global-session:global-session和Portlet应用相关。当你的应用部署在Portlet容器中工作时,它包含很多portlet。如果你想要声明让所有的portlet共用全局的存储变量的话,那么这全局变量需要存储在global-session中。

​ 生命周期属性

​ 1)init-method:配置一个方法作为生命周期初始化方法.spring会在对象创建之后立即调用.

​ 2)destory-method:配置一个方法作为生命周期的销毁方法.spring容器在关闭并销毁所有容器中的对象之前调用.

<bean  name="user" class="cn.itcast.bean.User"
		 init-method="init" destroy-method="destory" ></bean>
public class User {
	private String name;
	private Integer age;
	private Car car;

	public Car getCar() {return car;}
	public void setCar(Car car) {this.car = car;}
	public String getName() {return name;}
	public void setName(String name) {this.name = name;}
	public Integer getAge() {return age;}
	public void setAge(Integer age) {this.age = age;}
  
	public void init(){
		System.out.println("我是初始化方法!");
	}
	public void destory(){
		System.out.println("我是销毁方法!");
	}
	@Override
	public String toString() {
		return "User [name=" + name + ", age=" + age + ", car=" + car + "]";
	}
	
}

spring创建对象的方式

​ 1)空参构造方式

​ 2)静态工厂(了解)

​ 3)实例工厂(了解)

	<!-- 创建方式1:空参构造创建  -->
	<bean  name="user" class="cn.itcast.bean.User"
		 init-method="init" destroy-method="destory" ></bean>

	<!-- 创建方式2:静态工厂创建 
		  调用UserFactory的createUser方法创建名为user2的对象.放入容器
	 -->
	<bean  name="user2" 
		class="cn.itcast.b_create.UserFactory" 
		factory-method="createUser" ></bean>

	<!-- 创建方式3:实例工厂创建 
		 调用UserFactory对象的createUser2方法创建名为user3的对象.放入容器
	 -->
	<bean  name="user3" 
		factory-bean="userFactory"
		factory-method="createUser2" ></bean>
		
	<bean  name="userFactory" 
		class="cn.itcast.b_create.UserFactory"   ></bean>
public class UserFactory {

	public static User createUser(){
		
		System.out.println("静态工厂创建User");
		
		return new User();
		
	}
	
	public  User createUser2(){
		
		System.out.println("实例工厂创建User");
		
		return new User();
		
	}
	
}

spring属性注入

	<!-- set方式注入: -->
	<bean name="user" class="com.yoci.entity.User" >
		<!-- 值类型注入 -->
		<property name="name" value="zhangsan"></property>
		<property name="age" value="22"></property>
		<!-- 引用类型注入 -->
		<property name="car" ref="car"></property>
	</bean>
	
	<!-- 将car对象配置到容器当中 -->
	<bean name="car" class="com.yoci.entity.Car">
		<property name="name" value="兰博基尼"></property>
		<property name="color" value="黄色"></property>
	</bean>
	
	
	<!-- 构造函数注入 -->
	<bean name="user1" class="com.yoci.entity.User">
		<!-- name属性: 构造函数的参数名 -->
		<!-- index属性: 构造函数的参数索引 -->
		<!-- type属性: 构造函数的参数类型-->
		<constructor-arg name="name" index="0"  value="李四" ></constructor-arg>
		<constructor-arg name="car" index="1" ref="car" ></constructor-arg>
	</bean>
	
	<!-- p名称空间注入 -->
	<!-- 
		1.导入P名称空间  xmlns:p="http://www.springframework.org/schema/p"
		2.使用p:属性完成注入
		-值类型: p:属性名="值"
		-对象类型: p:属性名-ref="bean名称" -->
	<bean name="user2" class="com.yoci.entity.User" p:name="wangwu" p:age="26" p:car-ref="car"></bean>
	
	<!-- spEL注入 -->
	<bean name="user3" class="com.yoci.entity.User">
		<property name="name" value="#{user1.name}"></property>
		<property name="age" value="#{user2.age}"></property>
		<property name="car" ref="car"></property>
	</bean>

	<!-- 复杂类型注入 -->
	<bean name="collection" class="com.yoci.entity.Collection">
		<!-- 如果数组中只准备注入一个值(对象),直接使用value|ref即可 
			<property name="arr" value="tom" ></property>
		-->
		<!-- array注入,多个元素注入 -->
		<property name="arr">
			<array>
				<value>tom</value>
				<value>jack</value>
				<ref bean="user2"></ref>
			</array>
		</property>
		
		<!-- 
			如果List中只准备注入一个值(对象),直接使用value|ref即可 
			<property name="list" value="jack" ></property>
		-->
		<property name="list">
			<list>
				<value>zhangsan</value>
				<value>李四</value>
				<ref bean="user"/>
			</list>
		</property>
		
		<!-- map类型注入 -->
		<property name="map">
			<map>
				<entry key="url" value="www.yoci.com"></entry>
				<entry key="user3" value-ref="user"></entry>
			</map>
		</property>
		
		<!-- prperties 类型注入 -->
		<property name="prop">
			<props>
				<prop key="driverClass">com.jdbc.mysql.Driver</prop>
				<prop key="userName">root</prop>
				<prop key="password">1234</prop>
			</props>
		</property>

spring事务

什么是事务:

​ 事务逻辑上的一组操作,组成这组操作的各个逻辑单元,要么一起成功,要么一起失败。

事务特性

原子性 :强调事务的不可分割.

一致性 :事务的执行的前后数据的完整性保持一致.

隔离性 :一个事务执行的过程中,不应该受到其他事务的干扰

持久性 :事务一旦结束,数据就持久到数据库

如果不考虑隔离性引发安全性问题:

脏读 :一个事务读到了另一个事务的未提交的数据

不可重复读 :一个事务读到了另一个事务已经提交的 update 的数据导致多次查询结果不一致.

虚幻读 :一个事务读到了另一个事务已经提交的 insert 的数据导致多次查询结果不一致.

解决读问题:设置事务隔离级别

未提交读 :脏读,不可重复读,虚读都有可能发生

已提交读 :避免脏读。但是不可重复读和虚读有可能发生

可重复读 :避免脏读和不可重复读.但是虚幻读有可能发生.

串行化的 :避免以上所有读问题.

Mysql 默认:可重复读 Oracle 默认:读已提交

事务的操作对象

​ 在spring中玩事务管理.最为核心的对象就TransactionManager对象

事务的属性介绍

​ 事务隔离级别:

​ 1 读未提交 2 读已提交 4 可重复读 8 串行化

​ 是否只读:

​ true/false

​ 事务的传播行为:

2018-09-29_234855

spring代码(xml配置)

<!-- 事务管理器 -->
	<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:隔离级别
			propagation:传播行为
			read-only:是否只读
		 -->
          <!-- 传播行为 -->
		<tx:method name="save*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" />
		<tx:method name="persist*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" />
		<tx:method name="update*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" />
		<tx:method name="modify*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" />
		<tx:method name="delete*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" />
		<tx:method name="remove*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" />
		<tx:method name="get*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="true" />
		<tx:method name="find*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="true" />
		<tx:method name="transfer" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" />
		</tx:attributes>
	</tx:advice>

	<!-- 切面 -->
	<aop:config>
		<aop:advisor advice-ref="txAdvice"
			pointcut="execution(* cn.itcast.crm.service.*.*(..))" />
	</aop:config>


spring代码(注解配置)

<!-- 事务管理器 -->
	<bean id="transactionManager"	class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<!-- 数据源 -->
		<property name="dataSource" ref="dataSource" />
	</bean>

<!-- 开启使用注解管理aop事务 -->
<tx:annotation-driven/>

@Transactional(isolation=Isolation.REPEATABLE_READ,propagation=Propagation.REQUIRED,readOnly=true)
public class AccountServiceImpl implements AccountService {

	private AccountDao ad ;
	private TransactionTemplate tt;
		@Transactional(isolation=Isolation.REPEATABLE_READ,propagation=Propagation.REQUIRED,readOnly=false)
	public void transfer(final Integer from,final Integer to,final Double money) {
				//减钱
				ad.decreaseMoney(from, money);
				int i = 1/0;
				//加钱
				ad.increaseMoney(to, money);
	}

}


spring注解

开启spring注解

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd ">
  
<!-- 
	引入:
	xmlns:context="http://www.springframework.org/schema/context"
	http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-4.2.xsd
-->
<!-- 指定扫描cn.itcast.bean报下的所有类中的注解.
	 注意:扫描包时.会扫描指定报下的所有子孙包
 -->
<context:component-scan base-package="cn.itcast.bean"></context:component-scan>

</beans>

注解使用介绍

@Component("user") = <bean name="user" class="cn.itcast.bean.User"  />
  // service层
  @Service("user") 
  // web层
  @Controller("user") 
  // dao层
  @Repository("user")
  
//指定对象的作用范围
@Scope(scopeName="singleton/prototype")
  
//属性注入,推荐使用set方法注入方式, 第一种破坏封装性
@Value("18")
private Integer age;
@Value("tom")	
public void setName(String name) {
  this.name = name;
}

//自动装配
@Autowired //问题:如果匹配多个类型一致的对象.将无法选择具体注入哪一个对象.
@Qualifier("car2")//使用@Qualifier 配合 @Autowired注解告诉spring容器自动装配哪个名称的对象
//手动装配,指定注入哪个名称的对象
@Resource(name="car")
private Car car;

//在对象被创建后调用.init-method
@PostConstruct 
public void init(){
  System.out.println("我是初始化方法!");
}

//在销毁之前调用.destory-method
@PreDestroy 
public void destory(){
  System.out.println("我是销毁方法!");
}



spring整合junit测试

导入aop+test包

//帮我们创建容器
@RunWith(SpringJUnit4ClassRunner.class)
//指定创建容器时使用哪个配置文件
@ContextConfiguration("classpath:applicationContext.xml")
//指定多个配置文件时
@ContextConfiguration(locations = { "classpath*:/spring1.xml", "classpath*:/spring2.xml" }) 
public class Demo {
	//将名为user的对象注入到u变量中
	@Resource(name="user")
	private User u;
	
	@Test
	public void fun1(){
		
		System.out.println(u);
		
	}

}

原文地址:https://www.cnblogs.com/yoci/p/10642523.html