您好!欢迎光临这里是您的网站名称,我们竭诚为您服务!
定制咨询热线0296-29663837
您的位置:主页 > lol下注平台相册 >

lol下注平台相册

联系我们

lol下注平台岗亭有限公司

邮 箱:admin@richage.net
手 机:19914414688
电 话:0296-29663837
地 址:陕西省铜川市惠农区心升大楼48号

设计模式综合运用:lol英雄联盟外围网站

发布时间:2021-10-02 00:46:01人气:
本文摘要:1. 门面+模版方法+责任链+计谋1.1 项目配景在公司的一个实际项目中,需要做一个第三方公司(以下简称XHF)的系统集成事情,把该公司的一些订单数据集成到自己公司平台下,各个订单具有一些共性,可是也有其特有的特征。经由设计,现在我把订单分为POLICY和XHF类型(暂且这么说吧,横竖就是一种订单类型,大家参照着看就OK)。在订单数据集成到公司平台前,需要对订单数据举行一些须要的业务逻辑校验操作,而且每个订单都有自己的校验逻辑(包罗公共的校验逻辑)。

lol英雄联盟外围网站

1. 门面+模版方法+责任链+计谋1.1 项目配景在公司的一个实际项目中,需要做一个第三方公司(以下简称XHF)的系统集成事情,把该公司的一些订单数据集成到自己公司平台下,各个订单具有一些共性,可是也有其特有的特征。经由设计,现在我把订单分为POLICY和XHF类型(暂且这么说吧,横竖就是一种订单类型,大家参照着看就OK)。在订单数据集成到公司平台前,需要对订单数据举行一些须要的业务逻辑校验操作,而且每个订单都有自己的校验逻辑(包罗公共的校验逻辑)。

本节先容的即是整个订单集成系统中的校验逻辑在综合使用设计模式的基础上举行架构设计。1.2 校验逻辑本校验逻辑主要分为四个部门:校验文件名称(RequestValidator.validateFileInfo)校验文件内容中的提要部门(RequestValidator.validateSummary)校验文件内容中的列名称(RequestValidator.validateHeaders)校验文件内容中的明细(RequestValidator.validateDetails)其实上面的RequestValidator的实现逻辑最后都是委托给RequestValidationFacade这个门面类举行相应的校验操作。1.3 实现细节1.3.1 domain先容主要分为RequestFile和RequestDetail两个domain,RequestFile吸收泛型的类型(即RequestFile), 使得其子类能够自动识别相应的RequestDetail的子类。

RequestFile为抽象类,界说了以下抽象方法,由子类实现://由子类实现详细的获取文件明细内容public abstract List<T> getRequestDetails();//由子类实现详细的获取workflow的值public abstract WorkflowEnum getProcessWorkFlow();//由子类实现文件列字段名列表public abstract String[] getDetailHeaders();RequestDetail及其子类就是workflow对应文件的明细内容。1.3.2 WorkflowEnum枚举计谋本例中如下划定:workflow为WorkflowEnum.POLICY对应文件名为:xhf_policy_yyyyMMdd_HHmmss_count.txtworkflow为WorkflowEnum.XHF对应文件名为:xhf_integration_yyyyMMdd_HHmmss_count.txt以上校验逻辑在AbstractRequestValidation类相应的子类中实现(validateFileName方法),其实这个枚举贯串整个校验组件,它就是一个针对每个业务流程界说的一个枚举计谋。1.3.3 涉及到的设计模式实现思路1.3.3.1 门面模式在客户端挪用法式中,接纳门面模式举行统一的入口(门面模式讲求的是脱离详细的业务逻辑代码)。

门面模式封装的效果就是制止高层模块深入子系统内部,同时提供系统的高内聚、低耦合的特性。此案例中,门面类为RequestValidationFacade,然后各个门面方法的参数均为抽象类RequestFile,通过RequestFile->getProcessWorkFlow()决议挪用AbstractRequestValidation中的哪个子类。AbstractRequestValidation类结构方法中界说了如下逻辑:requestValidationHandlerMap.put(this.accessWorkflow(),this.accessBeanName());把子类中Spring自动注入的实体bean缓存到requestValidationHandlerMap中,key即为WorkflowEnum枚举值,value为spring bean name, 然后在门面类中可以通过对应的枚举值取得BeanName,进而获得AbstractRequestValidation相应的子类工具,举行相应的校验操作。

