日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

spring @order控制对象的顺序

發(fā)布時間:2025/3/19 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 spring @order控制对象的顺序 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

一、@order控制 @component,@configutation內(nèi)的@BEAN的加載和實例化順序。主要是在

ConfigurationClassPostProcessor.processConfigBeanDefinitions中加載調(diào)整順序, // Return immediately if no @Configuration classes were foundif (configCandidates.isEmpty()) {return;}// Sort by previously determined @Order value, if applicableconfigCandidates.sort((bd1, bd2) -> {int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());return Integer.compare(i1, i2);});// Detect any custom bean name generation strategy supplied through the enclosing application contextSingletonBeanRegistry sbr = null;if (registry instanceof SingletonBeanRegistry) {sbr = (SingletonBeanRegistry) registry;if (!this.localBeanNameGeneratorSet) {BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton(AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR);if (generator != null) {this.componentScanBeanNameGenerator = generator;this.importBeanNameGenerator = generator;}}}

二、@order控制 @aspect的切面執(zhí)行順序,數(shù)值越小優(yōu)先級越高。

spring aop就是一個同心圓,要執(zhí)行的方法為圓心,最外層的order最小。從最外層按照AOP1、AOP2的順序依次執(zhí)行doAround方法,doBefore方法。然后執(zhí)行method方法,最后按照AOP2、AOP1的順序依次執(zhí)行doAfter、doAfterReturn方法。也就是說對多個AOP來說,先before的,一定后after。

如果我們要在同一個方法事務提交后執(zhí)行自己的AOP,那么把事務的AOP order設置為2,自己的AOP order設置為1,然后在doAfterReturn里邊處理自己的業(yè)務邏輯。

示例代碼:

