Spring核心概念
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring核心概念相关的知识,希望对你有一定的参考价值。
Ioc(控制反转),也被称为依赖注入(Dependency Injection,DI),是面向对象编程中的一种设计理念,用来降低程序代码之间的耦合度。
依赖:在代码中一般指通过局部变量、方法参数、返回值等建立的对于其它对象的调用关系。
依赖注入:设值注入和构造注入
1.设值注入
1 package cn.springdemo; 2 3 /** 4 * 第一个Spring,输出"Hello,Spring!"。 5 * 6 * @author 北大青鸟 7 */ 8 public class HelloSpring { 9 // 定义who属性,该属性的值将通过Spring框架进行设置 10 private String who = null; 11 12 /** 13 * 定义打印方法,输出一句完整的问候。 14 */ 15 public void print() { 16 System.out.println("Hello," + this.getWho() + "!"); 17 } 18 19 public String getWho() { 20 return who; 21 } 22 public void setWho(String who) { 23 this.who = who; 24 } 25 26 }
1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns="http://www.springframework.org/schema/beans" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xsi:schemaLocation="http://www.springframework.org/schema/beans 5 http://www.springframework.org/schema/beans/spring-beans-3.2.xsd"> 6 <!-- 通过bean元素声明需要Spring创建的实例。该实例的类型通过class属性指定, 7 并通过id属性为该实例指定一个名称,以便在程序中使用 --> 8 <bean id="helloSpring" class="cn.springdemo.HelloSpring"> 9 <!-- property元素用来为实例的属性赋值,此处实际是调用setWho()方法实现赋值操作 --> 10 <property name="who"> 11 <!-- 此处将字符串"Spring"赋值给who属性 --> 12 <value>Spring</value> 13 </property> 14 </bean> 15 </beans>
1 package test; 2 3 import org.junit.Test; 4 import org.springframework.context.ApplicationContext; 5 import org.springframework.context.support.ClassPathXmlApplicationContext; 6 7 import cn.springdemo.HelloSpring; 8 9 public class HelloSpringTest { 10 11 @Test 12 public void helloSpring() { 13 // 通过ClassPathXmlApplicationContext实例化Spring的上下文 14 ApplicationContext context = new ClassPathXmlApplicationContext( 15 "applicationContext.xml"); 16 // 通过ApplicationContext的getBean()方法,根据id来获取bean的实例 17 HelloSpring helloSpring = (HelloSpring) context.getBean("helloSpring"); 18 // 执行print()方法 19 helloSpring.print(); 20 } 21 22 }
除了ClassPathXmlApplicationContext、ApplicationContext接口还有其它实现类,例如FileSystemXmlApplicationContext也可以用于加载Spring配置文件。
ClassPathXmlApplicationContext:读取的默认路径为src下一级目录。
FileSystemXmlApplicationContext:读取的默认路径为项目名下一级目录,与src同级。
2.构造注入
1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns="http://www.springframework.org/schema/beans" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xsi:schemaLocation="http://www.springframework.org/schema/beans 5 http://www.springframework.org/schema/beans/spring-beans-3.2.xsd "> 6 <!-- 定义UserDaoImpl对象,并指定id为userDao --> 7 <bean id="userDao" class="dao.impl.UserDaoImpl" /> 8 <!-- 定义UserServiceImpl对象,并指定id为userService --> 9 <bean id="userService" class="service.impl.UserServiceImpl"> 10 <!-- 通过定义的单参构造为userService的dao属性赋 值 --> 11 <constructor-arg> 12 <!-- 引用id为userDao的对象为userService的dao属性赋值 --> 13 <ref bean="userDao" /> 14 </constructor-arg> 15 </bean> 16 </beans>
一个<constructor-arg>元素表示构造方法的一个参数,且使用时不区分顺序。当构造方法的参数出现混淆、无法区分时,可以通过<constructor-arg>元素的index属性指定该参数的位置索引,位置从0开始。<constructor-arg>还提供了type属性指定参数的类型。
=======================================================================================================================================================================================================
AOP(Aspect Oriented Programming,AOP)面向切面编程,简单来说就是在不改变原程序的基础上为代码段增加新的功能,对代码段进行增强处理。
切面(Aspect):一个模块化的横切逻辑(或称横切关注点),可能会横切多个对象。
连接点(Join Point):程序执行中的某个具体的执行点。
增强处理(Advice):切面在某个特定链接点上执行的代码逻辑。
切入点(Pointcut):对连接点的特征进行描述,可以使用正则表达式。增强处理和一个切入点表达式相关联,并在与这个切入点匹配的某个连接点上运行。
目标处理(Target Object):被一个或多个切面增强的对象。
AOP代理(AOP proxy):由AOP框架所创建的对象,实现执行增强处理方法等功能。
织入(Weaving):将增强处理连接到应用程序中的类型或对象上的过程。
增强处理类型:在原对象的方法之前插入的增强为前置增强,该方法正常执行完以后插入的增强处理为后置增强,此外还有环绕增强、异常抛出增强、最终增强等类型。
前置增强和后置增强
1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns="http://www.springframework.org/schema/beans" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xmlns:aop="http://www.springframework.org/schema/aop" 5 xsi:schemaLocation="http://www.springframework.org/schema/beans 6 http://www.springframework.org/schema/beans/spring-beans-3.2.xsd 7 http://www.springframework.org/schema/aop 8 http://www.springframework.org/schema/aop/spring-aop-3.2.xsd"> 9 <bean id="dao" class="dao.impl.UserDaoImpl"></bean> 10 <bean id="service" class="service.impl.UserServiceImpl"> 11 <property name="dao" ref="dao"></property> 12 </bean> 13 <!-- 声明增强方法所在的Bean --> 14 <bean id="theLogger" class="aop.UserServiceLogger"></bean> 15 <!-- 配置切面 --> 16 <aop:config> 17 <!-- 定义切入点 --> 18 <aop:pointcut id="pointcut" 19 expression="execution(public void addNewUser(entity.User))" /> 20 <!-- 引用包含增强方法的Bean --> 21 <aop:aspect ref="theLogger"> 22 <!-- 将before()方法定义为前置增强并引用pointcut切入点 --> 23 <aop:before method="before" pointcut-ref="pointcut"></aop:before> 24 <!-- 将afterReturning()方法定义为后置增强并引用pointcut切入点 --> 25 <!-- 通过returning属性指定为名为result的参数注入返回值 --> 26 <aop:after-returning method="afterReturning" 27 pointcut-ref="pointcut" returning="result" /> 28 </aop:aspect> 29 </aop:config> 30 </beans>
1 package aop; 2 3 import java.util.Arrays; 4 import org.apache.log4j.Logger; 5 import org.aspectj.lang.JoinPoint; 6 7 public class UserServiceLogger { 8 private static final Logger log = Logger.getLogger(UserServiceLogger.class); 9 10 public void before(JoinPoint jp) { 11 log.info("调用 " + jp.getTarget() + " 的 " + jp.getSignature().getName() 12 + " 方法。方法入参:" + Arrays.toString(jp.getArgs())); 13 } 14 15 public void afterReturning(JoinPoint jp, Object result) { 16 log.info("调用 " + jp.getTarget() + " 的 " + jp.getSignature().getName() 17 + " 方法。方法返回值:" + result); 18 } 19 20 }
为了能够在增强方法中获取当前连接点的信息,可以在增强方法中声明一个JoinPoint类型的参数,Spring会自动注入该实例。通过该实例的getTarget()方法可以得到被代理的目标对象,getSignature()方法返回被代理的目标方法,getArgs()方法返回传递给目标方法的参数数组。对于后置增强的方法,还可以定义一个参数用于接收目标方法的返回值。
异常抛出增强
public void afterThrowing(JoinPoint jp, RuntimeException e) { log.error(jp.getSignature().getName() + " 方法发生异常:" + e); }
1 <bean id="dao" class="dao.impl.UserDaoImpl"></bean> 2 <bean id="service" class="service.impl.UserServiceImpl"> 3 <property name="dao" ref="dao"></property> 4 </bean> 5 <!-- 声明增强方法所在的Bean --> 6 <bean id="theLogger" class="aop.ErrorLogger"></bean> 7 <!-- 配置切面 --> 8 <aop:config> 9 <!-- 定义切入点 --> 10 <aop:pointcut id="pointcut" expression="execution(* service.UserService.*(..))" /> 11 <!-- 引用包含增强方法的Bean --> 12 <aop:aspect ref="theLogger"> 13 <!-- 将afterThrowing()方法定义为异常抛出增强并引用pointcut切入点 --> 14 <!-- 通过throwing属性指定为名为e的参数注入异常实例 --> 15 <aop:after-throwing method="afterThrowing" 16 pointcut-ref="pointcut" throwing="e" /> 17 </aop:aspect> 18 </aop:config>
环绕增强
public Object aroundLogger(ProceedingJoinPoint jp) throws Throwable { log.info("调用 " + jp.getTarget() + " 的 " + jp.getSignature().getName() + " 方法。方法入参:" + Arrays.toString(jp.getArgs())); try { Object result = jp.proceed();//执行目标方法并获得其返回值 log.info("调用 " + jp.getTarget() + " 的 " + jp.getSignature().getName() + " 方法。方法返回值:" + result); return result; } catch (Throwable e) { log.error(jp.getSignature().getName() + " 方法发生异常:" + e); throw e; } finally { log.info(jp.getSignature().getName() + " 方法结束执行。"); }
1 <bean id="dao" class="dao.impl.UserDaoImpl"></bean> 2 <bean id="service" class="service.impl.UserServiceImpl"> 3 <property name="dao" ref="dao"></property> 4 </bean> 5 <!-- 声明增强方法所在的Bean --> 6 <bean id="theLogger" class="aop.AroundLogger"></bean> 7 <!-- 配置切面 --> 8 <aop:config> 9 <!-- 定义切入点 --> 10 <aop:pointcut id="pointcut" expression="execution(* service.UserService.*(..))" /> 11 <!-- 引用包含增强方法的Bean --> 12 <aop:aspect ref="theLogger"> 13 <!-- 将aroundLogger()方法定义为环绕增强并引用pointcut切入点 --> 14 <aop:around method="aroundLogger" pointcut-ref="pointcut"/> 15 </aop:aspect> 16 </aop:config>
ProceedingJoinPoint是JoinPoint的子接口,其不但封装目标方法及其入参数组,还封装了被代理的目标对象,通过它的proceed()方法可以调用真正的目标方法,从而达到对连接点的完全控制。
环绕增强在目标的前后都可以织入增强处理。环绕增强是功能最强大的增强处理,Spring将目标方法的控制权全部交给了它。在环绕增强处理中,可以获取或修改目标方法的参数、返回值,可以对它进行异常处理,甚至可以决定目标方法是否被执行。
最终增强
public void afterLogger(JoinPoint jp) { log.info(jp.getSignature().getName() + " 方法结束执行。"); }
1 <bean id="dao" class="dao.impl.UserDaoImpl"></bean> 2 <bean id="service" class="service.impl.UserServiceImpl"> 3 <property name="dao" ref="dao"></property> 4 </bean> 5 <!-- 声明增强方法所在的Bean --> 6 <bean id="theLogger" class="aop.AfterLogger"></bean> 7 <!-- 配置切面 --> 8 <aop:config> 9 <!-- 定义切入点 --> 10 <aop:pointcut id="pointcut" expression="execution(* service.UserService.*(..))" /> 11 <!-- 引用包含增强方法的Bean --> 12 <aop:aspect ref="theLogger"> 13 <!-- 将afterLogger()方法定义为最终增强并引用pointcut切入点 --> 14 <aop:after method="afterLogger" pointcut-ref="pointcut"/> 15 </aop:aspect> 16 </aop:config>
最终增强的特点是无论方法抛出异常还是正常退出,该增强都会得到执行,类似于异常处理机制中的finally块的作用,一般用于释放资源。
以上是关于Spring核心概念的主要内容,如果未能解决你的问题,请参考以下文章