注:这边动态挪用到AbstractRequestValidation相应的子类工具,其实也是隐藏着【计谋模式】的影子。1.3.3.2 模版方法模式在详细的校验逻辑中,用到焦点设计模式即是模版方法模式,AbstractRequestValidation抽象类中界说了以下抽象方法: /** * validate the file details * @param errMsg * @param requestFile * @return */ protected abstract StringBuilder validateFileDetails(StringBuilder errMsg,RequestFile requestFile); /** * validate the file name * @param fileName * @return */ protected abstract String validateFileName(String fileName); /** * return the current xhf_UPDATE_WORKFLOW.UPDATE_WORKFLOW_ID * @return */ protected abstract WorkflowEnum accessWorkflow(); /** * return the current file name's format ,such as: xhf_policy_yyyyMMdd_HHmmss_count.txt * @return */ protected abstract String accessFileNameFormat(); /** * return the subclass's spring bean name * @return */ protected abstract String accessBeanName();以上抽象方法就类似我们常说的钩子函数,由子类实现即可。1.3.3.3 责任链模式在AbstractRequestValidation抽象类中有个抽象方法validateFileDetails,校验的是文件的明细内容中的相应业务规则,此为焦点校验, 较为庞大,而且针对每个业务流程,其校验逻辑相差较大,在此处,使用了责任链模式举行处置惩罚。

Validator为校验器的父接口,包罗两个泛型参数(即:<R extends RequestDetail,F extends RequestFile>),其实现类可以利便的转换需要校验的文件明细。String doValidate(R detail, F file, ValidatorChain chain) throws BusinessValidationException;该方法含有一个ValidatorChain参数,就自然而然的为该校验器形成一个链条提供便利条件。

ValidatorChain为校验器链,含有两个接口方法: String doValidate(T requestDetail, F requestFile) throws BusinessValidationException; ValidatorChain addValidator(Validator validator, WorkflowEnum workflowId);该处有一个addValidator方法,为ValidatorChain工具添加校验器的方法,返回自己。对应于每个业务流程需要哪些校验器就在此实现即可(即AbstractRequestValidation的子类方法validateFileDetails)。

1.3.3.4 计谋模式如果单单从上面的校验器实现上来看,如果需要增加一个校验器,就需要在AbstractRequestValidation的子类方法validateFileDetails中添加,然后举行相应的校验操作。这样就会很是的贫苦,没有做到真正的解耦。此时,计谋模式就发挥到了可以动态选择某种校验计谋的作用(Validator的实现类就是一个详细的校验计谋)。AbstractValidatorHandler抽象类持有FileDetailValidatorChain类的工具,而且实现累Spring的一个接口ApplicationListener(是为了Spring容器启动完成的时候自动把相应的校验器加入到校验器链中)。

焦点就是WorkflowEnum这个计谋枚举的作用,在子类可以动态的取得相应的校验器工具。凭据子类提供需要的校验器所在的包名列表和不需要的校验器列表,动态设置出需要的校验器链表。

焦点实现逻辑如下:private void addValidators() { List<Class<? extends Validator>> validators = getValidators(); validators.forEach((validator) -> { String simpleName = validator.getSimpleName(); String beanName = simpleName.substring(0, 1).toLowerCase() + simpleName.substring(1); LOGGER.info("Added validator:{},spring bean name is:{}",simpleName,beanName); Validator validatorInstance = ApplicationUtil.getApplicationContext().getBean(beanName,validator); fileDetailValidatorChain.addValidator(validatorInstance,getWorkflowId()); });}详细实现可以参考代码即可。该类含有以下几个抽象方法:protected abstract WorkflowEnum getWorkflowId();/** * the package need to be added the validators * @return */protected abstract Set<String> getBasePackages();/** * the classes need to be excluded * @return */protected abstract Set<Class> excludeClasses();2. 门面+模版方法+责任链+计谋+工厂方法上一节在实现计谋模式的实现上,发现了一个毛病:那就是如果在后续业务生长中,需要再次增加一个业务计谋的时候,则需要再次继续AbstractValidatorHandler类(详情请参见上篇文章),这样就会造成一定的类膨胀。今天我使用注解的方式革新成动态计谋模式,这样就只需要关注自己的业务类即可,无需再实现一个类似的Handler类。

