`
lucky520
  • 浏览: 35470 次
  • 性别: Icon_minigender_2
  • 来自: 武汉
社区版块
存档分类
最新评论

Spring AOP之增强

阅读更多

      继续Spring AOP的学习,总所周知,aop的魅力所在就是它能在方法前后起拦截作用,以便我们定义横切逻辑代码。增强大致分为5类:前置增强(就是在目标方法调用前拦截),后置增强(就是在目标方法调用之后拦截),异常增强(就是在目标方法抛出后拦截),引介增强(它是一种特殊的增强,可以在目标类添加属性和方法,通过拦截定义一个接口,让目标代理实现这个接口,它的连接点是类级别的),而前面三种增强则是方法级别的。以上四种增强接口是Spring定义的,还有只用环绕增强(目标方法前后拦截)是AOP联盟定义的接口。其实aop增强很简单,通过实现这些增强接口,在实现这些接口的方法中定义横切逻辑,然后通过配置spring配置文件,就可以完成将增强织入到目标方法中了。

 

首先,以前置增强为例,大家都知道如果我们到餐厅去,服务员首先会欢迎顾客,然后再为我们提供服务。这里我们一个

Waiter类:

package com.me.services;

public interface Waiter {
	void greetTo(String name);
	void serveTo(String name);
}

 现在我们来看一个训练不足的服务生的服务情况:

package com.me.services.imp;

import com.me.services.Waiter;

public class LuceyWaiter implements Waiter {

	public void greetTo(String name) {
		System.out.println("greet to "+name);
	}

	public void serveTo(String name) {
		System.out.println("server "+name);
	}

}

Lucey走到闷不做声走到顾客面前, 提供服务,那么,我们就需要对每个服务生进行规范,在服务之前要行礼貌用语。

package com.me.advice;

import java.lang.reflect.Method;

import org.springframework.aop.MethodBeforeAdvice;

public class GreetingBeforeAdvice implements MethodBeforeAdvice {

	public void before(Method method, Object[] args, Object obj)
			throws Throwable {
		String clientName = args[0].toString();
		System.out.println("How are you,"+clientName+"!");
	}

}

 这里我们就用到了前置增强,通过实现org.springframework.aop.MethodBeforeAdvice接口的before方法定义逻辑代码。before中的三个参数分别代表:目标方法,目标方法的参数列表,目标实例。

目标对象也有了,增强也有了,接下来如何把增强织入的目标对象生成代理呢?上一次博客写到spring的代理机制,我们知道可以通过JDK和CGLib两种方式动态创建代理。但是那样我们代码太过麻烦,要自定义一个类实现指定接口,那有没有简单的方法呢?当然,spring为我们提供了ProxyFactoryBean,它帮我们完成了上面通过JDK,CGLib创建代理那些复杂的工作,我们只需要在spring中配置一下即可完成织入工作,^-^

<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-2.0.xsd">
	<!-- 需要代理的业务类 -->
	<bean id="target" class="com.me.services.imp.LuceyWaiter"></bean>
	<!-- 指定增强,一个业务类可以有多个增强形成增强链,调用顺序与添加顺序一致 -->
	<bean id="greetAdvice" class="com.me.advice.GreetingBeforeAdvice"></bean>
	<!-- 利用ProxyFactoryBean创建代理 -->
	<bean id="waiter" class="org.springframework.aop.framework.ProxyFactoryBean">
	<!-- 代理要实现的接口,可以是多个接口 -->		
		<property name="proxyInterfaces" value="com.me.services.Waiter"/>
		<property name="target" ref="target"/>
		<!-- 需要织入目标对象的0增强数组 -->
		<property name="interceptorNames">
			<list>
				<value>greetAdvice</value>
			</list>
		</property>
	</bean>
</beans>

关于ProxyFactoryBean的工作原理将在以后写到,但需要进一步了解它的几个常用配置属性,除上面的属性外,还有singleton:返回代理是否为单实例,默认true.

optimize:当设置为true时,强制使用CGLib代理。对于单实例推荐配置true,但对于作用域类型的代理推荐false.

proxyTargetClass:是否对类代理(不是对接口进行代理),设置为true使用CGLib代理。当然如果设置为true就不必设置proxyInterfaces属性了,及时设置了也将被忽略。下面来一段测试代码吧:

package com.me.test;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.me.services.Waiter;

public class TestBeforeAdvice {

	public static void main(String[] args) {
		ApplicationContext cxt = new ClassPathXmlApplicationContext("applicationContext.xml");
        Waiter waiter = (Waiter)cxt.getBean("waiter");
        waiter.greetTo("John");
	}

}

 后置增强,异常抛出增强和环绕增强用法差不多,只是实现的接口不一样罢了。下面就做说明了,我将测试代码上传供大家学习。接下来,来谈谈我们类级别的增强,即引介增强,我们还是根据上一篇博客代理机制的示例来学习引介增强。我们前面用到监测用户添加和删除性能,现在将起改为可控的。即维护人员可控制是否采用性能监控。

首先定义一个用于标志目标类是否支持性能监控的接口:

package com.me.advice;

public interface Monitorable {
	/** 
	 * @param IsActive 
	 * true:性能监控功能激活
	 * false: 性能监控功能关闭
	 */
	public void setMonitorActive(boolean IsActive);
}

  通过继承DelegatingIntroductionInterceptor为目标类引入性能监控功能,代码如下:

package com.me.util;

import org.aopalliance.intercept.MethodInvocation;
import org.springframework.aop.support.DelegatingIntroductionInterceptor;

@SuppressWarnings("serial")
public class ControllablePerformanceMonitor extends
		DelegatingIntroductionInterceptor implements Monitorable {
	//为了解决线程安全问题
	private ThreadLocal<Boolean> statusMap = new ThreadLocal<Boolean>();
	
	public void setMonitorActive(boolean IsActive) {
		statusMap.set(new Boolean(IsActive));		
	}
	
	public Object invoke(MethodInvocation mi)throws Throwable{
		Object obj = null;
		if(statusMap.get()!=null && statusMap.get().booleanValue()){
			PerformanceMonitor pm = new PerformanceMonitor();
			pm.start(mi.getClass().getName()+"."+mi.getMethod().getName());
			obj = super.invoke(mi);
			pm.end();
		}else{
			obj = super.invoke(mi);
		}
		return obj;
	}

}

 

配置引介增强

<bean id="target" class="com.me.services.imp.UserServiceImp"/>
 	<bean id="pmonitor" class="com.me.util.ControllablePerformanceMonitor"/>
 	<!-- 创建代理 -->
 	<bean id="userService" class="org.springframework.aop.framework.ProxyFactoryBean">
 	<!-- 引介增强所实现的接口 -->
 	<property name="interfaces">
 		<value>com.me.util.Monitorable</value>
 	</property>
 	<property name="target" ref="target"/>
 	<property name="interceptorNames">
 		<idref local="pmonitor"/>
 	</property>
 	<!-- 由于引介增强通过子类创建代理,所以强制使用CGLib代理实现机制 -->
 	<property name="proxyTargetClass" value="true"/>
 	</bean>

 测试引介增强

package com.me.test;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.me.services.UserService;
import com.me.entity.*;
import com.me.util.Monitorable;
public class TestCotrollerPerformance {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		 ApplicationContext cxt = new ClassPathXmlApplicationContext("applicationContext.xml");
		 UserService service = (UserService)cxt.getBean("userService");
		 service.deleteUser(1);
		 service.insertUser(new User());
		 //这里强制成果,说明返回的代理引入了Monitorable接口
		 Monitorable monitor = (Monitorable)service;
		 monitor.setMonitorActive(true);
		 
		 service.deleteUser(1);
		 service.insertUser(new User());
	}

}

 

 

 

 

 

3
0
分享到:
评论

相关推荐

    Spring AOP之5种增强方法应用范例

    Spring AOP之5种增强方法应用范例 ,具体效果和过程看博文 http://blog.csdn.net/evankaka/article/details/45241863

    进击的编程思想!带你学Spring AOP核心编程思想教程 新角度学面向切面编程

    Spring AOP 使用纯 Java 实现,不需要专门的编译过程和类加载器,在运行期间通过代理方式向目标类植入增强的代码。 课程内容非常详细的介绍Spring AOP全栈技术点,开篇帮助同学们进行知识储备,夯实基础就是核心!...

    Spring3.2 AOP extra jar

    Spring3.2 版本中已不再提供第三放jar包,而在实际“AOP”应用中需要引入其他的jar包;此为,已知的jar包(最新版本)。

    spring AOP的代码实例

    spring AOP的代码实例,了解面向切面编程思想的精髓,

    线程池中使用spring aop事务增强

    主要介绍了线程池中使用spring aop事务增强,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

    Spring AOP详细介绍.docx

    (3)Advice(通知):AOP在特定的切入点上执行的增强处理,有before,after,afterReturning,afterThrowing,around (4)Pointcut(切入点):就是带有通知的连接点,在程序中主要体现为书写切入点表达式 (5)AOP代理:AOP框架...

    Spring AOP 原理剖析,这一篇就够

    Spring AOP 学习记录 AOP(面向切面编程)方面的知识又是看了忘忘了看,今天有空记录下AOP的知识点。主要分为以下几方面: ​ 1、AOP相关术语 ​ 2、基础知识及示例 ​ 3、增强分类 1、AOP相关术语 连接点...

    Java八股文-Spring AOP

    切点用于来限定Spring-AOP启动的范围,通常我们采用表达式的方式来设置,所以关键词 是范围 通知(Advice) 通知是织入到目标类连接点上的一段程序代码。在Spring中,像 BeforeAdvice等还带有方位信息 通知是直译...

    SpringAOP使用介绍,从前世到今生

    SpringAOP发展到现在出现的全部3种配置方式。 由于Spring强大的向后兼容性,实际代码中往往会出现很多配置混杂的情况,而且居然还能工作,本文希望帮助大家理清楚这些知识。 我们先来把它们的概念和关系说说清楚。 ...

    Spring Aop Advise方法(增强方法) 中获取目标方法的参数

    NULL 博文链接:https://jackyin5918.iteye.com/blog/1918076

    spring AOP代理机制.docx

    sping AOP面向切面的编程,程序运行过程中动态加入所需代码等,对公共的问题进行集中处理,具体的实现有动态代理与静态代理,本文通过对AOP的代理机制,前置、后置、环绕、异常的通知进行了综合总结和运用!

    spring AOP的Around增强实现方法分析

    主要介绍了spring AOP的Around增强实现方法,结合实例形式分析了spring面向切面AOP的Around增强具体步骤与相关操作方法,需要的朋友可以参考下

    springboot2-spring5-studying:Springboot2,Spring源码学习项目,涉及SpringBoot2自动装配实现机制,Spring AOP动态代理以及IOC各种扩展接口的实现方式

    微信公众号:吉姆餐厅ak学习更多原始知识,欢迎关注。 概述Spring Aop在Spring框架中的布局举足轻重,主要用于实现事务,缓存,安全等功能。... advice :通知,也就是aop中增强的方法。对以上三类核心类对应的UML分别

    spring AOP的After增强实现方法实例分析

    主要介绍了spring AOP的After增强实现方法,结合实例形式分析了spring面向切面AOP的After增强实现步骤与相关操作技巧,需要的朋友可以参考下

    Spring AOP与动态代理

    Spring AOP使用的动态代理,所谓的动态代理就是说AOP框架不会去修改字节码,而是在内存中临时为方法生成一个AOP对象,这个AOP对象包含了目标对象的全部方法,并且在特定的切点做了增强处理,并回调原对象的方法。...

    Spring_aop额外所需增强包.zip

    aopalliance.jar,aspectjrt.jar,aspectjweaver.jar包全部打包在这里了,省的到处找地方了

    《Java EE企业开发框架》 Spring AOP实验报告

    1. 定义一个MyClass类(或接口),包括math()、english()和physics()方法,可以简单模拟输出:上数学课/英语课/物理...请选择使用JDK动态代理、CGLIB代理、ProxyFactoryBean或者AspectJ中的某一种方式来实现增强处理。

Global site tag (gtag.js) - Google Analytics