第三章 AOP 基于Schema的AOP

时间:2025-01-17 11:35:26

基于Schema定义的切面和前现两种方式定义的切面,内容上都差不多,只是表现形式不一样而已。

3.7.1一般增强的使用


a、目标类
public class Target {
public void say(){
System.out.println("say...");
} public String getName(int id,String name){
System.out.println("getName...");
return "MR"+name+id;
} public void around(){
System.out.println("around...");
} public void targetThrow(){
System.out.println("targetThrow");
throw new RuntimeException("我是一个运行期异常...");
}
}

b、
POJO(增强所在的类
)

public class Pojo {
public void before() {
System.out.println("前置增强");
} public void afterReturning(String retName, int id, String name) {
System.out.println("后置增强,返回值为:"+retName+" 入参为:"+id+"-"+name);
} public Object around(ProceedingJoinPoint point) throws Throwable{
System.out.println("方法执行之前");
Object object = point.proceed();
System.out.println("方法执行之后");
return object;
} public void throwEx(Exception ex){
System.out.println("抛出异常增强,异常信息:"+ex.getMessage());
} public void finalEx(){
System.out.println("Final增强");
}
}
c、
aop
命名空间与
Schema
方式配置
<?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:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
<!-- 目标类 -->
<bean id="target" class="cn.framelife.spring.schema.Target"></bean> <!-- 增强所在的类 -->
<bean id="advisor" class="cn.framelife.spring.schema.Pojo"></bean> <!-- 配置基于schema的切面 -->
<aop:config proxy-target-class="true">
<!-- 确定增强所在类,并引入 -->
<aop:aspect ref="advisor">
<!—
前置增强
method是配置增强所在类中的方法
-->
<aop:before method="before" pointcut="target(cn.framelife.spring.schema.Target)"/> <!—
后置增强
Returning 是返回值,必须和method中的参数名是一样的
在Schema配置中,多个切点函数的与操作是and,或操作是or
-->
<aop:after-returning method="afterReturning" pointcut="execution(* cn.framelife.spring.schema..getName(..)) and args(id,name)" returning="retName" arg-names="retName,id,name"/> <!-- 环绕增强 -->
<aop:around method="around" pointcut="execution(* cn.framelife.spring.schema..around(..))"/> <!—
抛出异常增强
throwing是异常对象,必须和method中的参数是一样的
-->
<aop:after-throwing method="throwEx" pointcut="execution(* cn.framelife.spring.schema..targetThrow(..))" throwing="ex"/> <!-- Final增强 -->
<aop:after method="finalEx" pointcut="execution(* cn.framelife.spring.schema..targetThrow(..))"/>
</aop:config>
</beans>

d、测试

ApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"applicationContext.xml"});
Target target = (Target) context.getBean("target");
target.say();
target.getName(10, "Zhang");
target.around();
target.targetThrow();

e、结果

前置增强
say...
前置增强
getName...
后置增强,返回值为:MRZhang10 入参为:10-Zhang
前置增强
方法执行之前
around...
方法执行之后
前置增强
targetThrow
抛出异常增强,异常信息:我是一个运行期异常...
Final增强
Exception in thread "main" java.lang.RuntimeException: 我是一个运行期异常...

3.7.2引介增强的使用


我们还是使用3.6.2@DeclareParents中的例子:Waiter为目标类,然后让目标类拥有ISeller接口的功能:

http://blog.****.net/p_3er/article/details/9269407

a、两个接口与两个类

目标类与其接口:

  1. public interface IWaiter {
  2. public void service();
  3. }
  1. @Component
  2. public class Waiter implements IWaiter {
  3. @Override
  4. public void service() {
  5. System.out.println("service");
  6. }
  7. }

运行期织入到目标类的功能类与其接口:

  1. public interface ISeller {
  2. public void sell();
  3. }
  1. public class Seller implements ISeller {
  2. @Override
  3. public void sell() {
  4. System.out.println("sell");
  5. }
  6. }

b、配置

<?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:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
<!-- 目标类 -->
<bean id="waiter" class="cn.framelife.spring.schema.Waiter"></bean> <!-- 增强所在的类 -->
<bean id="advisor" class="cn.framelife.spring.schema.Pojo"></bean> <aop:config proxy-target-class="true">
<!—
虽然引介增强不需要在增强所在的类中定义一个方法用于增强的实现,但<aop:aspect ref="advisor">中的ref属性依然要指定一个增强Bean
--> <aop:aspect ref="advisor">
<!—
引介增强
types-matching 目标类
implement-interface 要织入目标类的接口
default-impl 织入接口的实现类
-->
<aop:declare-parents
types-matching="cn.framelife.spring.schema.IWaiter+"
implement-interface="cn.framelife.spring.schema.ISeller"
default-impl="cn.framelife.spring.schema.Seller"/>
</aop:aspect>
</aop:config>
</beans>

c、测试

ApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"applicationContext.xml"});
IWaiter waiter = (IWaiter) context.getBean("waiter");
waiter.service();
ISeller seller = (ISeller)waiter;
seller.sell();

d、结果

service
sell