2.1 项目配景2.1.1 项目简介在公司的一个业务系统中,有这样的一个需求,就是凭据差别的业务流程,可以凭据差别的组合主键计谋举行动态的数据业务查询操作。在本文中,我假设有这样两种业务,客户信息查询和订单信息查询,对应以下枚举类:/** * 业务流程枚举 * @author landyl * @create 11:18 AM 05/07/2018 */public enum WorkflowEnum { ORDER(2), CUSTOMER(3), ; }每种业务类型都有自己的组合主键查询规则,而且有自己的查询优先级,好比客户信息查询有以下计谋:customerIdrequestIdbirthDate+firstName以上仅是假设性操作,实际业务规则比这庞大的多2.1.2 流程梳理主要业务流程,可以参照以下简朴的业务流程图。2.1.2.1 查询抽象模型2.1.2.2 组合主键查询计谋2.1.2.3 组合主键查询责任链2.2 Java注解简介注解的语法比力简朴,除了@符号的使用之外,它基本与Java固有语法一致。

2.2.1 元注解JDK1.5提供了4种尺度元注解,专门卖力新注解的建立。注解说明@Target表现该注解可以用于什么地方,可能的ElementType参数有:CONSTRUCTOR:结构器的声明FIELD:域声明(包罗enum实例)LOCAL_VARIABLE:局部变量声明METHOD:方法声明PACKAGE:包声明PARAMETER:参数声明TYPE:类、接口(包罗注解类型)或enum声明@Retention表现需要在什么级别生存该注解信息。

可选的RetentionPolicy参数包罗:SOURCE:注解将被编译器抛弃CLASS:注解在class文件中可用,但会被VM抛弃RUNTIME:JVM将在运行期间保留注解,因此可以通过反射机制读取注解的信息@Document将注解包罗在Javadoc中@Inherited允许子类继续父类中的注解2.2.2 自界说注解界说一个注解的方式相当简朴,如下代码所示:@Target({ElementType.METHOD,ElementType.TYPE})@Retention(RetentionPolicy.RUNTIME)@Inherited@Documented//使用@interface关键字界说注解public @interface Description { /* * 注解方法的界说(其实在注解中也可以看做成员变量)有如下的划定: * 1.不能有参数和抛出异常 * 2.方法返回类型只能为八种基本数据类型和字符串,枚举和注解以及这些类型组成的数组 * 3.可以包罗默认值,通过default实现 * 4.如果只有一个方法(成员变量),最好命名为value */ String value(); int count() default 1; //默认值为1}注解的可用的类型包罗以下几种:所有基本类型、String、Class、enum、Annotation、以上类型的数组形式。元素不能有不确定的值,即要么有默认值,要么在使用注解的时候提供元素的值。而且元素不能使用null作为默认值。

注解在只有一个元素且该元素的名称是value的情况下,在使用注解的时候可以省略“value=”,直接写需要的值即可。2.2.3 使用注解如上所示的注解使用如下:/** * @author landyl * @create 2018-01-12:39 PM *///在类上使用界说的Description注解@Description(value="class annotation",count=2)public class Person { private String name; private int age; //在方法上使用界说的Description注解 @Description(value="method annotation",count=3) public String speak() { return "speaking..."; }}使用注解最主要的部门在于对注解的处置惩罚,那么就会涉及到注解处置惩罚器。从原理上讲,注解处置惩罚器就是通过反射机制获取被检查方法上的注解信息,然后凭据注解元素的值举行特定的处置惩罚。/** * @author landyl * @create 2018-01-12:35 PM * 注解剖析类 */public class ParseAnnotation { public static void main(String[] args){ //使用类加载器加载类 try { Class c = Class.forName("com.annatation.Person");//加载使用了界说注解的类 //找到类上的注解 boolean isExist = c.isAnnotationPresent(Description.class); if(isExist){ //拿到注解示例 Description d = (Description)c.getAnnotation(Description.class); System.out.println(d.value()); } //找到方法上的注解 Method[] ms = c.getMethods(); for(Method m : ms){ boolean isMExist = m.isAnnotationPresent(Description.class); if(isMExist){ Description d = m.getAnnotation(Description.class); System.out.println(d.value()); } } //另外一种注解方式 for(Method m:ms){ Annotation[] as = m.getAnnotations(); for(Annotation a:as){ if(a instanceof Description){ Description d = (Description)a; System.out.println(d.value()); } } } } catch (ClassNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } }}2.3 计谋模式升级版2.3.1 计谋模式实现方式使用工厂举行简朴的封装使用注解动态设置计谋使用模版方法模式设置计谋(参见1. 门面+模版方法+责任链+计谋)使用工厂+注解方式动态设置计谋(使用Spring加载)其中第1、2点请参见org.landy.strategy 包下的demo事例即可,而第4点的方式其实就是联合第1、2、3点的优点举行整合的方式。

