做静态页面的网站,搜索百度网址版搜索,asp网站检查,免费手机网站制作方法1. 代理模式 二十三种设计模式中的一种#xff0c;属于结构型模式。它的作用就是通过提供一个代理类#xff0c;让我们在调用目标方法的时候#xff0c;不再是直接对目标方法进行调用#xff0c;而是通过代理类**间接**调用。让不属于目标方法核心逻辑的代码从目标方法中剥…1. 代理模式 二十三种设计模式中的一种属于结构型模式。它的作用就是通过提供一个代理类让我们在调用目标方法的时候不再是直接对目标方法进行调用而是通过代理类**间接**调用。让不属于目标方法核心逻辑的代码从目标方法中剥离出来——**解耦**。调用目标方法时先调用代理对象的方法减少对目标方法的调用和打扰同时让附加功能能够集中在一起也有利于统一维护 动态代理 * 动态代理分为JDK动态代理和cglib动态代理 * 当目标类有接口的情况使用JDK动态代理和cglib动态代理没有接口时只能使用cglib动态代理 * JDK动态代理动态生成的代理类会在com.sun.proxy包下类名为$proxy1和目标类实现相同的接口 * cglib动态代理动态生成的代理类会和目标在在相同的包下会继承目标类 * 动态代理InvocationHandlerJDK原生的实现方式需要被代理的目标类必须实现接口。因为这个技术要求**代理对象和目标对象实现同样的接口**兄弟两个拜把子模式。 * cglib通过**继承被代理的目标类**认干爹模式实现代理所以不需要目标类实现接口。 * AspectJ是AOP思想的一种实现。本质上是静态代理**将代理逻辑“织入”被代理的目标类编译得到的字节码文件**所以最终效果是动态的。weaver就是织入器。Spring只是借用了AspectJ中的注解。 2. AOP概述 AOPAspect Oriented Programming是一种设计思想是软件设计领域中的面向切面编程它是面向对象编程的一种补充和完善它以通过预编译方式和运行期动态代理方式实现在不修改源代码的情况下给程序动态统一添加额外功能的一种技术。利用AOP可以对业务逻辑的各个部分进行隔离从而使得业务逻辑各部分之间的耦合度降低提高程序的可重用性同时提高了开发的效率 相关术语 横切关注点 这个概念不是语法层面的而是根据附加功能的逻辑上的需要有十个附加功能就有十个横切关注点。 通知功能切入后要新添什么新的功能 切面将通知功能封装成类 目标被代理对象 代理调用目标对象的功能并且有自己的业务功能即在目标基础上新加业务功能但不需要修改目标对象的代码 切入点通俗点来讲就是设置相对应的规则满足该规则的方法就是要被代理的方法也可理解为切入点在哪个点函数切入新增功能 作用 * 简化代码把方法中固定位置的重复的代码**抽取**出来让被抽取的方法更专注于自己的核心功能提高内聚性。 * 代码增强把特定的功能封装到切面类中看哪里有需要就往上套被**套用**了切面逻辑的方法就被切面给增强了。 3. 基于注解的AOP
业务场景模拟
原业务代码只能完成计算功能在次基础上新增日志功能
public interface Calculator {int add(int i, int j);int sub(int i, int j);int mul(int i, int j);int div(int i, int j);
}
Component
public class CalculatorImp implements Calculator{Overridepublic int add(int i, int j) {int result i j;System.out.println(方法内部 result result);return result;}Overridepublic int sub(int i, int j) {int result i - j;System.out.println(方法内部 result result);return result;}Overridepublic int mul(int i, int j) {int result i * j;System.out.println(方法内部 result result);return result;}Overridepublic int div(int i, int j) {int result i / j;System.out.println(方法内部 result result);return result;}
} 语法及细节 /**** 切入点表达式execution(权限修饰符. 返回值类型. 全类名. 方法名(形参类型))* * 可以代表任意修饰符任意返回值类型任意方法任意包任意类* .. 代表任意方法的形参列表为任意类型* 如: execution(* com.itgyl.annoAop.CalculatorImp.*(..))* 即修饰符和返回类型任意的com.itgyl.annoAop这个包下的CalculatorImp这个类的所有方法形参列表任意的方法 调用时会执行这个前置方法* execution(public int com.itgyl.annoAop.CalculatorImp.add(int int))* 即修饰符为public 返回值类型为int 的com.itgyl.annoAop包下 的 CalculatorImp类 执行add(形参为两个int类型)这个方法时会先执行这个前置方法*/ /**** 通知* 前置 Before* 前置通知执行时机为代理方法执行前* 返回 AfterReturning* 返回通知执行时机为代理方法调用结束正常返回结果后* 异常 AfterThrowing* 异常通知执行时机为调用方法出现异常时执行* 后置 After* 后置通知执行时机为代理方法调用完全结束后* 环绕 Around* 环绕通知可以出现在代理方法前后中或异常等时机都能进行触发* 需手动调用proceed方法才会执行代理方法并且代理方法的结果必须返回不然报错*/Aspect //该注解声明该类是一个切面类
Component //通过该注解可以完成自动注入放入IoC容器中
public class LogAspect {/**** JoinPoint切入点参数该参数可以获取执行方法的名称方法参数等等*///Before(execution(public int com.itgyl.annoAop.*.*(..)))Before(value execution(public int com.itgyl.annoAop.CalculatorImp.add(..)))public void beforeMethod(JoinPoint joinPoint) {String name joinPoint.getSignature().getName();Object[] args joinPoint.getArgs();System.out.println(前置通知执行啦 执行方法为 name 参数为 Arrays.toString(args));}After(execution(* com.itgyl.annoAop.CalculatorImp.*(..)))public void afterMethod(JoinPoint joinPoint) {String name joinPoint.getSignature().getName();Object[] args joinPoint.getArgs();System.out.println(后置通知执行啦 执行方法为 name 参数为 Arrays.toString(args));}/**** returning获取方法返回结果返回结果的变量名随便取但是下面执行的方法里的形参名要和该结果名保持一致* param joinPoint 可通过该形参获取代理方法的内容* param result 可通过该形参获取代理方法最终返回的结果*/AfterReturning(value execution(* com.itgyl.annoAop.CalculatorImp.*(..)), returning result)public void afterReturningMethod(JoinPoint joinPoint, Object result) {String name joinPoint.getSignature().getName();Object[] args joinPoint.getArgs();System.out.println(返回通知执行啦 执行方法为 name 参数为 Arrays.toString(args) 返回结果为 result);}/**** 参数Throwable为异常信息若添加该形参也需要在切入点表达式中绑定相应的形参* param joinPoint 通过该形参可以获取代理方法的参数* param e 通过该形参可以获取出现异常的信息*/AfterThrowing(value execution(* com.itgyl.annoAop.CalculatorImp.*(..)), throwing e)public void afterThrowingMethod(JoinPoint joinPoint, Throwable e) {String name joinPoint.getSignature().getName();Object[] args joinPoint.getArgs();System.out.println(异常通知执行啦 出现异常方法名为 name 参数为 Arrays.toString(args) 异常信息为 e);}Around(value pointCut())public Object aroundMethod(ProceedingJoinPoint joinPoint) throws Throwable {String name joinPoint.getSignature().getName();String args Arrays.toString(joinPoint.getArgs());Object result null;try {System.out.println(环绕通知执行调用代理方法前 方法名为 name 参数为 args);//调用代理方法后必须返回结果result joinPoint.proceed();System.out.println(环绕通知执行调用代理方法后 方法名为 name 参数为 args);} catch (Exception e) {System.out.println(环绕通知执行调用代理方法出现异常);} finally {System.out.println(环绕通知执行结束);}return result;}/***重用切入点表达式如果要代理方法值都一样时可以将切入点表达式封装起来后面可以直接调用该方法不需要每次重复写executing函数* 细节如果当前切面类重用该切入点表达式可以直接调用该函数使用* 当其他类调用时需要全类名该函数名才能调用* 如Around(value pointCut())* Around(value com.itgyl.annoAop.LogAspect.pointCut())*/Pointcut(value execution(* com.itgyl.annoAop.CalculatorImp.*(..)))public void pointCut() {}
}测试类
public class TestAnnoAop {Testpublic void testAdd() {ApplicationContext context new ClassPathXmlApplicationContext(bean.xml);System.out.println(context);Calculator c context.getBean(Calculator.class);System.out.println(c);c.add(2,3);}
}
执行结果 切入点优先级 4. 基于XML的AOP
?xml version1.0 encodingUTF-8?
beans xmlnshttp://www.springframework.org/schema/beansxmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexmlns:contexthttp://www.springframework.org/schema/contextxmlns:aophttp://www.springframework.org/schema/aopxsi:schemaLocationhttp://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsdcontext:component-scan base-packagecom.itgyl.xmlAop/context:component-scanaop:config!--配置切面类--aop:aspect reflogAspect!--配置切入点--aop:pointcut idpointCut expressionexecution(* com.itgyl.xmlAop.CalculatorImp.*(..))/!--配置通知--!--配置前置通知执行代理方法前要执行的方法为beforeMethod切入点为上面配置的切入点表达式--aop:before methodbeforeMethod pointcut-refpointCut/aop:before!--配置后置通知--aop:after methodafterMethod pointcut-refpointCut/aop:after!--配置异常通知需绑定抛出异常的值该值和函数中的异常形参名需保持一致--aop:after-throwing methodafterThrowingMethod pointcut-refpointCut throwinge/aop:after-throwingaop:after-returning methodafterReturningMethod pointcut-refpointCut returningresult/aop:after-returning!--配置环绕通知--aop:around methodaroundMethod pointcut-refpointCut/aop:around/aop:aspect/aop:config/beans