Spring 入门

一、Spring详细概括

1、spring是一个开源的轻量级(体积小、jar包少、不需要依赖其他jar)的JavaEE框架
2、spring核心部分IOC、AOP
	(1)IOC:创建对象由ioc负责不需要New对象
	(2)Aop:不修改源代码就可以实现对功能的添加
3、Spring特点:
	(1)方便解耦,简化开发
	(2)方便整合框架
	(3)降低JavaEE Api的使用难度(例:对JDBC进行封装)

二、IOC底层原理

1、简单使用

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="user唯一标识" class="cn.dao.User" /></bean>

实体类:
	public void user{
		public void add(){
			System.out.println("wdnmd");
		}
	}

测试:
	public static void main(String[] args) throws Exception {
		ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");//加载配置文件
		User us = ctx.getBean("user唯一标识",User.class);//对象创建成功
		us.add();
	}

2、IOC介绍

控制反转,对象的控制权移交给外部容器。解耦。

IOC通过 XML解析、工厂模式、反射进行管理。

例:(Start调用User的add方法)

1、原始(耦合太高,User中add方法变化,Start调用里要跟着变
	而且调用一次new一次)
	User us = new User();
	us.add();

2、工厂模式(为了解耦而出现)
	(1)、创建UserFactory类
	public void UserFactory(){
		public static User getUser(){
			return new User();
		}
	}
	(2)、调用
	User use = UserFactory.getUser();
	use.add();

3、IOC(最终进化版 XML解析+工厂模式+反射)
	(1)、xml文件进行配置
		<bean id="唯一标识" class="zz.User"/>
	(2)、创建工厂
		public void UserFactory(){
			public static User getUser(){
				String classvalue = class属性值	       //1、XML解析。
                              Class clazz = Class.forName(classValue)//2、反射创建对象。
				return (User)clazz.newInstance();
			}
		}
	

3、IOC重要接口

1、IOC思想基于IOC容器完成,IOC容器底层就是对象工厂

2、Spring提供两种IOC容器实现方式:(两个接口)
都是加载配置文件==》获取配置创建对象	
	(1)、BeanFactory:(最基本方式,Spring自带接口,一般Spring内部使用不提供开发人员使用)
	(2)、ApplicationContext:(BeanFactory的子接口,提供更多更强大的功能,一般开发人员使用)

区别:
	BeanFactory加载配置文件不会去创建对象,获取时才创建对象。
	ApplicationContext会把加载配置文件的对象创建。

好处:
	放在Tomcat时启动项目时就把耗时耗资源的操作加载出来,BeanFactory不行用的时候才加载

ApplicationContext接口有实现类
	(1)、FileSystemXmlApplicationContext:盘符路径
	(2)、ClassPathXmlApplicationContext:类路径

4、IOC操作bean管理(xml基本就不用基本都用注解撒)

bean管理具体指的是两个操作创建对象注入属性
而且bean管理有两种实现方式基于XML配置文件方式基于注解方式

(1)、IOC操作bean管理(基于XML实现bean管理)
DI:依赖注入(是IOC的一部分)
1、xml方式创建对象
	<bean id="user" class="cn.entity.User"/>
	id属性:唯一标识		class:类路径				
注:默认也是执行类无参构造方法
	
