跳至主要內容

Spring基础用法总结

Alooc...大约 19 分钟后端框架SpringSpring

Spring的基本用法:

spring是一个很普通但很实用的一个框架,它提取了大量实际开发中需要重复解决的步骤,将这些步骤抽象成一个框架。

1.spring简介:

  • spring5
    - Spring Core Container(即Spring容器)代表了Spring框架的核心机制。

2.spring入门:

21个jar包

  • 实用spring管理bean:

    • spring核心容器理论:spring核心容器就是一个超级大工厂,所有的对象都会被当成spring核心容器管理的对象。

    • Spring对Bean没有任何要求,只要是java类,将会当作bean处理

    • 对于Spring框架而言,一切Java对象都是Bean。

      				<beans>
      					<bean id="" class="">
      						<property name="" ref=""/>
      					</bean>
      					<bean id="" class="">
      						<property name="" value=""/>
      					</bean>
      					...
      				</beans>
      
    • spring通过反射机制从xml文件中获取bean对象:

      • ​ spring底层大概的执行代码:

        • 创建bean:

          String idStr=bean中的id;
          String classStr=bean中的class;
          Class clazz=Class.forName(classStr);
          Object obj=clazz.newInstance();
          spring的容器container.put(idStr,obj);
          
        • 设置参数(调用setter方法):

          String nameStr=属性的name;
          String refStr=属性的引用ref,某一个bean的id 或某个value参数值;
          String setterName="set"+nameStr.subString(0,1).toUpperCase()+nameStr.subString(1);生成方法名 setName
          Object paramBean=container.get(refStr)
          Method setter=clazz.getMethod(setterName,paramBean.getClass());
          setter.invoke(obj,paramBean);
          
      • 在程序中访问bean:

        • ApplicationContext是最常用的接口, 有两个实现类:

          • ClassPathXmlApplicationContext 从类加载路径下搜索配置文件,并根据配置文件创建spring容器

          • FileSystemXmlApplicationContext 从文件系统的相对路径或绝对路径中搜索配置文件,并根据配置文件创建spring容器

            ApplicationContext ctx=new ClassPathXmlApplicationContext("beans.xml");
            Person p=ctx.getBean("person",Person.class);
            
        • 获取对象的两个方法:

          • Object getBean(String id) 需要强制类型转换:

            Person p=(Person)ctx.getBean("person");
            
          • T getBean(String id,Class<T> requiredType) 无需进行强制类型转换:

            Person p=ctx.getBean("person",Person.class);
            

3.Spring的核心机制:依赖注入:

  • Spring框架的核心功能有两个:

    1. Spring容器作为超级大工厂,负责创建、管理所有的Java对象,这些Java对象被称为Bean

    2. Spring容器管理容器中Bean之间的依赖关系,使用一种被称为“依赖注入”的方式来管理Bean之间的依赖关系

  • 理解依赖注入:

    • 调用者无须主动获取被调用者,只要被动接受Spring容器为其赋值即可(<property />通过该子元素赋值)
    • 调用者获取依赖对象的方式由原来的主动获取,变成了被动接受,所以又被称为控制反转。
  • 依赖注入的两种注入方式:

    • 设值注入:IoC容器使用成员变量的setter方法来注入被依赖对象
    • 构造注入:IoC容器使用构造器来注入被依赖对象
    • Spring IoC容器的三个基本要点:
      1. 应用程序的各组件面向接口编程
      2. 应用程序的各组件不再由程序主动创建,而是由Spring容器来负责产生并实例化
      3. Spring采用配置文件或注解来管理bean的实现类、依赖关系。Spring容器根据配置文件或注解,利用反射来创建梳理,并为之注入依赖关系。
    • 两种方式对比:
      • 建议采用以设值注入为主,构造注入为辅的注入策略。
        • 对于依赖关系无需变化的注入,尽量采用构造注入;
        • 而对于其他依赖关系的注入,则考虑采用设值注入。

4.使用spring容器:

  • 核心接口(获取spring容器):BeanFactory ApplicationContext