package com.tpw.newday.aspect;import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.json.JSONUtil; import com.tpw.newday.annation.CacheProcesser; import com.tpw.newday.common.MyConstants; import com.tpw.newday.redis.RedisParam; import com.tpw.newday.redis.RedisService; import com.tpw.newday.utils.RedisUtil; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.*; import org.aspectj.lang.reflect.MethodSignature; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.LocalVariableTableParameterNameDiscoverer; import org.springframework.core.annotation.Order; import org.springframework.expression.ExpressionParser; import org.springframework.expression.spel.standard.SpelExpressionParser; import org.springframework.expression.spel.support.StandardEvaluationContext; import org.springframework.stereotype.Component;import javax.validation.constraints.Null; import java.lang.reflect.Method;/*** <h3>newday</h3>* <p>xx</p>** @author : lipengyao* @date : 2021-04-30 15:56:19**/ @Aspect @Component @Order(2) public class CacheAspect {private static final Log logger = LogFactory.getLog(CacheAspect.class);private RedisUtil redisUtil = new RedisUtil(MyConstants.redis_host_ip,MyConstants.redis_port,MyConstants.redis_password);@Autowiredprivate RedisService redisService;@Pointcut("execution(* com.tpw.newday.service..*.*(..)))")private void cacheMethod() {}/*** 前置通知:在目標方法執(zhí)行前調(diào)用*/@Before("cacheMethod()")public void begin() {logger.info("==@Before== lipy cache method : begin");}/*** 后置通知:在目標方法執(zhí)行后調(diào)用,若目標方法出現(xiàn)異常,則不執(zhí)行*/@AfterReturning(value = "cacheMethod()",returning = "ret")public void afterReturning(JoinPoint jp,Object ret) {Object[] args = jp.getArgs();logger.info("==@AfterReturning== lipy cache method : after returning ret:" + JSONUtil.toJsonStr(ret)+" args:" + JSONUtil.toJsonStr(args));}/*** 后置/最終通知:無論目標方法在執(zhí)行過程中出現(xiàn)一場都會在它之后調(diào)用*/@After("cacheMethod()")public void after() {logger.info("==@After== lipy cache method : finally returning");}/*** 異常通知:目標方法拋出異常時執(zhí)行*/@AfterThrowing(value = "cacheMethod()",throwing = "ex")public void afterThrowing(Throwable ex) {logger.info("==@AfterThrowing== lipy cache method : after throwing ex:" + ex.getMessage());}/*** 環(huán)繞通知:靈活自由的在目標方法中切入代碼*/@Around("cacheMethod()")public Object around(ProceedingJoinPoint joinPoint) throws Throwable {// 獲取目標方法的名稱String methodName = joinPoint.getSignature().getName();// 獲取方法傳入?yún)?shù)Object[] params = joinPoint.getArgs();logger.info("==@Around== lipy cache method --》begin method name " + methodName + " args " + (params.length > 0 ? params[0] :null));Object result = handleMethod(joinPoint);logger.info("==@Around== lipy cache method --》end method name " + methodName + " result " + JSONUtil.toJsonStr(result));return result;} }

切面2:

package com.tpw.newday.aspect;import cn.hutool.json.JSONUtil; import com.tpw.newday.common.MyConstants; import com.tpw.newday.redis.RedisService; import com.tpw.newday.utils.RedisUtil; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.*; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component;/*** <h3>newday</h3>* <p></p>** @author : lipengyao* @date : 2021-07-06 14:24:37**/ @Component @Aspect @Order(1) public class MqAopAspect {private static final Log logger = LogFactory.getLog(MqAopAspect.class);@Pointcut("@annotation(com.tpw.newday.annation.MqAop)")private void mqMethod() {}/*** 前置通知:在目標方法執(zhí)行前調(diào)用*/@Before("mqMethod()")public void begin() {logger.info("==@Before== lipy mq method : begin");}/*** 后置通知:在目標方法執(zhí)行后調(diào)用,若目標方法出現(xiàn)異常,則不執(zhí)行*/@AfterReturning("mqMethod()")public void afterReturning() {logger.info("==@AfterReturning== mq method : after returning");}/*** 后置/最終通知:無論目標方法在執(zhí)行過程中出現(xiàn)一場都會在它之后調(diào)用*/@After("mqMethod()")public void after() {logger.info("==@After== lipy mq method : finally returning");}/*** 異常通知:目標方法拋出異常時執(zhí)行*/@AfterThrowing("mqMethod()")public void afterThrowing() {logger.info("==@AfterThrowing== lipy mq method : after throwing");}/*** 環(huán)繞通知:靈活自由的在目標方法中切入代碼*/@Around("mqMethod()")public Object around(ProceedingJoinPoint joinPoint) throws Throwable {// 獲取目標方法的名稱String methodName = joinPoint.getSignature().getName();// 獲取方法傳入?yún)?shù)Object[] params = joinPoint.getArgs();logger.info("==@Around== lipy mq method --》begin method name " + methodName + " args " + (params.length > 0 ? params[0] :null));Object result = joinPoint.proceed();logger.info("==@Around== lipy mq method --》end method name " + methodName + " result:" + JSONUtil.toJsonStr(result));return result;}}

查看執(zhí)行結(jié)果

2021-07-06 15:07:35.101 INFO 28644 --- [nio-8080-exec-1] com.tpw.newday.aspect.MqAopAspect : ==@Around== lipy mq method --》begin method name getUserById args 1709121331320000 2021-07-06 15:07:35.101 INFO 28644 --- [nio-8080-exec-1] com.tpw.newday.aspect.MqAopAspect : ==@Before== lipy mq method : begin 2021-07-06 15:07:35.101 INFO 28644 --- [nio-8080-exec-1] com.tpw.newday.aspect.CacheAspect : ==@Around== lipy cache method --》begin method name getUserById args 1709121331320000 2021-07-06 15:07:35.123 INFO 28644 --- [nio-8080-exec-1] com.tpw.newday.aspect.CacheAspect : ==@Before== lipy cache method : begin 2021-07-06 15:07:35.125 DEBUG 28644 --- [nio-8080-exec-1] com.tpw.newday.service.UserServiceImpl : get begin userid:1709121331320000 2021-07-06 15:07:35.202 DEBUG 28644 --- [nio-8080-exec-1] org.hibernate.SQL : selecta.* fromsys_user a wherea.user_id=? Hibernate: selecta.* fromsys_user a wherea.user_id=? 2021-07-06 15:07:35.230 TRACE 28644 --- [nio-8080-exec-1] o.h.type.descriptor.sql.BasicBinder : binding parameter [1] as [VARCHAR] - [1709121331320000] 2021-07-06 15:07:35.259 DEBUG 28644 --- [nio-8080-exec-1] com.tpw.newday.service.UserServiceImpl : u1:com.tpw.newday.local_bean.JpaUser@79a58149 2021-07-06 15:07:35.285 INFO 28644 --- [nio-8080-exec-1] com.tpw.newday.service.UserServiceImpl : get end userid:1709121331320000 2021-07-06 15:07:35.285 DEBUG 28644 --- [nio-8080-exec-1] com.tpw.newday.service.UserServiceImpl : debug test common loging userid:1709121331320000 2021-07-06 15:07:35.285 INFO 28644 --- [nio-8080-exec-1] com.tpw.newday.service.UserServiceImpl : info test common loging userid:1709121331320000 2021-07-06 15:07:35.285 WARN 28644 --- [nio-8080-exec-1] com.tpw.newday.service.UserServiceImpl : warn test common loging userid:1709121331320000 2021-07-06 15:07:35.285 INFO 28644 --- [nio-8080-exec-1] com.tpw.newday.aspect.CacheAspect : ==@AfterReturning== lipy cache method : after returning ret:{"userCreateTime":1512653581000,"userPassword":"root123456","userStatus":"1","userName":"超級管理員","userId":"1709121331320000","roleName":"adminRole","userLoginName":"root"} args:["1709121331320000"] 2021-07-06 15:07:35.285 INFO 28644 --- [nio-8080-exec-1] com.tpw.newday.aspect.CacheAspect : ==@After== lipy cache method : finally returning 2021-07-06 15:07:35.306 INFO 28644 --- [nio-8080-exec-1] com.tpw.newday.aspect.CacheAspect : call method,set to cache key:getUserById:1709121331320000 2021-07-06 15:07:35.307 INFO 28644 --- [nio-8080-exec-1] com.tpw.newday.aspect.CacheAspect : ==@Around== lipy cache method --》end method name getUserById result {"userCreateTime":1512653581000,"userPassword":"root123456","userStatus":"1","userName":"超級管理員","userId":"1709121331320000","roleName":"adminRole","userLoginName":"root"} 2021-07-06 15:07:35.307 INFO 28644 --- [nio-8080-exec-1] com.tpw.newday.aspect.MqAopAspect : ==@AfterReturning== mq method : after returning 2021-07-06 15:07:35.307 INFO 28644 --- [nio-8080-exec-1] com.tpw.newday.aspect.MqAopAspect : ==@After== lipy mq method : finally returning 2021-07-06 15:07:35.307 INFO 28644 --- [nio-8080-exec-1] com.tpw.newday.aspect.MqAopAspect : ==@Around== lipy mq method --》end method name getUserById result:{"userCreateTime":1512653581000,"userPassword":"root123456","userStatus":"1","userName":"超級管理員","userId":"1709121331320000","roleName":"adminRole","userLoginName":"root"}

三、@order控制同一個接口的多實現(xiàn)版本對象通過構(gòu)造函數(shù)注入的列表對象順序。是在創(chuàng)建實例對象時,調(diào)用自動注入?yún)?shù)的構(gòu)造函數(shù),會從容器工廠registry中獲取依賴的實現(xiàn)此接口參數(shù)的所有對象,然后再對參數(shù)列表對象進行ORDER排序,最后調(diào)用帶參數(shù)構(gòu)造函數(shù)創(chuàng)建對象。最終實現(xiàn)在DefaultListableBeanFactory.resolveMultipleBeans

@Nullableprivate Object resolveMultipleBeans(DependencyDescriptor descriptor, @Nullable String beanName,@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) {Class<?> type = descriptor.getDependencyType();if (Collection.class.isAssignableFrom(type) && type.isInterface()) {Class<?> elementType = descriptor.getResolvableType().asCollection().resolveGeneric();if (elementType == null) {return null;}Map<String, Object> matchingBeans = findAutowireCandidates(beanName, elementType,new MultiElementDescriptor(descriptor));if (matchingBeans.isEmpty()) {return null;}if (autowiredBeanNames != null) {autowiredBeanNames.addAll(matchingBeans.keySet());}TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());Object result = converter.convertIfNecessary(matchingBeans.values(), type);if (result instanceof List) {if (((List<?>) result).size() > 1) {Comparator<Object> comparator = adaptDependencyComparator(matchingBeans);if (comparator != null) {((List<?>) result).sort(comparator);}}}return result;}}

?測試代碼:

@Service public class RunServiceImpl {public static interface DemoService{void say();}@Service@Order(-2)public static class DemoServiceImpl01 implements DemoService {public DemoServiceImpl01() {System.out.println("DemoServiceImpl01被實例化了");}@Overridepublic void say() {System.out.println("DemoServiceImpl01被執(zhí)行了");}}@Service@Order(0)public static class DemoServiceImpl02 implements DemoService {public DemoServiceImpl02() {System.out.println("DemoServiceImpl02被實例化了");}@Overridepublic void say() {System.out.println("DemoServiceImpl02被執(zhí)行了");}}@Service@Order(-1)public static class DemoServiceImpl03 implements DemoService {public DemoServiceImpl03() {System.out.println("DemoServiceImpl03被實例化了");}@Overridepublic void say() {System.out.println("DemoServiceImpl03被執(zhí)行了");}}public RunServiceImpl(List<DemoService> demoServices) { // AnnotationAwareOrderComparatordemoServices.forEach(t->t.say());} }

四、@order控制同一個對象上的多個condition條件的判斷順序。

ConditionEvaluator.shouldSkip 方法中。 public boolean shouldSkip(@Nullable AnnotatedTypeMetadata metadata, @Nullable ConfigurationPhase phase) {if (metadata == null || !metadata.isAnnotated(Conditional.class.getName())) {return false;}if (phase == null) {if (metadata instanceof AnnotationMetadata &&ConfigurationClassUtils.isConfigurationCandidate((AnnotationMetadata) metadata)) {return shouldSkip(metadata, ConfigurationPhase.PARSE_CONFIGURATION);}return shouldSkip(metadata, ConfigurationPhase.REGISTER_BEAN);}List<Condition> conditions = new ArrayList<>();for (String[] conditionClasses : getConditionClasses(metadata)) {for (String conditionClass : conditionClasses) {Condition condition = getCondition(conditionClass, this.context.getClassLoader());conditions.add(condition);}}AnnotationAwareOrderComparator.sort(conditions);for (Condition condition : conditions) {ConfigurationPhase requiredPhase = null;if (condition instanceof ConfigurationCondition) {requiredPhase = ((ConfigurationCondition) condition).getConfigurationPhase();}if ((requiredPhase == null || requiredPhase == phase) && !condition.matches(this.context, metadata)) {return true;}}return false;}

五、EventListenerFactory進行排序。在EventListenerMethodProcessor.postProcessBeanFactory中進行排序處理。

@Overridepublic void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {this.beanFactory = beanFactory;Map<String, EventListenerFactory> beans = beanFactory.getBeansOfType(EventListenerFactory.class, false, false);List<EventListenerFactory> factories = new ArrayList<>(beans.values());AnnotationAwareOrderComparator.sort(factories);this.eventListenerFactories = factories;}

六、ApplicationListener的通知順序,根據(jù)ORDER進行控制。

SimpleApplicationEventMulticaster.multicastEvent @Overridepublic void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));Executor executor = getTaskExecutor();for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {if (executor != null) {executor.execute(() -> invokeListener(listener, event));}else {invokeListener(listener, event);}}}

總結(jié)

以上是生活随笔為你收集整理的spring @order控制对象的顺序的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。