lol英雄联盟外围网站

2.3.2 注解方式优点使用注解方式可以极大的淘汰使用模版方法模式带来的扩展时需要继续模版类的毛病,工厂+注解的方式可以无需体贴其他业务类的实现,而且淘汰了类膨胀的风险。2.3.3 组合主键查询计谋本文以组合主键查询计谋这一计谋举行说明,计谋注解如下:/** * 组合主键查询计谋(凭据差别业务流程区分组合主键查询计谋,而且每个业务流程都有自己的优先级计谋) * @author landyl * @create 2:22 PM 09/29/2018 */@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)@Documentedpublic @interface KeyIdentificationStrategy { /** * 主键计谋优先级 * @return */ int priority() default 0; /** * 业务流程类型(如:订单信息,会员信息等业务流程) * @return */ WorkflowEnum workflowId(); /** * the spring bean name * @return */ String beanName();}2.3.4 计谋工厂既然界说了组合主键查询计谋注解,那一定需要一个注解处置惩罚器举行剖析注解的操作,本文以工厂的方式举行。主要逻辑如下:扫描指定包下的Java类,找出相应接口(即KeyIdentification)下的所有Class工具。private List<Class<? extends KeyIdentification>> getIdentifications() { Set<String> packageNames = this.getBasePackages(); List<Class<? extends KeyIdentification>> identifications = new ArrayList<>(); if(packageNames != null) { packageNames.forEach((packageName) -> identifications.addAll(getIdentifications(packageName))); } return identifications; }剖析注解KeyIdentificationStrategy,界说一个排序工具(KeyIdentificationComparator),指定优先级。