2、xml方式注入属性
	(1)、有参构造注入(提供有参构造)
		<bean id="user" class="cn.entity.User">
			//通过定义单参构造方法为userserviceimpl的dao属性赋值
					//外部bean注入属性
			<constructor-arg><ref bean="引用bean"/></constructor-arg>
			<constructor-arg name="name" value="有参构造注入"></constructor-arg>
		</bean>
					
		//内部bean太鸡肋有印象就行。
			
	(2)、set注入(提供set方法)
		<bean id="user" class="cn.dao.User">
			<property name="name" value="WDNMD"></property>
		</bean>

	(3)、P命名空间注入(需要引入   xmlns:p="http://www.springframework.org/schema/p")
		<bean id="user" class="cn.dao.User" p:name="WDNMD"></bean>
		注:p:属性名=“属性值”		p:属性名-ref=“nean的id”

	(4)、注入不同的数据类型
		1、简单类型、特殊字符
		<property><value><![CDATA[$&#$@##@$]]></value></property>

		2、List
		<bean id="user" class="entity.User">
			<property name="hobbies">
			<list><value>1</value><value>2</value>
			</list>
		    </property>
		</bean>

		3、Map
		<bean id="user" class="entity.User">
			<property name="hobbies">
			<map><entry><key><value>键</value></key><value>值</value></entry>
			</map>
		    </property>
		</bean>

		4、空字符串注入<value></value>	<bean name="user"><null/></bean>

	(5)、级联赋值(撕~好多鱼)
		方法1:
			<bean id="teachers" class="entity.teacher">
				<property name="对象(一对多)" ref="引用bean的唯一标识"></property>
			</bean>
			<bean id="引用bean的唯一标识" class="entity.students">
				<property name="student" value="张三"></property>
			</bean>
		
		方法2:
			<bean id="teacher" class="entity.teacher">
				<property name="对象(一对多)" value="引用bean的唯一标识"></property>
				//需要提供get方法
				<property name="student.student" value="张三"></property>
			</bean>
(2)、IOC操作bean管理(Factorybean)

Spring有两种bean
1、普通bean(bean的class定义类型和返回类型必须一致)

2、工厂(Factory为了创建bean过程不被暴漏)bean(bean的class定义类型和返回类型可以一致)

工厂bean使用方法
第一步:创建类,让此类成为工厂类,实现Factory接口即可
第二部:实现接口中的方法,在方法中定义bean的返回类型

	public class Mybean implents Factory<随意类型>(){
		public 随意类型 getObject()throws Execption{
			随意类型 名字 = new 随意类型();
			名字.属性="赋值";
			return 名字;
		}
	}

	XML中:
		<bean id="mybean" class="conf.Mybean"></bean>

	测试: 
		ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");//容器初始化
		随意类型 名字 = ctx.getBean("mybean",随意类型.class);//对象创建成功

(3)、IOC操作bean管理(bean作用域和生命周期)

作用域:bean默认是单例模式,可以设置成多例模

1、设置单例 || 多例
	单例:(默认,加载配置文件时就创建)
	<bean id="wdnmd" class="WDNMD" scope="singleton"</bean>
	多例:(每次请求创建新的实例bean,getbean获取时才创建)
	<bean id="wdnmd" class="WDNMD" scope=""prototype></bean>

2、生命周期
	(1)通过构造器创建bean实例(无参构造)

	(2)为bean的属性设置值||引用(set方法设置)

	(3)调用bean的初始化方法(自己写方法名随意)
		xml中:
		<bean id="wdnmd" class="entity.WDNMD" init-method="initmethod"></bean>
		实体类中:
		public void initmethod(){
			System.out.Print("bean初始化");
		}
		
	(4)获取bean对象
		随意类型 名字 = ctx.getBean("mybean",随意类型.class);//对象创建成功

	(5)容器关闭,销毁bean(自己写方法名随意)
		xml中:
		<bean id="wdnmd" class="entity.WDNMD" destory-method="destorymethod"></bean>
		实体类中:
		public void destorymethod(){
			System.out.Print("bean销毁");
		}
		//测试类中
		//手动销毁,销毁后才会调用上面销毁方法
		加载配置文件所创建的对象.close();

第三步前后还有一个操作把bean实例传递给后置处理器。
(4)、IOC操作bean管理(bean自动装配)
byName:根据名称自动装配()
	<bean id="teacher" class="entity.teachers" autowrie="btName"></bean>
	//id必须对应teacher中的student属性名称	
	<bean id="student" class="entity.student"></bean>
byType:根据类型自动装配
	还是别用了太鸡肋了跟上面一样类型一致就行,但是多个bean他就不知道用那个了
(5:重点)、IOC操作bean管理(基于注解实现bean管理)

注解简化xml配置

注:所有注解都是创建bean对象。@MapperScan扫描指定包下注解,想要用注解需要开启扫描,不然Spring不知道做什么
@MapperScan=<context:component-scan base-package=”com.eric.spring”>(xml方式配置)

@component
	泛指组件,当组件不好归类的时候,我们可以使用这个注解进行标注。
	@component默认值为(value="指定类的名字把首字母小写")

@Service
	用于标注业务层组件

@controller
	用于标注控制层组件

@Repository
	用于标注数据访问组件,即DAO组件

@Configuration
	标注此类为配置类
	加载配置类:ApplicationContext con = new AnnotationConfigApplicationContext(配置类名字.class);

常用的注解注入
	@Autowired:根据属性类型进行注入			@Qualifier:根据属性名称注入
	@Resource:可以根据类型也可以根据属性注入	@Value:普通属性注入(标注在属性上)
	区别:
		多个实现类情况下@Autowired+@Qualifier(value="指定一个实现类首字母小写")
		而Resource就牛逼了多个实现类@Resource(name="指定一个实现类首字母小写")
		Java提供@Resource	Spring提供@Autowired和@Qualifier

三、AOP的底层学习

AOP为面向切面编程(不改变源代码,为项目添加新功能),对业务逻辑各个部分进行隔离,
从而降低耦合度提高可重用性

1、底层原理

AOP底层使用动态代理
	1、动态代理有两种情况
		(1)、有接口,使用JDK动态代理(创建接口实现类代理实现增强)
			//调用Proxy中的newProxyInstance方法(有三个参数)
			//参数一:类加载器  参数二:增加类方法的接口(支持多接口) 参数三:增强的部分	
			1、创建接口
			public class Subject(){	
				public interface history(int age){					
					return age;
				}
			}
			2、实现接口
			public class SubjectImpl implements Subject(){
				public int history(int age){
					return age;
				}
			}
			3、创建一个代理类JDKProxy(名字按照规范即可)
			public class JDKProxy(){
				public static void main(String[]args){
					//创建接口代实现类代理对象
					Class interfaces[] = {Subject.class};
					SubjectImpl Subjects = new SubjectImpl();
					Subject sub =(Subject)Proxy.newProxyInstance(JDKProxy.class.getClassLoder,interfaces,
											new Strong(Subjects));
				}			
			}
			4、创建一个类实现InvocationHandler接口
			//把创建的是谁的代理对象,就传谁过来
			private Object obj;
			public Subject(Object obj){
				this.obj=obj
			}

			public class Strong implements InvocationHandler(){
				@Override//根据method判断增强那个方法,如果方法a,如果方法b
				public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
					//写增强逻辑
					//方法执行前
					System.out.print("方法名称:"+method.getName()+"传递的参数:"+Arrays.toString(args));
					
					//执行原有方法
					Object res = method.invoke(obj,args);

					//方法之后
					System.out.print(obj);
					return res;
				}	    
			}
	
		(2)、无接口,使用CGLIB动态代理(创建当前类子类的代理对象)
				
			

2、AOP术语

(1)、连接点
	类的哪些方法可以被增强,这些方法就叫做连接点

(2)、切入点
	实际被真正增强的方法,叫做切入点

(3)、通知(增强)
	实际增强的逻辑部分问叫做通知。(有5种类型)
	1、前置通知
		方法之前做的通知
	2、后置通知
		方法之后做的通知(有异常就不通知)
	3、环绕通知
		方法前后都做的通知
	4、异常通知
		出现异常时做的通知
	5、最终通知
		不管是否有异常都会通知

(4)、(切面)
	把通知应用到切入点的过程叫做切面

3、AOP准备操作

Spring一般基于AspectJ实现AOP操作
AspectJ是Spring的组成部分,独立AOP框架,一般把AspectJ和Spring一起使用进行AOP操作,基于AspectJ实现AOP有两种方式

1、xml方式      2、注解方式

//切入点表达式(为了知道对那个类中那个方法增强)
语法:execution([权限修饰符][返回类型][类全路径][方法名称]([参数列表]))
例:	//单个方法					//所有方法直接.*
	execution(* 空格 [代表匹配所有修饰符]nb.Dao.UserDao.add(...[代表参数列表]))

1、通过注解实现AOP(AspectJ,要开启注解扫描@MapperScan)
	(1)、创建类,再类里定义方法
	@Compoment
	public class wdnmd(){
		public void dnmd(){
			System.out.printl("WDNMD");
		}
	}

	(2)、创建增强类并创建方法
	@Compoment
	@Aspect
	public class StrongProxy(){
		//前置通知
		@Before(execution(* 类路径.需要增强的方法名称(..)))
		public void before(){
			System.out.printl("前置增强!");
		}
	}

	(3)、配置
		<?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
			xmlns:context="http://www.springframework.org/schema/context" 
			http://www.springframework.org/schema/beans/spring-beans.xsd 
			http://www.springframework.org/schema/context 
			http://www.springframework.org/schema/context/spring-context.xsd">
		
		<!--开启注解扫描,可以扫描com.mq包下的所有bean  -->
		<context:component-scan base-package="com.mq"/>
		
		<!-- 启动AspectJ支持 -->  
		<aop:aspectj-autoproxy /> 		     
	</beans> 

	(4)、配置不同类型通知
		//什么类通知在通知方法上加什么类型注解
		//前置通知
		@Before(execution(* 类路径.需要增强的方法名称(..)))
						
		//方法后执行		//返回值之后执行			//异常通知		
		@After(最终通知)		@AfterReturning(后置通知)	@AfterThrowing		
		
		//环绕通知
		@Around

	(5)、相同切入点抽取
	@Pointcut(value="execution(* 空格 [代表匹配所有修饰符]nb.Dao.UserDao.add(...[代表参数列表])")
	public void pubs(){
	}
	//通知就可以简化
	@Before(value="pubs()")

	(6)、多个增强类对同一个方法进行增强,设置增强优先级
	//在代理类加@Order(0-~ 0的优先级最高)实现增强的优先级
	

四、事务(不包含查询)

事务是数据库操作最进本的单元,逻辑上的一组操作,要么都成功,一个是失败全部失败

1、事务概念

(1)、原子性
	要么都成功,一个失败全部失败
(2)、一致性
	操作前后总量一致
(3)、隔离性
	两人同时间操作同一条数据不会产生影响
(4)、持久性
	对数据库中的数据的改变就是永久性的

2、Spring中事务的使用

(1)、开启事务
(2)、逻辑操作
(3)、事务(Spring有两种事务方式)
	1、编程式事务管理
		try{
			//事务开启
			//编写业务逻辑
			//事务提交
		}catch(Execption e){
			//事务回滚
		}
	
	2、声明式事务管理(又分为两种)
		(1)、xml方式(知道有就好。。。。。就不写了。。。。嗯。。。。)
		(2)、注解方式
		步骤一、在spring配置文件中引入<tx:>命名空间
			
			<beans xmlns="http://www.springframework.org/schema/beans"
			 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
			 xmlns:tx="http://www.springframework.org/schema/tx"
			 xsi:schemaLocation="http://www.springframework.org/schema/beans
			 http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
			 http://www.springframework.org/schema/tx
			 http://www.springframework.org/schema/tx/spring-tx-2.0.xsd">

		<bean id="defaultTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
			<property name="sessionFactory" ref="sessionFactory" />
		</bean>

		<!-- 使用annotation定义事务 -->
		<tx:annotation-driven transaction-manager="defaultTransactionManager" proxy-target-class="true"/>
		</beans>

		步骤二、在service的类 || 方法上添加事务注解(@Transactional)
			//添加到类上所有方法添加事务,添加方法上单个方法添加事务	

3、Spring中事务参数详解

事务参数

属性类型描述
valueString可选的限定描述符,指定使用的事务管理器
propagationenum: Propagation可选的事务传播行为设置
isolationenum: Isolation可选的事务隔离级别设置
readOnlyboolean读写或只读事务,默认读写
timeoutint (in seconds granularity)事务超时时间设置
rollbackForClass对象数组,必须继承自Throwable导致事务回滚的异常类数组
rollbackForClassName类名数组,必须继承自Throwable导致事务回滚的异常类名字数组
noRollbackForClass对象数组,必须继承自Throwable不会导致事务回滚的异常类数组
noRollbackForClassName类名数组,必须继承自Throwable不会导致事务回滚的异常类名字数组
(1)、传播设置:(propagation )Spring在TransactionDefinition类中定义了以下7种传播特性
	PROPAGATION_REQUIRED:如果不存在外层事务,就主动创建事务;否则使用外层事务

	PROPAGATION_SUPPORTS:如果不存在外层事务,就不开启事务;否则使用外层事务

	PROPAGATION_MANDATORY:如果不存在外层事务,就抛出异常;否则使用外层事务

	PROPAGATION_REQUIRES_NEW:总是主动开启事务;如果存在外层事务,就将外层事务挂起

	PROPAGATION_NOT_SUPPORTED:总是不开启事务;如果存在外层事务,就将外层事务挂起

	PROPAGATION_NEVER:总是不开启事务;如果存在外层事务,则抛出异常

	PROPAGATION_NESTED:如果不存在外层事务,就主动创建事务;否则创建嵌套的子事务

	示例:@Transactional(propagation=PROPAGATION.REQUIRED)

(2)、隔离级别(isolation 解决并发时出现问题):多事务操作之间不会产生影响 
	不使用有三个问题:
	脏读:读取到了别的事务回滚前的数据,例如B事务修改数据库X,在未提交前A事务读取了X的值,而B事务发生了回滚。
	
	不可重复读:一个事务在两次读取同一个数据的值不一致。例如A事务读取X,在中间过程中B事务修改了X的值,事务A再次
		读取X时值发生了改变。
	
	幻读:查询得到的数据条数发生了改变,例如A事务搜索数据时有10条数据,在这时B事务插入了一条数据,A事务再搜索时
		发现数据有11条了。

	参数可以使用的值:
		READ-UNCOMMITTED:未提交读(脏读、不可重复读、幻读)
		READ-COMMITTED:已提交读(不可重复读、幻读),大多数主流数据库的默认事务等级,保证了一个事务不会读到
			另一个并行事务已修改但未提交的数据,避免了“脏读取”。
		REPEATABLE-READ(mysql默认):可重复读(幻读),保证了一个事务不会修改已经由另一个事务读取但未提交
			(回滚)的数据。
		SERIALIZABLE:串行化最严格的级别,事务串行执行,资源消耗最大

	示例:@Transactional(isolation=Isolation.REPEATABLE-READ)


(3)、超时时间(timeout)
	//事务在规定时间内提交,否则进行回滚。默认为-1单位秒
	示例:@Transactional(timeout="5")

(4)、是否只读(readOnly)	
	//默认为false,如果为true则只能进行查询操作
	示例:@Transactional(readOnly=true || false)

(5)、异常回滚(rollbackFor )
	//出现那些异常进行回滚
	示例:@Transactional(rollbackFor=Execption)

(6)、异常不回滚(noRollbackFor)
	//出现那些异常不进行回滚
	示例:@Transactional(norollbackFor=Execption)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值