ApplicationContextBeanFactory的子接口

  • ApplicationContext:

    当系统创建ApplicationContext容器时,默认会预初始化所有的singleton Bean 可在<bean>中设置 lazy-init="true"改变默认预初始化

  • ApplicationContext国际化

  • ApplicationContext的事件机制:

    • 通过ApplicationEvent类和ApplicationListener接口实现事件处理
    • 如果容器中有一个ApplicationListener Bean,每当ApplicationContext发布ApplicationEvent时,ApplicationListener Bean将自动被触发。
    • 容器事件监听器可以监听事件。
      • 除此之外,程序也就二调用ApplicationContexpublishEvent()方法来触发容器事件。
  • 让Bean获取Spring容器:

    • 接口有一个方法:setBeanFactory(BeanFactory beanFactory)

    • spring容器会检测容器中的所有Bean,如果发现某个Bean实现了ApplicationContextAware接口,

      Spring容器会在创建该Bean后,自动调用该方法,调用该方法时,会将容器本身作为参数传给该方法。

    • 示例:

      public class Person implements ApplicationContextAware{
          private ApplicationContext ctx;
      
          public void setApplicationContext(ApplicationContext ctx) throws BeansException{
              this.ctx=ctx;
          }
          ...
      }
      

      5.Spring容器中的Bean:

		Bean的基本定义和Bean别名:
			<bean id="person" class="..." name="#abc,@123,abc*" />
			<alias name="person" alias="jack" />
			<alias name="jack" alias="jackee" />
			
		容器中Bean的作用域:
			singleton 单例模式
			prototype 每调用一次getBean就创建一个新的Bean实例
				<bean id="..." class="..." scope="prototype" />
			
		配置依赖:
			
		设置普通属性值:
			value用于指定基本类型及其包装、字符串类型的参数值
				<property name="" value=""/>
		
		配置合作者Bean:
			属性值是另一个Bean的实例
			<property name="" ref=""/>
		
		使用自动装配注入合作者Bean:
			不推荐使用
		
		注入嵌套Bean:
			<bean ...>
				<property ...>
					<bean class="..."/>无需id属性,spring容器不能访问嵌套bean
				</property>
			</bean>
		
		组合属性:
			先getBean() 然后再setter()
			<bean id="a" class="...">
				<property name="foo.bar.x.y" value="xxx" />
			</bean>
			相当于:
				a.getFoo().getBar().getX().setY("xxx");
		
		Spring的Bean 和JavaBean:
			javabean通常作为DTO(数据传输对象),用来封装值对象,再各层之间传递数据。
			 spring的Bean 无所不包,任何组件都可被称为Bean
		

6.Spring提供的Java配置管理:

  • 以xml为主,Java类配置为辅
  • 以Java类配置为主,xml为辅

7.创建bean的三种方式:

  • 调用构造器创建Bean

  • 调用静态工厂方法创建Bean

    <bean id="..." class="静态工厂类" factory-method="工厂方法" />
    
  • 调用实例工厂方法创建Bean

    • 先将工厂实例化为bean

    • 然后:

      <bean id="..." factory-bean="工厂bean的id" factory-method="方法" />
      

8.深入理解容器中的Bean:

	抽象Bean和子bean:
			抽象:
				<bean id="parentId" class="..." abstract="true" />
			子:
				<bean id="..." class="..." parent="parentId" />
	Bean继承与Java继承:
		不同
	
	容器中的工厂Bean:
		FactoryBean
		获取的是工厂bean的getObject()方法获取的值
	
	获得Bean本身的id:
		实现BeanNameAware接口
		提供方法:
			setBeanName(String name)
	
	强制初始化Bean:
		可以在初始化主调Bean之前,强制初始化一个或多个Bean
			<bean id="a" class="..." depends-on="b" />
			<bean id="b" class="..." />