private class KeyIdentificationComparator implements Comparator { @Override public int compare(Object objClass1, Object objClass2) { if(objClass1 != null && objClass2 != null) { Optional<KeyIdentificationStrategy> strategyOptional1 = getPrimaryKeyIdentificationStrategy((Class)objClass1); Optional<KeyIdentificationStrategy> strategyOptional2 = getPrimaryKeyIdentificationStrategy((Class)objClass2); KeyIdentificationStrategy ip1 = strategyOptional1.get(); KeyIdentificationStrategy ip2 = strategyOptional2.get(); Integer priority1 = ip1.priority(); Integer priority2 = ip2.priority(); WorkflowEnum workflow1 = ip1.workflowId(); WorkflowEnum workflow2 = ip2.workflowId(); //先按业务类型排序 int result = workflow1.getValue() - workflow2.getValue(); //再按优先级排序 if(result == 0) return priority1.compareTo(priority2); return result; } return 0; } }凭据注解,把相应业务类型的组合主键查询计谋工具放入容器中(即DefaultKeyIdentificationChain)。KeyIdentificationStrategy strategy = strategyOptional.get(); String beanName = strategy.beanName(); //业务流程类型 WorkflowEnum workflowId = strategy.workflowId(); KeyIdentificationStrategy priority = getPrimaryKeyIdentificationStrategy(v).get(); LOGGER.info("To add identification:{},spring bean name is:{},the identify priority is:{},workflowId:{}",simpleName,beanName,priority.priority(),workflowId.name()); KeyIdentification instance = ApplicationUtil.getApplicationContext().getBean(beanName,v); defaultKeyIdentificationChain.addIdentification(instance,workflowId);后续,在各自对应的业务查询组件工具中即可使用该工厂工具挪用如下方法,即可举行相应的查询操作。

public IdentificationResultType identify(IdentifyCriterion identifyCriterion,WorkflowEnum workflowId) { defaultKeyIdentificationChain.doClearIdentificationIndex(workflowId); return defaultKeyIdentificationChain.doIdentify(identifyCriterion,workflowId); }3. 动态署理+Spring AOPAOP设计模式通常运用在日志,校验等业务场景,本文将简朴先容基于Spring的AOP署理模式的运用。3.1 Spring AOP3.1.1 Spring AOP原理AOP实现的关键在于AOP框架自动建立的AOP署理,AOP署理主要分为静态署理和动态署理,静态署理的代表为AspectJ;而动态署理则以Spring AOP为代表。本文以Spring AOP的实现举行分析和先容。

Spring AOP使用的动态署理,所谓的动态署理就是说AOP框架不会去修改字节码,而是在内存中暂时为方法生成一个AOP工具,这个AOP工具包罗了目的工具的全部方法,而且在特定的切点做了增强处置惩罚,并回调原工具的方法。Spring AOP中的动态署理主要有两种方式,JDK动态署理和CGLIB动态署理。JDK动态署理通过反射来吸收被署理的类,而且要求被署理的类必须实现一个接口。JDK动态署理的焦点是InvocationHandler接口和Proxy类。

lol下注平台

如果目的类没有实现接口,那么Spring AOP会选择使用CGLIB来动态署理目的类。CGLIB(Code Generation Library),是一个代码生成的类库,可以在运行时动态的生成某个类的子类,注意,CGLIB是通过继续的方式做的动态署理,因此如果某个类被标志为final,那么它是无法使用CGLIB做动态署理的。注意:以上片段引用自文章Spring AOP的实现原理,如有冒犯,请联系笔者删除之,谢谢!Spring AOP判断是JDK署理还是CGLib署理的源码如下(来自org.springframework.aop.framework.DefaultAopProxyFactory):@Overridepublic AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException { if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) { Class<?> targetClass = config.getTargetClass(); if (targetClass == null) { throw new AopConfigException("TargetSource cannot determine target class: " + "Either an interface or a target is required for proxy creation."); } if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) { return new JdkDynamicAopProxy(config); } return new ObjenesisCglibAopProxy(config); } else { return new JdkDynamicAopProxy(config); }}由代码发现,如果设置proxyTargetClass = true了而且目的类非接口的情况,则会使用CGLib署理,否则使用JDK署理。

3.1.2 Spring AOP设置Spring AOP的设置有两种方式,XML和注解方式。3.1.2.1 XML设置首先需要引入AOP相关的DTD设置,如下:<beans xmlns="http://www.springframework.org/schema/beans" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsdhttp://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd">然后需要引入AOP自动署理设置:<!-- 自动扫描(自动注入) --><context:component-scan base-package="org.landy" /><!-- 指定proxy-target-class为true可强制使用cglib --><aop:aspectj-autoproxy proxy-target-class="true"></aop:aspectj-autoproxy>3.1.2.2 注解设置Java设置类如下:/** * 相当于Spring.xml设置文件的作用 * @author landyl * @create 2:44 PM 09/30/2018 */@Configuration//@EnableLoadTimeWeaving(aspectjWeaving = EnableLoadTimeWeaving.AspectJWeaving.ENABLED)@EnableAspectJAutoProxy(proxyTargetClass = true)//@EnableAspectJAutoProxy@ComponentScan(basePackages = "org.landy")public class ApplicationConfigure { @Bean public ApplicationUtil getApplicationUtil() { return new ApplicationUtil(); }}3.1.2.3 依赖包需要使用Spring AOP需要引入以下Jar包:<properties> <spring.version>5.0.8.RELEASE</spring.version> <aspectj.version>1.8.7</aspectj.version></properties><!-- aspectjrt.jar包主要是提供运行时的一些注解,静态方法等等工具,通常我们要使用aspectJ的时候都要使用这个包。

--><dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjrt</artifactId> <version>${aspectj.version}</version></dependency><!-- aspectjweaverjar包主要是提供了一个java agent用于在类加载期间织入切面(Load time weaving)。而且提供了对切面语法的相关处置惩罚等基础方法,供ajc使用或者供第三方开发使用。这个包一般我们不需要显式引用,除非需要使用LTW。

--><dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>${aspectj.version}</version></dependency><dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> <version>${spring.version}</version> <scope>compile</scope></dependency>3.1.2.4 设置单元测试以上两种设置方式,单元测试需要注意一个地方就是引入设置的方式纷歧样,区别如下:XML方式@ContextConfiguration(locations = { "classpath:spring.xml" }) //加载设置文件 @RunWith(SpringJUnit4ClassRunner.class) //使用junit4举行测试 public class SpringTestBase extends AbstractJUnit4SpringContextTests { }注解方式@ContextConfiguration(classes = ApplicationConfigure.class)@RunWith(SpringJUnit4ClassRunner.class) //使用junit4举行测试public class SpringTestBase extends AbstractJUnit4SpringContextTests {}设置好了以后,以后所有的测试类都继续SpringTestBase类即可。3.2 项目演示3.2.1 逻辑梳理本文将以校验某个业务逻辑为例说明Spring AOP署理模式的运用。根据老例,还是以客户信息更新校验为例,假设有个校验类如下:/** * @author landyl * @create 2:22 PM 09/30/2018 */@Componentpublic class CustomerUpdateRule implements UpdateRule { //使用自界说注解,举行AOP切面编程,举行其他业务逻辑的校验操作 @StatusCheck public CheckResult check(String updateStatus, String currentStatus) { System.out.println("CustomerUpdateRule:在此另有其他业务校验逻辑。"+updateStatus + "____" + currentStatus); return new CheckResult(); }}此时我们需要界说一个注解StatusCheck类,如下:/** * @author landyl * @create 2:37 PM 09/23/2018 */@Target(ElementType.METHOD)@Retention(RetentionPolicy.RUNTIME)public @interface StatusCheck {}此注解仅为一个标志注解。

最为主要的就是界说一个更新校验的切面类,界说好切入点。@Component@Aspectpublic class StatusCheckAspect { private static final int VALID_UPDATE = Constants.UPDATE_STATUS_VALID_UPDATE; private static final Logger LOGGER = LoggerFactory.getLogger(StatusCheckAspect.class); //界说切入点:界说一个方法,用于声明切面表达式,一般地,该方法中不再需要添加其他的代码 @Pointcut("execution(* org.landy.business.rules..*(..)) && @annotation(org.landy.business.rules.annotation.StatusCheck)") public void declareJoinPointExpression() {} /** * 前置通知 * @param joinPoint */ @Before("declareJoinPointExpression()") public void beforeCheck(JoinPoint joinPoint) { System.out.println("before statusCheck method start ..."); System.out.println(joinPoint.getSignature()); //获得自界说注解的参数 String methodName = joinPoint.getSignature().getName(); List<Object> args = Arrays.asList(joinPoint.getArgs()); System.out.println("The method " + methodName + " begins with " + args); System.out.println("before statusCheck method end ..."); }} 详细代码请参见github。3.2.2 逻辑测试3.2.2.1 JDK动态署理JDK动态署理必须实现一个接口,本文实现UpdateRule为例,public interface UpdateRule { CheckResult check(String updateStatus, String currentStatus);}而且AOP需要做如下设置:XML方式:<!-- 指定proxy-target-class为true可强制使用cglib --><aop:aspectj-autoproxy proxy-target-class="false"></aop:aspectj-autoproxy>注解方式:@Configuration@EnableAspectJAutoProxy@ComponentScan(basePackages = "org.landy")public class ApplicationConfigure {}在测试类中,必须使用接口方式注入:/** * @author landyl * @create 2:32 PM 09/30/2018 */public class CustomerUpdateRuleTest extends SpringTestBase { @Autowired private UpdateRule customerUpdateRule; //JDK署理方式必须以接口方式注入 @Test public void customerCheckTest() { System.out.println("proxy class:" + customerUpdateRule.getClass()); CheckResult checkResult = customerUpdateRule.check("2","currentStatus"); AssertUtil.assertTrue(checkResult.getCheckResult() == 0,"与预期效果纷歧致"); }}测试效果如下:proxy class:class com.sun.proxy.$Proxy342018-10-05 14:18:17.515 [main] INFO org.landy.business.rules.aop.StatusCheckAspect - Status check around method start ....before statusCheck method start ...CheckResult org.landy.business.rules.stategy.UpdateRule.check(String,String)The method check begins with [2, currentStatus]before statusCheck method end ...CustomerUpdateRule:在此另有其他业务校验逻辑。

2____currentStatus2018-10-05 14:18:17.526 [main] INFO org.landy.business.rules.aop.StatusCheckAspect - execute the target method,the return result_msg:null2018-10-05 14:18:17.526 [main] INFO org.landy.business.rules.aop.StatusCheckAspect - Status check around method end ....以上效果说明它生成的署理类为$Proxy34,说明是JDK署理。3.2.2.2 CGLib动态署理使用CGlib可以不用接口(经测试,用了接口似乎也没问题)。在测试类中,必须使用实现类方式注入: @Autowired private CustomerUpdateRule customerUpdateRule;而且AOP需要做如下设置:XML方式:<!-- 指定proxy-target-class为true可强制使用cglib --><aop:aspectj-autoproxy proxy-target-class="true"></aop:aspectj-autoproxy>注解方式:@Configuration@EnableAspectJAutoProxy(proxyTargetClass = true)@ComponentScan(basePackages = "org.landy")public class ApplicationConfigure {}不外发现我并未设置proxyTargetClass = true也可以正常运行,有点奇怪。(按理说,默认是为false)运行效果生成的署理类为:proxy class:class org.landy.business.rules.stategy.CustomerUpdateRule$$EnhancerBySpringCGLIB$$d1075aca说明是CGLib署理。

经由进一步测试,发现如果我实现接口UpdateRule,可是注入方式使用类注入方式:@Autowiredprivate CustomerUpdateRule customerUpdateRule;而且把proxyTargetClass设置为false,则运行就报如下错误:严重: Caught exception while allowing TestExecutionListener [org.springframework.test.context.support.DependencyInjectionTestExecutionListener@6a024a67] to prepare test instance [org.landy.business.rules.CustomerUpdateRuleTest@7fcf2fc1]org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'org.landy.business.rules.CustomerUpdateRuleTest': Unsatisfied dependency expressed through field 'customerUpdateRule'; nested exception is org.springframework.beans.factory.BeanNotOfRequiredTypeException: Bean named 'customerUpdateRule' is expected to be of type 'org.landy.business.rules.stategy.CustomerUpdateRule' but was actually of type 'com.sun.proxy.$Proxy34'at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:586)以上说明晰一个问题,使用接口实现的方式则会被默认为JDK署理方式,如果需要使用CGLib署理,需要把proxyTargetClass设置为true。3.2.2.3 综合测试为了再次验证Spring AOP如何选择JDK署理还是CGLib署理,在此举行一个综合测试。测试前提:实现UpdateRule接口测试类使用接口方式注入@Autowired private UpdateRule customerUpdateRule; //JDK署理方式必须以接口方式注入测试:设置proxyTargetClass为true,运行效果如下:customerCheckTestproxy class:class org.landy.business.rules.stategy.CustomerUpdateRule$$EnhancerBySpringCGLIB$$f5a349532018-10-05 15:28:42.820 [main] INFO org.landy.business.rules.aop.StatusCheckAspect - Status check around method start ....2018-10-05 15:28:42.823 [main] INFO org.landy.business.rules.aop.StatusCheckAspect - Status check dynamic AOP,paramValues:2AOP实际校验逻辑。

2----currentStatusbefore statusCheck method start ...target class:org.landy.business.rules.stategy.CustomerUpdateRule@7164ca4c说明为CGLIb署理。设置proxyTargetClass为false,运行效果如下:proxy class:class com.sun.proxy.$Proxy342018-10-05 15:20:59.894 [main] INFO org.landy.business.rules.aop.StatusCheckAspect - Status check around method start ....before statusCheck method start ...target class:org.landy.business.rules.stategy.CustomerUpdateRule@ae3540e说明为JDK署理。

以上测试说明,指定proxy-target-class为true可强制使用cglib。3.2.3 常见问题如果使用JDK动态署理,未使用接口方式注入(或者使用接口实现,并未设置proxyTargetClass为true),则会泛起以下异常信息:严重: Caught exception while allowing TestExecutionListener [org.springframework.test.context.support.DependencyInjectionTestExecutionListener@6a024a67] to prepare test instance [org.landy.business.rules.CustomerUpdateRuleTest@7fcf2fc1]org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'org.landy.business.rules.CustomerUpdateRuleTest': Unsatisfied dependency expressed through field 'customerUpdateRule'; nested exception is org.springframework.beans.factory.BeanNotOfRequiredTypeException: Bean named 'customerUpdateRule' is expected to be of type 'org.landy.business.rules.stategy.CustomerUpdateRule' but was actually of type 'com.sun.proxy.$Proxy34'与生成的署理类型纷歧致,有兴趣的同学可以Debug DefaultAopProxyFactory类中的createAopProxy方法即可自动两种动态署理的区别。


本文关键词:lol英雄联盟外围网站,设计模式,综合,运用,lol,英雄,联盟,外围,网站

本文来源:lol下注平台-www.richage.net

0296-29663837