网站弹窗页面是谁做的,动漫制作专业论文,四合一网站建设,电子平台网站为什么使用AOP#xff0c;一个简单的回答这个问题的方法是显示一个横切关注点的实现而不使用AOP。 考虑一个简单的服务及其实现#xff1a; public interface InventoryService {public Inventory create(Inventory inventory);public Listinventory list();public I… 为什么使用AOP一个简单的回答这个问题的方法是显示一个横切关注点的实现而不使用AOP。 考虑一个简单的服务及其实现 public interface InventoryService {public Inventory create(Inventory inventory);public Listinventory list();public Inventory findByVin(String vin);public Inventory update(Inventory inventory);public boolean delete(Long id);public Inventory compositeUpdateService(String vin, String newMake);
} 及其默认实现 public class DefaultInventoryService implements InventoryService{Overridepublic Inventory create(Inventory inventory) {logger.info(Create Inventory called);inventory.setId(1L);return inventory; }Overridepublic Listinventory list(){return new ArrayListinventory();}Overridepublic Inventory update(Inventory inventory) {return inventory;}Overridepublic boolean delete(Long id) {logger.info(Delete Inventory called);return true;}
.... 这只是一项服务。 假设此项目中还有更多服务。 因此现在如果需要记录每种服务方法所花费的时间则没有AOP的选项将遵循以下内容。 为服务创建一个装饰器 public class InventoryServiceDecorator implements InventoryService{private static Logger logger LoggerFactory.getLogger(InventoryServiceDecorator.class);private InventoryService decorated;Overridepublic Inventory create(Inventory inventory) {logger.info(before method: create);long start System.nanoTime();Inventory inventoryCreated decorated.create(inventory);long end System.nanoTime();logger.info(String.format(%s took %d ns, create, (end-start)) );return inventoryCreated;} 该修饰器实质上将代表修饰的对象拦截该调用记录将方法委派给修饰对象时该方法调用所花费的时间。 想象一下对项目中的所有方法和所有服务执行此操作。 这是AOP解决的方案它为交叉问题服务方法的记录时间要求例如提供了一种模块化的方式–单独包装而不会污染类的核心。 为了结束会话实现装饰器的另一种方法是使用Java的动态代理功能 public class AuditProxy implements java.lang.reflect.InvocationHandler {private static Logger logger LoggerFactory.getLogger(AuditProxy.class);private Object obj;public static Object newInstance(Object obj) {return java.lang.reflect.Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), new AuditProxy(obj));}private AuditProxy(Object obj) {this.obj obj;}public Object invoke(Object proxy, Method m, Object[] args) throws Throwable {Object result;try {logger.info(before method m.getName());long start System.nanoTime();result m.invoke(obj, args);long end System.nanoTime();logger.info(String.format(%s took %d ns, m.getName(), (end-start)) );} catch (InvocationTargetException e) {throw e.getTargetException();} catch (Exception e) {throw new RuntimeException(unexpected invocation exception: e.getMessage());} finally {logger.info(after method m.getName());}return result;}
} 因此现在当创建InventoryService实例时我将通过AuditProxy动态代理创建它 InventoryService inventoryService (InventoryService)AuditProxy.newInstance(new DefaultInventoryService()); 重写的java.lang.reflect.InvocationHandler调用方法将拦截以这种方式创建的对InventoryService的所有调用其中记录了审核方法调用时间的交叉问题。 这样将跨领域关注点模块化到一个位置AuditProxy但是在实例化InventoryService时仍然需要InventoryService的客户端明确地知道它。 现在我将展示如何使用Spring AOP来实现跨领域的关注– Spring提供了多种实现Aspects的方式–基于XML配置基于AspectJ。 在此特定示例中我将使用基于XML配置文件的方式定义方面 Spring AOP在Spring容器的上下文中工作因此在上一个会话中定义的服务实现必须是Spring Bean我使用Service批注定义了它 Service
public class DefaultInventoryService implements InventoryService{
...
} 现在我想记录我的DefaultInventoryService的每个方法调用所花费的时间–我首先将其模块化为“建议” package org.bk.inventory.aspect;import org.aspectj.lang.ProceedingJoinPoint;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;public class AuditAdvice {private static Logger logger LoggerFactory.getLogger(AuditAdvice.class);public void beforeMethod() {logger.info(before method);}public void afterMethod() {logger.info(after method);}public Object aroundMethod(ProceedingJoinPoint joinpoint) {try {long start System.nanoTime();Object result joinpoint.proceed();long end System.nanoTime();logger.info(String.format(%s took %d ns, joinpoint.getSignature(), (end - start)));return result;} catch (Throwable e) {throw new RuntimeException(e);}}} 预计该建议将捕获DefaultInventoryService中的方法所花费的时间。 因此现在将此建议连接到DefaultInventoryService Spring bean bean idauditAspect classorg.bk.inventory.aspect.AuditAdvice /aop:configaop:aspect refauditAspectaop:pointcut idserviceMethods expressionexecution(* org.bk.inventory.service.*.*(..)) /aop:before pointcut-refserviceMethods methodbeforeMethod / aop:around pointcut-refserviceMethods methodaroundMethod /aop:after-returning pointcut-refserviceMethods methodafterMethod / /aop:aspect/aop:config 这是通过首先定义“切入点”即在本例中为服务方法的位置添加横切关注点在本例中为捕获方法执行时间添加的。 在这里我使用切入点表达式进行了定义– execution(* org.bk.inventory.service.*.*(..)) 这实际上是选择org.bk.inventory.service包中所有类型的所有方法。 定义切入点后它使用表达式定义围绕切入点建议要做的事情 aop:around pointcut-refserviceMethods methodaroundMethod / 这基本上就是说围绕任何服务类型的每个方法执行前面定义的AspectAdvice的aroundMethod。 现在如果执行了服务方法我将看到在方法执行期间调用建议以下是如果调用DefaultInventoryServicecreateInventory方法的示例输出 org.bk.inventory.service.InventoryService - Create Inventory called
org.bk.inventory.aspect.AuditAdvice - Inventory org.bk.inventory.service.InventoryService.create(Inventory) took 82492 ns Spring的AOP实现通过在运行时基于定义的切入点为所有目标bean生成动态代理来工作。 定义方面的另一种方法是使用AspectJ注释-Spring本身理解 package org.bk.inventory.aspect;import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;Aspect
public class AuditAspect {private static Logger logger LoggerFactory.getLogger(AuditAspect.class);Pointcut(execution(* org.bk.inventory.service.*.*(..)))public void serviceMethods(){//}Before(serviceMethods())public void beforeMethod() {logger.info(before method);}Around(serviceMethods())public Object aroundMethod(ProceedingJoinPoint joinpoint) {try {long start System.nanoTime();Object result joinpoint.proceed();long end System.nanoTime();logger.info(String.format(%s took %d ns, joinpoint.getSignature(), (end - start)));return result;} catch (Throwable e) {throw new RuntimeException(e);}}After(serviceMethods())public void afterMethod() {logger.info(after method);}
} 类上的Aspect批注将其标识为方面定义。 首先定义切入点 Pointcut(execution(* org.bk.inventory.service.*.*(..)))public void serviceMethods(){} 上面的代码基本上标识了org.bk.inventory.service包中所有类型的所有方法该切入点通过放置注释的方法的名称在本例中为“ serviceMethods”进行标识。 接下来使用BeforeserviceMethods AfterserviceMethods和AroundserviceMethods注释定义建议而需要发生的细节是带有这些注释的方法的主体。 如果此Aspect被定义为bean则Spring AOP可以自然地理解AspectJ批注 bean idauditAspect classorg.bk.inventory.aspect.AuditAspect / Spring将创建一个动态代理以将建议应用于所有标识为切入点符号的目标Bean。 定义方面的另一种方法–这次使用本机AspectJ表示法。 package org.bk.inventory.aspect;import org.bk.inventory.types.Inventory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;public aspect AuditAspect {private static Logger logger LoggerFactory.getLogger(AuditAspect.class);pointcut serviceMethods() : execution(* org.bk.inventory.service.*.*(..));pointcut serviceMethodsWithInventoryAsParam(Inventory inventory) : execution(* org.bk.inventory.service.*.*(Inventory)) args(inventory);before() : serviceMethods() {logger.info(before method);}Object around() : serviceMethods() {long start System.nanoTime();Object result proceed();long end System.nanoTime();logger.info(String.format(%s took %d ns, thisJoinPointStaticPart.getSignature(),(end - start)));return result;}Object around(Inventory inventory) : serviceMethodsWithInventoryAsParam(inventory) {Object result proceed(inventory);logger.info(String.format(WITH PARAM: %s, inventory.toString()));return result;}after() : serviceMethods() {logger.info(after method);}
} 这映射到先前定义的 AspectJ表示法 由于这是专门用于定义方面的DSL因此Java编译器无法理解。 AspectJ提供了一个工具ajc来编译这些本机的Aspectj文件并将其编织到目标切入点中。 Maven提供了一个在编译时无缝调用ajc的插件 plugingroupIdorg.codehaus.mojo/groupIdartifactIdaspectj-maven-plugin/artifactIdversion1.0/versiondependenciesdependencygroupIdorg.aspectj/groupIdartifactIdaspectjrt/artifactIdversion${aspectj.version}/version/dependencydependencygroupIdorg.aspectj/groupIdartifactIdaspectjtools/artifactIdversion${aspectj.version}/version/dependency/dependenciesexecutionsexecutiongoalsgoalcompile/goalgoaltest-compile/goal/goals/execution/executionsconfigurationoutxmltrue/outxmlaspectLibrariesaspectLibrarygroupIdorg.springframework/groupIdartifactIdspring-aspects/artifactId/aspectLibrary/aspectLibrariessource1.6/sourcetarget1.6/target/configuration/plugin 这将是AOP简介的总结并提供一个示例该示例将全面应用前几节中介绍的概念。 用例很简单我将定义一个自定义批注PerfLog我希望对使用此批注进行批注的方法的调用进行计时和记录。 让我首先定义注释 package org.bk.annotations;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;Target({ElementType.TYPE, ElementType.METHOD})
Retention(RetentionPolicy.RUNTIME)
public interface PerfLog {} 现在使用此注释来注释一些服务方法 Service
public class DefaultInventoryService implements InventoryService{private static Logger logger LoggerFactory.getLogger(InventoryService.class);Overridepublic Inventory create(Inventory inventory) {logger.info(Create Inventory called);inventory.setId(1L);return inventory; }Overridepublic ListInventory list() {return new ArrayListInventory();}OverridePerfLogpublic Inventory update(Inventory inventory) {return inventory;}Overridepublic boolean delete(Long id) {logger.info(Delete Inventory called);return true;}OverridePerfLogpublic Inventory findByVin(String vin) {logger.info(find by vin called);return new Inventory(testmake, testmodel,testtrim,testvin );}OverridePerfLogpublic Inventory compositeUpdateService(String vin, String newMake) {logger.info(composite Update Service called);Inventory inventory findByVin(vin);inventory.setMake(newMake);update(inventory);return inventory;}
} 在这里已使用PerfLog批注对DefaultInventoryService的三种方法进行了批注– updatefindByVincompositeUpdateService它们在内部调用方法findByVin和update。 现在对于Aspect它将拦截对所有使用PerfLog注释的方法的调用并记录该方法调用所花费的时间 package org.bk.inventory.aspect;import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;Aspect
public class AuditAspect {private static Logger logger LoggerFactory.getLogger(AuditAspect.class);Pointcut(execution(org.bk.annotations.PerfLog * *.*(..)))public void performanceTargets(){}Around(performanceTargets())public Object logPerformanceStats(ProceedingJoinPoint joinpoint) {try {long start System.nanoTime();Object result joinpoint.proceed();long end System.nanoTime();logger.info(String.format(%s took %d ns, joinpoint.getSignature(), (end - start)));return result;} catch (Throwable e) {throw new RuntimeException(e);}}
} 这里的切入点表达– Pointcut(execution(org.bk.annotations.PerfLog * *.*(..))) 选择所有使用PerfLog注释注释的方法并且方面方法logPerformanceStats记录方法调用所花费的时间。 要对此进行测试 package org.bk.inventory;import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*;import org.bk.inventory.service.InventoryService;
import org.bk.inventory.types.Inventory;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;RunWith(SpringJUnit4ClassRunner.class)
ContextConfiguration(classpath:/testApplicationContextAOP.xml)
public class AuditAspectTest {Autowired InventoryService inventoryService;Testpublic void testInventoryService() {Inventory inventory this.inventoryService.create(new Inventory(testmake, testmodel,testtrim,testvin ));assertThat(inventory.getId(), is(1L));assertThat(this.inventoryService.delete(1L), is(true));assertThat(this.inventoryService.compositeUpdateService(vin,newmake).getMake(),is(newmake));}} 调用此测试时输出如下 2011-09-08 20:54:03,521 org.bk.inventory.service.InventoryService - Create Inventory called
2011-09-08 20:54:03,536 org.bk.inventory.service.InventoryService - Delete Inventory called
2011-09-08 20:54:03,536 org.bk.inventory.service.InventoryService - composite Update Service called
2011-09-08 20:54:03,536 org.bk.inventory.service.InventoryService - find by vin called
2011-09-08 20:54:03,536 org.bk.inventory.aspect.AuditAspect - Inventory org.bk.inventory.service.DefaultInventoryService.findByVin(String) took 64893 ns
2011-09-08 20:54:03,536 org.bk.inventory.aspect.AuditAspect - Inventory org.bk.inventory.service.DefaultInventoryService.update(Inventory) took 1833 ns
2011-09-08 20:54:03,536 org.bk.inventory.aspect.AuditAspect - Inventory org.bk.inventory.service.DefaultInventoryService.compositeUpdateService(String, String) took 1371171 ns 正确调用了findByVinupdate和CompositeUpdateService的建议。 该示例可在以下位置获得git//github.com/bijukunjummen/AOP-Samples.git 参考 all和其他博客中的JCG合作伙伴 Biju Kunjummen 对AOP的简单介绍 。 翻译自: https://www.javacodegeeks.com/2012/06/simple-introduction-to-aop.html