spring
简介
-
Spring是Java EE编程领域的一个轻量级开源框架,
-
该框架由一个叫Rod Johnson的程序员在 2002 年最早提出并随后创建,
-
是为了解决企业级编程开发中的复杂性,实现敏捷开发的应用型框架 。
-
Spring是一个开源容器框架,它集成各类型的工具,通过核心的Bean factory实现了底层的类的实例化和生命周期的管理。
-
在整个框架中,各类型的功能被抽象成一个个的 Bean,这样就可以实现各种功能的管理,包括动态加载和切面编程。
特点
-
方便解耦,简化开发
通过Spring提供的IoC容器,我们可以将对象之间的依赖关系交由Spring进行控制,避免硬编码所造成的过度程序耦合。有了Spring,用户不必再为单实例模式类、属性文件解析等这些很底层的需求编写代码,可以更专注于上层的应用。 -
AOP编程的支持
通过Spring提供的AOP功能,方便进行面向切面的编程,许多不容易用传统OOP实现的功能可以通过AOP轻松应付。 -
声明式事务的支持
在Spring中,我们可以从单调烦闷的事务管理代码中解脱出来,通过声明式方式灵活地进行事务的管理,提高开发效率和质量。 -
方便程序的测试
可以用非容器依赖的编程方式进行几乎所有的测试工作,在Spring里,测试不再是昂贵的操作,而是随手可做的事情。例如:Spring对Junit4支持,可以通过注解方便的测试Spring程序。 -
方便集成各种优秀框架
Spring不排斥各种优秀的开源框架,相反,Spring可以降低各种框架的使用难度,Spring提供了对各种优秀框架(如Struts,Hibernate、Hessian、Quartz)等的直接支持。 -
降低Java EE API的使用难度
Spring对很多难用的Java EE API(如JDBC,JavaMail,远程调用等)提供了一个薄薄的封装层,通过Spring的简易封装,这些Java EE API的使用难度大为降低。 -
Java 源码是经典学习范例
Spring的源码设计精妙、结构清晰、匠心独运,处处体现着大师对Java设计模式灵活运用以及对Java技术的高深造诣。Spring框架源码无疑是Java技术的最佳实践范例。如果想在短时间内迅速提高自己的Java技术水平和应用开发水平,学习和研究Spring源码将会使你收到意想不到的效果。
入门
spring中最重要的就是IOC( Inversion of Control 控制反转)和AOP( Aspect-Oriented Programming 面向切面编程)
IOC(控制反转)
-
是面向对象编程中的一种设计原则,可以用来减低计算机代码之间的耦合度。
-
最常见的方式叫做依赖注入,还有一种方式叫“依赖查找”
-
通过控制反转,对象在被创建的时候,由一个调控系统内所有对象的外界实体将其所依赖的对象的引用传递给它。也可以说,依赖被注入到对象中。
实现策略
IoC是一个很大的概念,可以用不同的方式实现。其主要形式有两种:
- **依赖查找:**容器提供回调接口和上下文条件给组件。EJB和Apache Avalon 都使用这种方式。这样一来,组件就必须使用容器提供的API来查找资源和协作对象,仅有的控制反转只体现在那些回调方法上(也就是上面所说的 类型1):容器将调用这些回调方法,从而让应用代码获得相关资源。
- **依赖注入:**组件不做定位查询,只提供普通的Java方法让容器去决定依赖关系。容器全权负责的组件的装配,它会把符合依赖关系的对象通过JavaBean属性或者构造函数传递给需要的对象。通过JavaBean属性注射依赖关系的做法称为设值方法注入(Setter Injection);将依赖关系作为构造函数参数传入的做法称为构造器注入(Constructor Injection) [2]
AOP
- 面向切面编程,通过预编译方式和运行期间动态代理实现程序功能的统一维护的一种技术。
- AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。
- 利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的***耦合度***降低, 提高程序的可重用性 ,同时提高了开发的效率
在AOP中,Aspect的含义,可能更多的理解为“切面”比较合适。
可以通过预编译方式和运行其动态代理实现在不修改源代码的情况下给程序动态统一添加功能的一种技术。
编程中,对象与对象之间,方法与方法之间,模块与模块之间都是一个个切面。
我们一般做活动的时候,一般对每一个接口都会做活动的有效性校验(是否开始、是否结束等等)、以及这个接口是不是需要用户登录。
按照正常的逻辑,我们可以这么做。
这有个问题就是,有多少接口,就要多少次代码copy。对于一个“懒人”,这是不可容忍的。好,提出一个公共方法,每个接口都来调用这个接口。这里有点切面的味道了。
同样有个问题,我虽然不用每次都copy代码了,但是,每个接口总得要调用这个方法吧。于是就有了切面的概念,我将方法注入到接口调用的某个地方(切点)。
这样接口只需要关心具体的业务,而不需要关注其他非该接口关注的逻辑或处理。
IOC容器
In Spring, the objects that form the backbone of your application and that are managed by the Spring IoC container are called beans. A bean is an object that is instantiated, assembled, and managed by a Spring IoC container. Otherwise, a bean is simply one of many objects in your application. Beans, and the dependencies among them, are reflected in the configuration metadata used by a container.
在Spring中,构成应用程序主干并由Spring IoC容器管理的对象称为bean。 Bean是由Spring IoC容器实例化,组装和管理的对象。 否则,bean仅仅是应用程序中许多对象之一。 Bean及其之间的依赖关系反映在容器使用的配置元数据中。
org.springframework.context.ApplicationContext
,这个接口代表了IOC容器,并且对beans进行实例化,配置和组装。通过xml文件,注释和Java代码控制容器。
在程序中,通常创建一个实例化的 ClassPathXmlApplicationContext 或 FileSystemXmlApplicationContext
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
基于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
https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="..." class="...">
<!-- collaborators and configuration for this bean go here -->
</bean>
<bean id="..." class="...">
<!-- collaborators and configuration for this bean go here -->
</bean>
<!-- more bean definitions go here -->
</beans>
该 id属性是标识单个bean定义的字符串。
该 class属性定义bean的类型并使用完全限定的班级名称。
实例化容器
ApplicationContext context = new ClassPathXmlApplicationContext("services.xml", "daos.xml");
当一个xml需要加载其他xml中的beans时可以使用
<beans>
<import resource="services.xml"/>
<import resource="resources/messageSource.xml"/>
<import resource="/resources/themeSource.xml"/>
<bean id="bean1" class="..."/>
<bean id="bean2" class="..."/>
</beans>
可以但不建议引用父目录中的文件
使用容器
T getBean(String name, Class requiredType)
获取实例化的bean
// create and configure beans
ApplicationContext context = new ClassPathXmlApplicationContext("services.xml", "daos.xml");
// retrieve configured instance
PetStoreService service = context.getBean("petStore", PetStoreService.class);
// use configured instance
List<String> userList = service.getUsernameList();
bean定义
属性 | 在…中解释 |
---|---|
类 | 实例化豆 |
Name | 命名豆 |
范围 | 豆范围 |
构造函数参数 | 依赖注入 |
物产 | 依赖注入 |
自动接线方式 | 自动装配协作器 |
延迟初始化模式 | Lazy-initialized Beans |
初始化方法 | 初始化回调 |
销毁方式 | 销毁回调 |
bean命名约定
bean名称以小写字母开头,以驼峰命名法进行。
通过在类路径中进行组件扫描,Spring会为未命名的bean生成bean名称 组件,遵循前面描述的规则:本质上,采用简单的类名 并将其初始字符转换为小写。 但是,在(不寻常的)特殊情况下 如果有多个字符且第一个和第二个字符都存在 如果是大写字母,原始外壳将保留下来。
bean可以有一个id和多个name,使用引入别名
<alias name="fromName" alias="toName"/>
实例化bean
构造函数实例化
静态工厂方法实例化
实例工厂方法实例化
依赖注入
分为构造函数注入和setter注入
使用构造函数注入时应注意避免出现依赖循环(鸡与蛋的问题)
例如:类A通过构造函数注入需要类B的实例,并且 B类通过构造函数注入需要A类的实例。 如果您配置 用于将A和B类相互注入的bean,Spring IoC容器 在运行时检测到此循环引用,并引发 BeanCurrentlyInCreationException
。
<!-- 使用setter注入 -->
<bean id="exampleBean" class="examples.ExampleBean">
<!-- setter injection using the nested ref element -->
<property name="beanOne">
<ref bean="anotherExampleBean"/>
</property>
<!-- setter injection using the neater ref attribute -->
<property name="beanTwo" ref="yetAnotherBean"/>
<property name="integerProperty" value="1"/>
</bean>
<bean id="anotherExampleBean" class="examples.AnotherBean"/>
<bean id="yetAnotherBean" class="examples.YetAnotherBean"/>
<!-- 构造函数注入 -->
<bean id="exampleBean" class="examples.ExampleBean">
<!-- constructor injection using the nested ref element -->
<constructor-arg>
<ref bean="anotherExampleBean"/>
</constructor-arg>
<!-- constructor injection using the neater ref attribute -->
<constructor-arg ref="yetAnotherBean"/>
<constructor-arg type="int" value="1"/>
</bean>
<bean id="anotherExampleBean" class="examples.AnotherBean"/>
<bean id="yetAnotherBean" class="examples.YetAnotherBean"/>
p-namespace的使用
<!--不使用p-namespace-->
<bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<!-- results in a setDriverClassName(String) call -->
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mydb"/>
<property name="username" value="root"/>
<property name="password" value="misterkaoli"/>
</bean>
<!--使用p-namespace-->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd">
<!--使用p-namespace需要加上一行约束 -->
<bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close"
p:driverClassName="com.mysql.jdbc.Driver"
p:url="jdbc:mysql://localhost:3306/mydb"
p:username="root"
p:password="misterkaoli"/>
</beans>
<!--直接使用properties-->
<bean id="mappings"
class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer">
<!-- typed as a java.util.Properties -->
<property name="properties">
<value>
jdbc.driver.className=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mydb
</value>
</property>
</bean>
使用Collections进行DI注入
, ,
<bean id="moreComplexObject" class="example.ComplexObject">
<!-- results in a setAdminEmails(java.util.Properties) call -->
<property name="adminEmails">
<props>
<prop key="administrator">administrator@example.org</prop>
<prop key="support">support@example.org</prop>
<prop key="development">development@example.org</prop>
</props>
</property>
<!-- results in a setSomeList(java.util.List) call -->
<property name="someList">
<list>
<value>a list element followed by a reference</value>
<ref bean="myDataSource" />
</list>
</property>
<!-- results in a setSomeMap(java.util.Map) call -->
<property name="someMap">
<map>
<entry key="an entry" value="just some string"/>
<entry key ="a ref" value-ref="myDataSource"/>
</map>
</property>
<!-- results in a setSomeSet(java.util.Set) call -->
<property name="someSet">
<set>
<value>just some string</value>
<ref bean="myDataSource" />
</set>
</property>
</bean>
空字符串注入
<property name="email" value=""/>
空引用注入
<property name="email">
<null/>
</property>
c-namespace的使用
<!-- traditional declaration with optional argument names -->
<bean id="beanOne" class="x.y.ThingOne">
<constructor-arg name="thingTwo" ref="beanTwo"/>
<constructor-arg name="thingThree" ref="beanThree"/>
<constructor-arg name="email" value="something@somewhere.com"/>
</bean>
<!-- c-namespace declaration with argument names -->
<bean id="beanOne" class="x.y.ThingOne" c:thingTwo-ref="beanTwo"
c:thingThree-ref="beanThree" c:email="something@somewhere.com"/>
与p-namespace相似的需要在xml中添加声明
https://www.springframework.org/schema/beans/spring-beans.xsd
depends-on的使用
depends-on
属性可以 使用该元素显式强制一个或多个Bean在Bean初始化 之前 被初始化
<bean id="beanOne" class="ExampleBean" depends-on="manager"/>
Lazy-initialized Beans
在第一次发出请求时才创建Bean,而不是启动时
<bean id="lazy" class="com.something.ExpensiveToCreateBean" lazy-init="true"/>
<!--以下方式一样的效果,在beans中的bean将会在第一次发出请求时才创建-->
<beans default-lazy-init="true">
<!-- no beans will be pre-instantiated... -->
</beans>
自动装配
模式 | 说明 |
---|---|
no | (默认)无自动装配。 Bean引用必须由 定义 ref 元素 。 改变中 对于较大的部署,建议不要使用默认设置,因为 协作者明确提供了更大的控制权和清晰度。 在某种程度上,它 记录系统的结构。 |
byName | 按属性名称自动布线。 Spring寻找与Bean具有相同名称的bean 需要自动接线的属性。 例如,如果将bean定义设置为 按名称自动装配,它包含一个 master 属性(即,它具有一个 setMaster(..) 方法),Spring寻找一个名为的bean定义 master 并使用 它来设置属性。 |
byType | 如果属性类型中恰好存在一个bean,则使该属性自动连接 容器。 如果存在多个,则会引发致命异常,这表明 您可能不会 使用 byType 对该bean 自动装配。 如果没有匹配项 Bean,什么也没发生(未设置属性)。 |
constructor | 类似于 byType 但适用于构造函数参数。 如果不完全正确 容器中构造函数参数类型的一个bean会引发致命错误。 |
使用 byType
或 constructor
自动装配模式,您可以连接阵列和 输入的集合。 在这种情况下,容器中的所有自动接线候选物 提供符合预期类型的匹配项以满足相关性。 您可以自动接线 强类型 Map
如果预期键类型为,则为 实例 String
。 自动接线 Map
实例的值包括所有与预期类型匹配的bean实例,以及 Map
实例的键包含相应的Bean名称。
Bean Scopes
Scope | Description |
---|---|
singleton | (Default) Scopes a single bean definition to a single object instance for each Spring IoC container. |
prototype | Scopes a single bean definition to any number of object instances. |
request | Scopes a single bean definition to the lifecycle of a single HTTP request. That is, each HTTP request has its own instance of a bean created off the back of a single bean definition. Only valid in the context of a web-aware Spring ApplicationContext . |
session | Scopes a single bean definition to the lifecycle of an HTTP Session . Only valid in the context of a web-aware Spring ApplicationContext . |
application | Scopes a single bean definition to the lifecycle of a ServletContext . Only valid in the context of a web-aware Spring ApplicationContext . |
websocket | Scopes a single bean definition to the lifecycle of a WebSocket . Only valid in the context of a web-aware Spring ApplicationContext . |
单例模式:每次请求都返回同一个bean
原型模式:每次请求返回不同的bean
bean的生命周期
<bean id="exampleInitBean" class="examples.ExampleBean" init-method="init"/>
初始化时将会自动调用 init() 方法
<bean id="exampleInitBean" class="examples.ExampleBean" destroy-method="cleanup"/>
结束后自动调用 cleanup() 方法
当设置default-init-method属性时,所有包含的bean都将调用初始化方法
基于注释的容器配置
<?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
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">
<context:annotation-config/>
<!-- <context:annotation-config/> 只在相同的bean上查找注释 定义它的应用程序上下文-->
</beans>
@Required
@Required
注释适用于bean属性setter方法
若被修饰的属性没有填充的话容器将会引发异常
@Required
Spring Framework 5.1开始正式弃用 批注 使用构造函数注入进行必要设置
@Autowired
@Autowired
注释应用于构造函数
@Autowired
注释应用于 传统的 setter方法
@Primary
@Qualifier
可以关联限定符值 使用特定的参数,缩小类型匹配的范围,以便特定的Bean 为每个参数选择。
可以 指定 @Qualifier
在各个构造函数参数上 注释,或 方法参数
@Resource
public class SimpleMovieLister {
private MovieFinder movieFinder;
@Resource(name="myMovieFinder")
public void setMovieFinder(MovieFinder movieFinder) {
this.movieFinder = movieFinder;
}
}
@Value
@Value
通常用于注入外部属性
自动检测类并注册Bean定义
Spring可以自动检测构造型类并注册相应的类 BeanDefinition
的实例 ApplicationContext
使用 @Bean
注释
@Bean
是方法级别的注释,是XML 的直接类似物 元素 。 批注支持所提供的某些属性
,例如: * 初始化方法 * 破坏方法 * 自动接线 * name
。
您可以在- @Bean
注释 @Configuration
或 @Component
-带注释的类。
@Scope
注释
您可以指定用 定义的bean @Bean
注释 应该有一个 具体范围。
Aspect Oriented Programming with Spring
AOP概念
让我们首先定义一些主要的AOP概念和术语。 这些条款不是 特定于弹簧。 不幸的是,AOP术语并不是特别直观。 但是,如果使用Spring自己的术语,将会更加令人困惑。
- 方面:涉及多个类别的关注点的模块化。 事务管理是企业Java中横切关注点的一个很好的例子 应用程序。 在Spring AOP中,方面是通过使用常规类来实现的 ( 基于模式的方法 )或带有
@Aspect
批注( @AspectJ样式 )。 - 连接点:程序执行过程中的一个点,例如执行 方法或异常的处理。 在Spring AOP中,连接点总是 表示方法执行。
- 建议:方面在特定的连接点处采取的操作。 不同类型的 建议包括“周围”,“之前”和“之后”建议。 (讨论了咨询类型 后来)。许多AOP框架(包括Spring)将建议建模为拦截器, 在连接点周围保持一串拦截器。
- 切入点:与连接点匹配的谓词。 咨询与 切入点表达式,并在与该切入点匹配的任何连接点处运行(例如, 具有特定名称的方法的执行)。 连接点匹配的概念 切入点表达式是AOP的核心,Spring使用AspectJ切入点 默认情况下为表达语言。
- 简介:代表类型声明其他方法或字段。 弹簧 通过AOP,您可以向任何对象引入新的接口(以及相应的实现) 建议对象。 例如,您可以使用简介来使Bean实现
IsModified
接口,以简化缓存。 (简介称为 AspectJ社区中的类型间声明。) - 目标对象:一个或多个方面建议的对象。 也称为 “建议对象”。 由于Spring AOP是使用运行时代理实现的,因此 对象始终是代理对象。
- AOP代理:由AOP框架创建的,用于实现方面的对象 合同(建议方法执行等)。 在Spring Framework中,一个AOP代理 是JDK动态代理或CGLIB代理。
- 编织:将方面与其他应用程序类型或对象链接以创建一个 建议对象。 这可以在编译时完成(使用AspectJ编译器 例如),加载时间或运行时。 与其他纯Java AOP框架一样,Spring AOP也是如此, 在运行时执行编织。
最好的做法是对接口进行编程,而不要对类,业务进行编程 类通常实现一个或多个业务接口。
通过XML配置启用@AspectJ支持
<aop:aspectj-autoproxy/>
声明切入点
@Pointcut("execution(* transfer(..))") // the pointcut expression
private void anyOldTransfer() {} // the pointcut signature
形成 值的切入点表达式 表达式 @Pointcut
注释 是一个正则 AspectJ 5切入点表达式。
支持的切入点指示符
Spring AOP支持以下在切入点中使用的AspectJ切入点指示符(PCD) 表达式:
execution
:用于匹配方法执行的连接点。 这是主要的 使用Spring AOP时要使用的切入点指示符。within
:将匹配限制为某些类型内的连接点(执行 在使用Spring AOP时在匹配类型内声明的方法)。this
:限制匹配连接点(使用Spring时方法的执行 AOP),其中bean引用(Spring AOP代理)是给定类型的实例。target
:限制匹配连接点(使用时执行方法 Spring AOP),其中目标对象(正在代理的应用程序对象)是一个实例 给定类型的。args
:限制匹配连接点(使用Spring时方法的执行 AOP),其中参数是给定类型的实例。@target
:限制匹配连接点(使用时执行方法 Spring AOP),其中执行对象的类具有给定类型的注释。@args
:限制匹配连接点(使用Spring时方法的执行 AOP),其中传递的实际参数的运行时类型具有 给定类型。@within
:将匹配限制为具有给定类型的连接点 批注(在具有给定批注的类型中声明的方法的执行 使用Spring AOP)。@annotation
:将匹配限制为连接点的主题所在的连接点 (在Spring AOP中运行的方法)具有给定的注释。
声明一个切面
使用模式支持时,切面是一个常规Java对象,在其中定义为Bean 您的Spring应用程序上下文。 状态和行为在字段中捕获, 对象的方法,切入点和建议信息都在XML中捕获。
您可以使用 声明一个切面 ``元素 ,并引用支持bean 通过使用 ref
属性,如以下示例所示:
<aop:config>
<aop:aspect id="myAspect" ref="aBean">
...
</aop:aspect>
</aop:config>
<bean id="aBean" class="...">
...
</bean>
支持方面的Bean( aBean
在这种情况下)当然可以配置并 依赖注入就像其他任何Spring bean一样。
声明切入点
您可以在 内声明命名的切入点 ``元素 ,让切入点 定义可以在多个方面和顾问之间共享。
表示服务层中任何业务服务的执行的切入点可以 定义如下:
<aop:config>
<aop:pointcut id="businessService"
expression="execution(* com.xyz.myapp.service.*.*(..))"/>
</aop:config>
请注意,切入点表达式本身正在使用相同的AspectJ切入点表达式 如 所述的语言 @AspectJ支持中 。 如果您使用基于架构的声明 样式,您可以引用在类型(@Aspects)中定义的命名切入点 切入点表达式。 定义上述切入点的另一种方法如下:
<aop:config>
<aop:pointcut id="businessService"
expression="com.xyz.myapp.CommonPointcuts.businessService()"/>
</aop:config>
假定您具有“ 的 CommonPointcuts
描述 方面 共享公共切入点定义”中 。
然后,在方面内声明切入点与声明顶级切入点非常相似, 如下例所示:
<aop:config>
<aop:aspect id="myAspect" ref="aBean">
<aop:pointcut id="businessService"
expression="execution(* com.xyz.myapp.service.*.*(..))"/>
...
</aop:aspect>
</aop:config>
与@AspectJ方面几乎相同,通过使用基于架构的声明的切入点 定义样式可以收集连接点上下文。 例如,以下切入点 收集 this
对象作为连接点上下文,并将其传递给建议:
<aop:config>
<aop:aspect id="myAspect" ref="aBean">
<aop:pointcut id="businessService"
expression="execution(* com.xyz.myapp.service.*.*(..)) && this(service)"/>
<aop:before pointcut-ref="businessService" method="monitor"/>
...
</aop:aspect>
</aop:config>
必须声明该建议以通过以下方式接收收集的连接点上下文: 匹配名称的参数,如下所示:
public void monitor(Object service) {
// ...
}
组合切入点子表达式时, &&
在XML中很尴尬 文件,这样你就可以使用 and
, or
以及 not
关键字的地方 &&
, ||
,和 !
。 例如,上一个切入点可以更好地写为 如下:
<aop:config>
<aop:aspect id="myAspect" ref="aBean">
<aop:pointcut id="businessService"
expression="execution(* com.xyz.myapp.service.*.*(..)) and this(service)"/>
<aop:before pointcut-ref="businessService" method="monitor"/>
...
</aop:aspect>
</aop:config>
请注意,以这种方式定义的切入点由其XML引用, id
并且不能 用作命名切入点以形成复合切入点。 中的命名切入点支持 因此,基于架构的定义样式比@AspectJ提供的样式更受限制 风格。
五种切入建议
< aop:before > 在运行匹配的方法之前,建议运行之前
< aop:after-returning> 返回的建议在匹配的方法执行正常完成时运行。 它是 在内部声明 ``的方式与建议之前相同。
< aop:after-throwing > 抛出建议后,当匹配的方法执行通过抛出 例外。
< aop:after > 无论最终如何执行匹配的方法,建议(最终)都会运行。
< aop:around > 围绕建议运行“围绕”匹配的方法 执行。 它有机会在方法运行之前和之后进行工作 并确定何时,如何以及该方法实际上是否可以运行。 周围建议通常用于共享状态执行之前和之后的状态 线程安全的方式(例如,启动和停止计时器)。
<aop:aspect id="aroundExample" ref="aBean">
<aop:around
pointcut-ref="businessService"
method="doBasicProfiling"/>
...
</aop:aspect>