9.容器中Bean的生命周期:

	singleton作用域的Bean,Spring 可完全管理
		prototype作用域的Bean,Spring 只负责创建,然后交给客户端后,容器不在跟踪其生命周期
	管理Bean的生命周期行为主要有如下两个时机:
		1.注入依赖关系之后
		2.即将销毁Bean之前
	
	依赖关系注入之后的行为:
		使用init-method属性 指定某个方法在Bean全部依赖关系设置结束后自动执行。
		实现InitializingBean接口
		
	Bean销毁之前的行为:
		使用destory-method属性	指定某个方法在Bean销毁之前被自动执行
		实现DisposableBean接口
	
	协调作用域不同步的Bean:
		方法注入
		<lookup-method name="..." bean="..."/>

10.高级依赖关系配置:

将任意方法的返回值、类或对象的Field值、其他Bean的getter方法返回值,直接定义成容器中的一个Bean

11.基于XML Schema的简化配置方式:

	使用p:命名空间简化配置:【简化设值注入】
		p:命名空间不需要特定的Schema定义,它直接存在于Spring内核中
		可直接使用属性来配置参数值
		<beans ...
				xmlns:p="http://www.springframework.org/schema/p">
			<bean id="..." class="..." p:age="22" p:axe-ref="Bean的id" />
			...
		</beans>
		如果某属性名是以"-ref"结尾,则会引起冲突。
	
	使用c:命名空间简化配置:【简化构造注入】
		<beans ...
				xmlns:c="http://www.springframework.org/schema/c">
			<bean id="..." class="..." c:age="22" c:axe-ref="Bean的id" />
			...
		</beans>
	
	使用util:命名空间简化配置:
		必须导入最新的spring-util.xsd
		
		util Schema提供如下几个元素:
			constant	获取指定类的静态Field的值
			property-path	获取指定对象的getter方法的返回值
			list	定义一个List Bean
			set	定义一个Set Bean	
			map	定义一个Map Bean
			properties	加载一份资源文件,并根据加载的资源文件创建一个Properties Bean实例
			
			<util:constant id="chin.age" static-field="java.sql.Connection.TRANSACTION_SERIALIZABLE" />
			
			<util:properties id="confTest" location="classpath:test_zh_CN.properties" />
			
			<util:list id="chin.schools" list-class="java.util.LinkedList">
				<value>小学</value>
				<value>中学</value>
				<value>大学</value>
			</util:list>
			
			<util:set id="chin.axes" set-class="java.util.HashSet">
				<value>字符串</value>
				<bean class="..."/>
				<ref bean="stoneAxe"/>
			</util:set>
			
			<util:map id="chin.scores" map-class="java.util.TreeMap">
				<entry key="语文" value="99" />
				<entry key="数学" value="99" />
				<entry key="英语" value="99" />
			</util:map>

12.Spring提供的表达式语言(SpEL):

	在运行时查询和操作对象图
	
	使用Expression接口进行表达式求值:
		SpEL的三个接口:
			ExpressionParser:	负责解析一个SpEL表达式,返回一个Expression对象
			Expression:			该接口的实例代表一个表达式
			EvaluationContext:	代表计算表达式值得上下文
		
		Expression包含的方法:
			Object getValue():	计算表达式的值
			<T> T getValue(Class<T> desiredResultType):	计算表达式的值,并尝试将该值当成desiredResultType类型处理
			Object getValue(EvaluationContext context):		用指定的EvaluationContext来计算表达式的值
			<T> T getValue(EvaluationContext context,Class<T> desiredResultType)
			Object getValue(Object rootObject):		以rootObject作为表达式的root对象来计算表达式的值
			<T> T getValue(Object rootObject,Class<T> desiredResultType):
	
	Bean定义中的表达式语言支持:
		在XML配置文件和注解中使用SpEL时,在表达式外面增加#{}包围即可
	
	SpEL语法详述:
		1.直接量表达式:
			就是在表达式中使用Java语言支持的直接量,包括字符串、日期、数值、boolean值和null。
			
		2.在表达式中创建数组:
			支持使用静态初始化、动态初始化两种语法来创建数组
			
		3.在表达式中创建List集合:
			{ele1,ele2,ele3 ...}
		
		4.在表达式中访问List,Map等集合元素:
			list[index]
			map[key]
		
		5.调用方法:
			和Java一样
		
		6.算术、比较、逻辑、赋值、三目等运算符:
		
		7.类型运算符:
			T()将括号内的字符串当成“类”处理
		
		8.调用构造器:
			直接使用new 来调用构造器
		
		9.变量:
			允许通过EvaluationContext来使用变量,该对象包含了一个setVariable(String name,Object value)方法,该方法用于设置一个变量。
				在EvaluationContext中设置了变量,就可以在SpEL中通过#name来访问该变量。
			#name
			#this	引用SpEL当前正在计算的对象
			#root	引用SpEL的EvaluationContext的root对象
		
		10.自定义函数:
			为Java方法重新起个名字
			registerFunction(String name,Method m)	将m方法注册成自定义函数,该函数的名称为name
		
		11.Elvis运算符:
			name != null? name:"newVal"
			简化为:
				name?:"newVal"
		12.安全导航操作:
			foo?.bar	若foo为空,直接返回null,不会导致NullPointerException
			
		13.集合选择:
			collection.?[condition_expr]
				"#myList.?[length()>7]"
		
		14.集合投影:
			collection.![condition_expr]
				把collection集合中的元素依次传入condition_expr中,每个元素得到一个新结果,所有计算出来的结果组成的新结果就是该表达式的返回值
		
		15.表达式模板:
			允许在“直接量表达式”中插入一个或多个#{expr},#{expr}将会被动态计算出来。

