AOP的实现者:AspectJ、JBoss AOP、Spring AOP,其中AspectJ提供语言级别的AOP实现,有一个专门的编译器生成遵守Java字节编码规范的Class文件。在Spring中,可以无缝集成Spring AOP、IoC、AspectJ。
Spring AOP使用了两种代理机制:一种是基于JDK的动态代理,另一种是基于CGLib的动态代理,之所以需要两种代理机制,很大程度上是因为JDK本身只提供接口的代理,而不支持类的代理。
》JDK动态代理实例:
package com.springzoo.proxy; public interface ForumService { void removeTopic(int topicId); void removeForum(int forumId); }
package com.springzoo.proxy; public class ForumServiceImpl implements ForumService { public void removeTopic(int topicId) { System.out.println("模拟删除Topic记录:"+topicId); try { Thread.currentThread().sleep(20); } catch (Exception e) { throw new RuntimeException(e); } } public void removeForum(int forumId) { System.out.println("模拟删除Forum记录:"+forumId); try { Thread.currentThread().sleep(40); } catch (Exception e) { throw new RuntimeException(e); } } }
package com.springzoo.proxy; public class PerformanceMonitor { private static ThreadLocal<MethodPerformace> performaceRecord = new ThreadLocal<MethodPerformace>(); public static void begin(String method) { System.out.println("begin monitor..."); MethodPerformace mp = performaceRecord.get(); if(mp == null){ mp = new MethodPerformace(method); performaceRecord.set(mp); }else{ mp.reset(method); } } public static void end() { System.out.println("end monitor..."); MethodPerformace mp = performaceRecord.get(); mp.printPerformace(); } }
package com.springzoo.proxy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; public class PerformaceHandler implements InvocationHandler { private Object target; public PerformaceHandler(Object target){ this.target = target; } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { PerformanceMonitor.begin(target.getClass().getName()+"."+ method.getName()); Object obj = method.invoke(target, args); PerformanceMonitor.end(); return obj; } }
最后测试下:
package com.springzoo.proxy; public class TestForumService { public static void main(String[] args) { // 使用JDK动态代理 // ForumService target = new ForumServiceImpl(); // PerformaceHandler handler = new PerformaceHandler(target); // ForumService proxy = (ForumService) Proxy.newProxyInstance(target // .getClass().getClassLoader(), // target.getClass().getInterfaces(), handler); // proxy.removeForum(10); // proxy.removeTopic(1012); //使用CGLib动态代理 CglibProxy proxy = new CglibProxy(); ForumService forumService = (ForumService)proxy.getProxy(ForumServiceImpl.class); forumService.removeForum(10); forumService.removeTopic(1023); } }
以上的手动编写AOP逻辑和植入非常的不方便,而spring AOP就是要解决这个问题。spring AOP通过Pointcut指定在哪些类的哪些方法上织入横切逻辑,通过Advice描述横切逻辑和方法的织入方位(方法前、方法后、方法前后,跑出异常时)。此外,spring通过Advisor切面将Pointcut和Advice两者组装起来。有了Advisor的信息,spring就可以利用JDK或者CGLib的动态代理技术采用统一的方式为目标Bean创建织入切面的代理对象了。
动态代理性能:CGLib的代理对象性能是JDK的10倍,但是创建时间是JDK的8倍,因此对于singleton的对象适合用CGLib,而其他的情况适合用JDK动态代理。注意,CGLib由于采用动态创建子类方式生产代理对象,所以不能对目标类中的final方法进行代理。
》Introduction,引介增强
引介增强可以为目标类创建新的方法和属性,所以其连接点是类级别,通过引介增强我们可以为目标类添加一个接口的实现,通过引介增强我们可以为目标类创建实现某接口的代理。继承DelegatingIntroductionInterceptor即可,覆盖其中的invoke方法。
先定义一个接口类:
package com.springzoo.introduce;
public interface Monitorable {
void setMonitorActive(boolean active);
}
然后自定义Introduction:
package com.springzoo.introduce;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.aop.support.DelegatingIntroductionInterceptor;
public class ControllablePerformaceMonitor extends DelegatingIntroductionInterceptor
implements Monitorable{
private ThreadLocal<Boolean> monitorStatusMap = new ThreadLocal<Boolean>();
public void setMonitorActive(boolean active) {
monitorStatusMap.set(active);
}
public Object invoke(MethodInvocation mi) throws Throwable {
Object obj = null;
if (monitorStatusMap.get() != null && monitorStatusMap.get()) {
PerformanceMonitor.begin(mi.getClass().getName() + "."
+ mi.getMethod().getName());
obj = super.invoke(mi);
PerformanceMonitor.end();
} else {
obj = super.invoke(mi);
}
return obj;
}
}
接下来在spring中配置Introduction:
<?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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id="pmonitor" class="com.springzoo.introduce.ControllablePerformaceMonitor" />
<bean id="forumServiceTarget" class="com.springzoo.introduce.ForumService" />
<bean id="forumService" class="org.springframework.aop.framework.ProxyFactoryBean"
p:interfaces="com.springzoo.introduce.Monitorable"
p:target-ref="forumServiceTarget"
p:interceptorNames="pmonitor"
p:proxyTargetClass="true" />
</beans>
注意:必须指定引介增强所实现的接口,p:inaterfaces,其次由于只能通过为目标类创建子类方式生产引介增强代理,所以必须将proxyTargetClass设为true。还有就是我们没有对ControllerPerformanceMonitor进行线程安全的特殊处理,就必须将singleton属性设为true让ProxyFactoryBean产生prototype的代理,这样会带来严重的性能问题,因为CGLib创建动态代理的性能很低,所以加了个TreadLocal,那么就可以了。
》创建切面Advisor
我们再次给出spring AOP如何定位连接点:
增强Advice提供了连接点方位信息:如织入方法前、后等,而切点进一步描述织入到哪些类的哪些方法上。
spring通过org.springframework.aop.Pointcut接口描述切点,Pointcut由ClassFilter和MethodMatcher构成。
本人博客已搬家,新地址为:http://yidao620c.github.io/
相关推荐
Spring基础:Spring AOP简单使用
Maven坐标:org.springframework:spring-aop:5.0.10.RELEASE; 标签:spring、aop、springframework、jar包、java、API文档、中文版; 使用方法:解压翻译后的API文档,用浏览器打开“index.html”文件,即可纵览...
Spring AOP面向方面编程原理:AOP概念,主要介绍面向对象的概念及原理,及作者的一些理解。
NULL 博文链接:https://foreversky12.iteye.com/blog/2341332
一部分详细分析了Spring的核心:IoC容器和AOP的实现,能帮助读者了解Spring的运行机制;第二部分深入阐述了各种基于IoC容器和AOP的Java EE组件在Spring中的实现原理;第三部分讲述了ACEGI安全框架、DM模块以及Flex...
hualinux spring XML开发系列之 hualinux spring 3.15:Spring AOP 文字版本
Maven坐标:org.springframework:spring-aop:5.2.0.RELEASE; 标签:springframework、spring、aop、中文文档、jar包、java; 使用方法:解压翻译后的API文档,用浏览器打开“index.html”文件,即可纵览文档内容。 ...
SPRING:AOP
spring-aop-1.1.1.jar spring-aop-1.2.6.jar spring-aop-1.2.9.jar spring-aop-2.0.2.jar spring-aop-2.0.6.jar spring-aop-2.0.7.jar spring-aop-2.0.8.jar spring-aop-2.0.jar spring-aop-2.5.1.jar spring-aop-...
Spring源码最难问题:当Spring AOP遇上循环依赖.docx
使用Spring配置文件实现AOP
spring aop spring aop spring aop spring aop spring aop spring aop spring aop spring aop spring aop
Spring如何简捷地在JVM上实现AOP功能? Spring AOP如何实现Aspect编织功能? Spring如何实现各种数据库操作组件的集成? Spring如何在Web环境中集成IoC容器并为Web应用开发提供利器? 我们耳熟能详的MVC...
Maven坐标:org.springframework:spring-aop:5.3.12; 标签:springframework、spring、aop、中英对照文档、jar包、java; 使用方法:解压翻译后的API文档,用浏览器打开“index.html”文件,即可纵览文档内容。 ...
Maven坐标:org.springframework:spring-aop:5.0.8.RELEASE; 标签:springframework、spring、aop、中英对照文档、jar包、java; 使用方法:解压翻译后的API文档,用浏览器打开“index.html”文件,即可纵览文档...
NULL 博文链接:https://foreversky12.iteye.com/blog/2337737
Maven坐标:org.springframework:spring-aop:5.3.10; 标签:springframework、spring、aop、中文文档、jar包、java; 使用方法:解压翻译后的API文档,用浏览器打开“index.html”文件,即可纵览文档内容。 人性化...
package com.gc.aop下为:aop方式ProxyFactoryBean代理 package com.gc.aop下为:aop方式ProxyFactoryBean代理 package com.gc.autoproxy下为:aop方式自动代理 package com.gc.cglib下为:aop方式cglib代理 ...
NULL 博文链接:https://foreversky12.iteye.com/blog/2338186
NULL 博文链接:https://foreversky12.iteye.com/blog/2339065