内容简介:回眸一笑百媚生,六宫粉黛无颜色。在前四篇,我们已经实现了使用
回眸一笑百媚生,六宫粉黛无颜色。
概述
在前四篇,我们已经实现了使用 Cglib
实现了 aop
动态代理。但是在 spring
中如果代理对象实现了接口,则默认使用 jdk
动态代理,也可以通过配置强制使用 cglib
代理。本篇,我们使用 jdk
动态代理来完善 aop
准备工作
INioCoderService
新增接口类,因为使用 jdk
动态代理,代理对象必须实现接口。
package com.niocoder.service.v6; /** * 测试 JDK 动态代理 */ public interface INioCoderService { void placeOrder(); }
NioCoderService
实现 INioCoderService
接口。
@Component(value = "nioCoder") public class NioCoderService implements INioCoderService { public NioCoderService() { } public void placeOrder() { System.out.println("place order"); MessageTracker.addMsg("place order"); } public void placeOrderV2() { System.out.println("no interception"); } }
bean-v6.XML
设置 Pointcut
为 v6
包下面的 placeOrder
方法。
<?xml version="1.0" encoding="UTF-8"?> <!-- 增加namespace--> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop"> <!-- 扫描哪个包下面的文件 --> <context:component-scan base-package="com.niocoder.service.v6"> </context:component-scan> <!-- 模拟 TransactionManager--> <bean id="tx" class="com.niocoder.tx.TransactionManager"/> <!-- aop 配置--> <aop:config> <!-- aop 核心配置 依赖tx--> <aop:aspect ref="tx"> <!-- 切入点配置 包下面的placeOrder 方法--> <aop:pointcut id="placeOrder" expression="execution(* com.niocoder.service.v6.*.placeOrder(..))"/> <!-- 通知配置,--> <aop:before pointcut-ref="placeOrder" method="start"/> <aop:after-returning pointcut-ref="placeOrder" method="commit"/> <aop:after-throwing pointcut-ref="placeOrder" method="rollback"/> </aop:aspect> </aop:config> </beans>
创建jdk代理工厂
根据类图aop 动态获取代理实例 创建 JdkAopProxyFactory
代理工厂。
JdkAopProxyFactory
package com.niocoder.aop.framework; import com.niocoder.aop.Advice; import com.niocoder.util.Assert; import com.niocoder.util.ClassUtils; import lombok.extern.java.Log; import org.aopalliance.intercept.MethodInterceptor; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.util.ArrayList; import java.util.List; /** * @author zhenglongfei */ @Log public class JdkAopProxyFactory implements AopProxyFactory, InvocationHandler { private final AopConfig config; public JdkAopProxyFactory(AopConfig config) throws AopConfigException { Assert.notNull(config, "AdvisedSupport must not be null"); if (config.getAdvices().size() == 0) { throw new AopConfigException("No advices specified"); } this.config = config; } @Override public Object getProxy() { return getProxy(ClassUtils.getDefaultClassLoader()); } @Override public Object getProxy(ClassLoader classLoader) { log.info("Creating JDK dynamic proxy: target source is " + this.config.getTargetObject()); Class<?>[] proxiedInterfaces = config.getProxiedInterfaces(); return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this); } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object target = this.config.getTargetObject(); Object retVal; List<Advice> chain = this.config.getAdvices(method); if (chain.isEmpty()) { retVal = method.invoke(target, args); } else { List<MethodInterceptor> interceptors = new ArrayList<MethodInterceptor>(); interceptors.addAll(chain); // We need to create a method invocation... retVal = new ReflectiveMethodInvocation(target, method, args, interceptors).proceed(); } return retVal; } }
AspectJAutoProxyCreator
在 AspectJAutoProxyCreator
的 createProxy
方法中添加 JDK
代理支持。
public class AspectJAutoProxyCreator implements BeanPostProcessor { ...... protected Object createProxy(List<Advice> advices, Object bean) { AopConfigSupport config = new AopConfigSupport(); for (Advice advice : advices) { config.addAdvice(advice); } Set<Class> targetInterfaces = ClassUtils.getAllInterfacesForClassAsSet(bean.getClass()); for (Class<?> targetInterface : targetInterfaces) { config.addInterface(targetInterface); } config.setTargetObject(bean); AopProxyFactory proxyFactory = null; if (config.getProxiedInterfaces().length == 0) { proxyFactory = new CglibProxyFactory(config); } else { // JDK 代理 proxyFactory = new JdkAopProxyFactory(config); } return proxyFactory.getProxy(); } ...... }
ApplicationContextTest
测试 jdk
动态代理。
public class ApplicationContextTest { @Before public void setUp() { MessageTracker.clearMsgs(); } @Test public void testGetBeanProperty() { ApplicationContext ctx = new ClassPathXmlApplicationContext("bean-v6.xml"); INioCoderService nioCoderService = (INioCoderService) ctx.getBean("nioCoder"); nioCoderService.placeOrder(); List<String> msgs = MessageTracker.getMsgs(); Assert.assertEquals(3, msgs.size()); Assert.assertEquals("start tx", msgs.get(0)); Assert.assertEquals("place order", msgs.get(1)); Assert.assertEquals("commit tx", msgs.get(2)); } }
输出:
start tx place order commit tx
代码下载
代码下载
参考资料
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
现代操作系统(第3版)
Andrew S. Tanenbaum / 陈向群、马洪兵 / 机械工业出版社 / 2009-7 / 75.00元
本书是操作系统领域的经典之作,与第2版相比,增加了关于Linux、Windows Vista和Symbian操作系统的详细介绍。书中集中讨论了操作系统的基本原理,包括进程、线程、存储管理、文件系统、输入/输出、死锁等,同时还包含了有关计算机安全、多媒体操作系统、掌上计算机操作系统、微内核、多核处理机上的虚拟机以及操作系统设计等方面的内容。此外,还在第2版的基础上对部分习题进行了增删,更有助于读者学......一起来看看 《现代操作系统(第3版)》 这本书的介绍吧!