深入使用Spring:

1.两种后处理器:

	开发者可以通过后处理器对IoC容器进行扩展
	Bean后处理器:对容器中的Bean进行后处理,对Bean进行额外加强
	容器后处理器:对IoC容器进行后处理,用于增强容器功能
	
	Bean后处理器:
		必须实现BeanPostProcessor接口
			接口包含两个方法:
				Object postProcessBeforeInitialization(Object bean,String name) throws BeansException
				Object postProcessAfterInitialization(Object bean,String name) throws BeansException
		
		Spring常用的两个后处理器:
			BeanNameAutoProxyCreator:		根据Bean实例的name属性,创建Bean实例的代理
			DefaultAdvisorAutoProxyCreator:	根据提供的Advisor,对容器中的所有Bean实例创建代理
		
	容器后处理器:
		必须实现BeanFactoryPostProcessor接口
			接口包含一个方法:
				postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
		
		PropertyPlaceholderConfigurer:属性占位符配置器
			<context:property-placeholder location="classpath:dbconn.properties" />
			使用:
				"$(jdbc.url)"
			属性文件dbconn.properties:
				jdbc.driverClassName=com.mysql.cj.jdbc.Driver
				jdbc.url=
				jdbc.username=
				jdbc.password=
		
		PropertyOverrideConfigurer:重写占位符配置器 【直接覆盖bean的值】
			<context:property-override location="classpath:db.properties" />
	
			db.properties:
				dataSource.driverClass=
				dataSource.jdbcUrl=
				dataSource.user=
				dataSource.password=

2.Spring的“零配置”支持:

	搜索Bean类:
			注解:
				@Component	标注一个普通的SpringBean类
				@Controller	标注一个控制器组件类
				@Service	标注一个业务逻辑组件类
				@Respository	标注一个DAO组件类
				<context:component-scan base-package="app.service"/>
	指定Bean的作用域:
		@Scope("prototype")
	
	使用@Resource和@Value配置依赖:	
		@Resource name值,需要被注入的Bean实例的id  相当于<property.../>元素的ref属性
		@Value 相当于<property.../>元素的value属性
	
	使用@PostConstruct和@PreDestory定制生命周期行为:
		前者用于注解Bean的初始化方法
		后者用于注解Bean销毁之前的方法			
	
	使用@DependsOn和@Lazy改变初始化行为:
		前者用于强制初始化其他Bean
		后者用于指定该Bean是否取消预初始化
		@DependsOn({"steelAxe","abc"})
		@Lazy(true)
	
	自动装配和精确装配:
		@Autowired 标注setter时,默认采用byType自动装配策略
		@Primary 修饰特定Bean类,当自动装配出现冲突时,选择该注解修饰的Bean
	
	使用@Required检查注入:
		@Required修饰方法,若被修饰的方法没有配置注入,则报出异常,以防止程序运行时引发NPE异常,而找不到出错点。

3.资源访问:

	程序访问资源(各种类型的文件,二进制流)
	
	URL:
		java.net.URL 
	
	Spring改进Java资源访问的策略,提供Resource接口
		该接口是所有资源访问类所实现的接口:
			Resource接口的方法;
				getInputStream()
				exists()
				isOpen()
				getDescription()
				getFile()
				getURL()
				
	Spring提供的Resource实现类:
		UrlResource
		ClassPathResource	对于web应用,ClassPathResource可以自动搜索位于WEB-INF/classes下的资源文件
		FileSystemResource
		ServletContextResource 访问应用的相关资源
		InputStreamResource
		ByteArrayResource	访问字节数组
		针对不同的底层资源,这些实现类提供响应的资源访问逻辑,并提供便捷的包装,以利于客户端程序的资源访问
		
		示例:	
			UrlResource ur=new UrlResource("file:book.xml");
			
			ClassPathResource:
				显示创建:ClassPathResource cr=new ClassPathResource("book.xml");
				常用隐式创建:spring识别字符串参数包含classpath:前缀后,系统会自动创建ClassPathResource对象
			
			FilePathResource:
				显示创建:FilePathResource fr=new FilePathResource("book.xml");
				常用隐式创建:spring识别字符串参数包含file:前缀后,系统会自动创建FilePathResource对象
			
			ServletContextResource:
				// 从Web Context下的WEB-INF路径下读取book.xml资源
				ServletContextResource src = new ServletContextResource(application , "WEB-INF/book.xml");
				可以访问WEB-INF中的资源了
			
			访问字节数组资源:
				InputStreamResource效率低,尽量使用ByteArrayResource或FileSystemResource替代它
				先从InputStream流中读出字节数组,然后以字节数组来创建ByteArrayResource。这样,InputStreamResource被转换为ByteArrayResource,从而方便多次读取。
	
	ResourceLoader接口和ResourceLoaderAware接口:
		ResourceLoader接口:实现类的示例可以获得一个Resource示例
		ResourceLoaderAware接口:实现类的示例可以获得一个ResourceLoader的引用
		
		ResourceLoader接口的方法:
			Resource getResource(String location) 
				ApplicationContext的实现类都实现了ResourceLoader接口,因此可直接获取Resource示例
	
	使用Resource作为属性:
		<bean id="test" class="org.crazyit.app.service.TestBean"
			p:res="classpath:book.xml"/>
	
	在ApplicationContext中使用资源:
		显式声明:
			ApplicationContext ctx = new ClassPathXmlApplicationContext("beans*.xml");
			ApplicationContext ctx = new FileSystemXmlApplicationContext("beans.xml");

4.Spring的AOP:

OOP将程序分解成各个层次的对象,从静态角度考虑程序结构

AOP将程序运行过程分解成各个切面,从动态角度考虑程序运行过程

  • 为什么需要AOP:

    • AOP专门用于处理系统中分布于各模块(不同方法)中的交叉关注点的问题。
    • 在Java EE应用中,常常用AOP来处理一些具有横切性质的系统级服务,
      • 如事务管理、安全检查、缓存、对象池管理等。
  • 使用AspectJ实现AOP:

    • AspectJ是一个基于Java语言的AOP框架

    • AspectJ主要包括两部分:

      • 定义如何表达、定义AOP编程中的语法规范
      • 工具部分,包括编译器、调试工具等
      			// 指定在执行org.crazyit.app.service包中任意类的、任意方法之前执行下面代码块
      			// 第一个星号表示返回值不限;第二个星号表示类名不限;
      			// 第三个星号表示方法名不限;圆括号中..代表任意个数、类型不限的形参
      			before(): execution(* org.crazyit.app.service.*.*(..))
      			{
      				System.out.println("模拟进行权限检查...");
      			}
      			
      			// 定义一个PointCut,其名为logPointcut,
      			// 该Pointcut代表了后面给出的切入点表达式,这样可复用该切入点表达式
      			pointcut logPointcut()
      				:execution(* org.crazyit.app.service.*.*(..));
      			after():logPointcut()
      			{
      				System.out.println("模拟记录日志...");
      			}
      		
      			// 指定在执行org.crazyit.app.service包中任意类的、任意方法时执行下面代码块
      			Object around():call(* org.crazyit.app.service.*.*(..))
      			{
      				System.out.println("模拟开启事务...");
      				// 回调原来的目标方法
      				Object rvt = proceed();
      				System.out.println("模拟结束事务...");
      				return rvt;
      			}
      
    • AOP的基本概念:

      • AOP框架能处理程序执行中特定的切入点(Pointcut),而不与具体类耦合
      • AOP框架两个特征:
        • 1.各步骤之间的良好隔离性
        • 2.源代码无关性
      • 关于切面编程的一些术语:
        • 切面(Aspect):切面用于组织多个Advice,Advice放在切面中定义
        • 连接点(Joinpoint):程序执行过程中明确的点,如方法的调用,或者异常的抛出。
        • 增强处理(Advice):AOP框架在特定的切入点执行的增强处理。处理有“around”,“before”,“after”等类型
        • 切入点(Pointcut): 可以增强处理的连接点。连接点被添加增强处理,该连接点就变成了切入点。如何使用表达式来定义切入点是AOP的核心。
        • 引入:将方法或字段添加到被处理的类中
        • 目标对象:被AOP框架进行增强处理的对象
        • AOP代理:AOP框架创建的对象,代理就是对目标对象的加强。
          • 可以是JDK动态代理,也可以是cglib代理。前者为实现接口的目标对象的代理,后者不实现接口。
        • 织入(Weaving):将增强处理添加到目标对象中,并创建一个被增强的对象(AOP代理)的过程就是织入。
          • 织入的两种实现方式:
            • 1.编译时增强,如AsoectJ
            • 2.运行时增强,如Sping AOP
    • Spring的AOP支持:

      • spring目前仅支持将方法调用作为连接点
      • AOP编程三件事:
        • 定义普通业务组件
        • 定义切入点,一个切入点可能横切多个业务组件
        • 定义增强处理,增强处理就是在AOP框架为普通业务组件织入的处理动作
        • AOP代理的方法 = 增强处理 + 目标对象的方法
      • Spring的两种选择来定义切入点和增强处理:
        • 1.基于注解的“零配置”方式:使用@Aspect,@Pointcut等注解标注切入点和增强处理。
        • 2.基于XML配置文件的管理方式:使用spring配置文件来定义切入点和增强处理
    • 基于注解的“零配置”方式:

      • <!-- 启动@AspectJ支持 -->
        aop:aspectj-autoproxy/

      • Jar包: aspectjweaver.jar aspectjrt.jar aopalliance.jar

          	定义切面Bean: @Aspect 切面类
          	定义Before增强处理:@Before("切入点表达式")
          		示例:	@Before("execution(* org.crazyit.app.service.impl.*.*(..))")
          	定义切面Bean:
          			@Aspect 切面类
          	定义Before增强处理:
          		@Before("切入点表达式")
          		示例:	@Before("execution(* org.crazyit.app.service.impl.*.*(..))")
          		
          	定义AfterReturning增强处理:
          		// 匹配org.crazyit.app.service.impl包下所有类的、
          		// 所有方法的执行作为切入点
          		@AfterReturning(returning="rvt", pointcut="execution(* org.crazyit.app.service.impl.*.*(..))")
          		
          		@AfterReturning的两个常用属性:
          			pointcut/value:指定切入点对应的切入表达式
          			returning:指定一个形参名,该形参可用于访问目标方法的返回值 
          						如果增强方法的形参类型定义好了,若于目标方法返回值类型不同,
          														则增强方法不会织入。
          		
          	定义AfterThrowing增强处理:
          		主要用于处理程序中未处理的异常
          		@AfterThrowing(throwing="ex", pointcut="execution(* org.crazyit.app.service.impl.*.*(..))")
          			pointcut/value:指定切入点对应的切入表达式
          			throwing:指定一个形参名,该形参可用于访问目标方法的返回值 
          						如果增强方法的形参异常类型定义好了,若于目标方法返回值异常类型不同,
          														则增强方法不会织入。
          
          	After:
          		不管目标方法成功完成,还是异常结束,该Advice都会织入
          		这种Advice类似于finally块
          		通常用来释放资源
          		@After("execution(* org.crazyit.app.service.*.*(..))")
          		
          	Around:
          		这种Advice功能最强大,它既可访问、修改目标方法调用参数,也可访问、修改目标方法的返回值。
          		它甚至完全组阻止目标方法的执行
          		
          		它既可在目标方法之前织入,也可以在目标方法之后织入。
          		
          		弱点:它是线程不安全的,能用其他Advice搞定的,就不要把Around Adivce拿出来。
          		
          		Around Advice方法必须满足如下三点:
          			1.必须声明返回值类型
          			2.必须声明一个类型为ProceedingJoinPoint类型的形参
          			3.必须调用ProceedingJoinPoint形参的proceed()方法,这就是回调目标方法。如果没有这一行,目标方法不会执行。
          		
          		@Around("execution(* org.crazyit.app.service.impl.*.*(..))")
          		
          		public Object processTx(ProceedingJoinPoint jp) throws java.lang.Throwable{
          			System.out.println("执行目标方法之前,模拟开始事务...");
          			
          			// 获取目标方法原始的调用参数
          			Object[] args = jp.getArgs();
          			if(args != null && args.length > 1)
          			{
          				// 修改目标方法的第一个参数
          				args[0] = "【增加的前缀】" + args[0];
          			}
          			
          			// 以改变后的参数去执行目标方法,并保存目标方法执行后的返回值
          			Object rvt = jp.proceed(args);
          			
          			System.out.println("执行目标方法之后,模拟结束事务...");
          			
          			// 如果rvt的类型是Integer,将rvt改为它的平方
          			if(rvt != null && rvt instanceof Integer)
          				rvt = (Integer)rvt * (Integer)rvt;
          			return rvt;
        


        }

          	一般来说,需要修改目标方法的调用参数、修改目标方法的返回值,此时只能用Around
          			组织目标方法执行,用before
          	
          	访问目标方法的参数:
          		JoinPoint类型:
          			方法:
          				Object[] getArgs()	返回执行目标方法时的参数
          				Signature getSignature()	返回被增强的方法的相关信息
          				Object getTarget()	返回目标对象
          				Object getThis()	返回代理对象
          
          	定义切入点:
          		切入点定义:
          			一个切入点表达式
          			一个包含名字和任意参数的方法签名
          			@Aspect
          			public class SystemArchitecture
          			{
          				@Pointcut("execution(* org.crazyit.app.service.impl.*.*(..))")
          				public void myPointcut(){}
          			}
          			
          			// 直接使用SystemArchitecture切面类的myPointcut()切入点
          			@AfterReturning(returning="rvt", pointcut="SystemArchitecture.myPointcut()")
          			
          	切入点指示符,组合符号:
          		// 下面的args(arg0,arg1)会限制目标方法必须有2个形参
          		@AfterReturning(returning="rvt" , pointcut="execution(* org.crazyit.app.service.impl.*.*(..)) && args(arg0,arg1)")
        

5.Spring的缓存机制:

6.Spring的事务:

	@Transactional(propagation=Propagation.REQUIRED ,isolation=Isolation.DEFAULT , timeout=5)
	
	<!-- 配置JDBC数据源的局部事务管理器,使用DataSourceTransactionManager 类 -->
	<!-- 该类实现PlatformTransactionManager接口,是针对采用数据源连接的特定实现-->
	<!-- 配置DataSourceTransactionManager时需要依注入DataSource的引用 -->
	<bean id="transactionManager" 
		class="org.springframework.jdbc.datasource.DataSourceTransactionManager"
		p:dataSource-ref="dataSource"/>
	<!-- 根据Annotation来生成事务代理 -->
	<tx:annotation-driven transaction-manager="transactionManager"/>
评论
  • 按正序
  • 按倒序
  • 按热度
Powered by Waline v2.15.5