您现在的位置: 首页> 观点 > 正文
【Spring源码】- 10 Spring AOP核心API
发布时间:2023-03-28 13:08:28 来源:腾讯云

概述

Spring的两大核心:IoCAOPIoC作为Spring的根基,通过大量的扩展点让系统轻而易举的就可以实现良好的扩展性,而AOPIoC结合在一起,类似于发生强大化学反应一样,将Spring的功能性又提高了一个层次。Spring中也有大量使用AOP场景,比如@Configuration、数据库事务、mybatis mapper接口注入等等。

AOP全称Aspect Oriented Programming,即面向切面编程,其并非Spring独有,作为一种对OOP编程思想的补充,其也有自己的标准规范并有独立的组织进行维护。

根据织入时机的不同,AOP又可以分为三类:


(资料图)

编译时织入:ApectJ主要采用的就是编译时织入方式,这种一般使用特定的编译器方式实现;类加载时织入:这种一般都是依赖JVM Instruments技术实现,Spring中也有对这种技术支持,具体可以了解下LoadTimeWeaver;动态织入:动态代理方式实现AOP就是动态织入场景,Spring中实现AOP最主要方式,根据动态代理方式不同,又可以分为:JDK动态代理CGLIB动态代理

AOP标准规范是由独立的组织机构进行维护,其涉及到的核心概念主要如下:

连接点(JoinPoint):程序运行中的某个阶段点,比如方法的调用、异常的抛出、类初始化和对象实例化等。连接点是AOP的核心概念,并且定义了在应用程序中可以使用AOP插入其它逻辑的点;切点(Pointcut):切点是基于规则定义如何查找连接点,其可以看成包含一系列连接点的组合,Spring中对应的是Pointcut接口,定义了哪些类的哪些方法需要织入增强;通知(Advice):在连接点处需要织入的增强代码逻辑封装;切面(Aspect):切面是AdvicePointcut组合,对应SpringAdvisor;织入(Weaving):织入是在适当的位置将切面插入到应用程序代码中的过程,就是上面说的编译时织入、类加载时织入和动态织入;目标对象(target):AOP代理增强的原生对象;

基础API

Spring AOP很多人不能很好的理解、使用,一方面是因为AOP涉及的概念可能比较抽象,不容易理解;另外一方面你对Spring AOP涉及到的一些基础API不熟悉。下面我们就对Spring AOP中最核心的一些API,由底向上,由基础到高级方式一步步分析。

Enhancer

Spring AOP主要使用的是动态代理方式实现,动态代理实现主要包括两种:jdk动态代理cglib动态代理jdk动态代理方式比较熟悉,下面就来看下cglib动态代理如何实现。

Spring中提供了一个工具类:EnhancerSpring中主要就是利用该工具类创建cglib动态代理。下面我们通过一个案例看下其基本使用:

1、创建Callback回调接口类,该接口中就可以实现增强逻辑:

public class MyMethodInterceptor implements MethodInterceptor { @Override public Object intercept(Object obj, Method method, Object[] args, MethodProxy methodProxy)   throws Throwable {  try {   before(method);//前置通知   Object ret = methodProxy.invokeSuper(obj, args);//目标方法执行   after(method, ret);//后置通知   return ret;  } catch (Exception e) {   exception();//异常通知  } finally {   afterReturning();//方法返回通知  }  return null; } //前置增强 private void before(Method method) {  System.out.printf("before execute:%s\r\n", method.getName()); } //后置增强 private void after(Method method, Object ret) {  System.out.printf("after execute:%s, ret:%s\r\n", method.getName(), ret); } //异常增强 private void exception() {  System.out.println("execute failure"); } //after返回增强 private void afterReturning() {  System.out.println("execute finish"); }    }

2、编写测试:

//NoOp.INSTANCE:NoOp回调把对方法调用直接委派给这个方法在父类中的实现,即可理解为真实对象直接调用方法,没有任何增强private static final Callback[] CALLBACKS = new Callback[] {            new MyMethodInterceptor(),            NoOp.INSTANCE};public void test()  {    //创建Enhancer实例    Enhancer enhancer =  new Enhancer();        //cglib是基于继承方式代理,superClass就是基于哪个类型父类进行增强,创建出来的对象就是该类型子类    enhancer.setSuperclass(UserServiceImpl.class);    //CallbackFilter主要用于过滤不同Method使用不同的Callback    enhancer.setCallbackFilter(new CallbackFilter() {        @Override        public int accept(Method method) {            if (method.getDeclaringClass() == Object.class) {                return 1;//使用Callback数组下标是1的            }            return 0;//使用Callback数组下标是0的        }    });    //设置Callback数组,Callback就是封装的增强逻辑    enhancer.setCallbacks(CALLBACKS);    //创建代理对象    UserService proxyObj = (UserService) enhancer.create();    System.out.println(proxyObj.say("zhangsan"));}

通过上面enhancer.create()这条语句,就可以为目标类创建一个cglib动态代理,通过Callback回调方式将各种增强逻辑织入到代理实例中。

还可以使用Enhancer.createClass()方法只创建出代理类型,然后自己通过反射方式创建对象。这时,需要注意:1、这时就不能使用setCallbacks()设置Callback数组,而是使用setCallbackTypes()设置Callback对应的类型;2、Enhancer.createClass()执行完成后,再通过Enhancer.registerStaticCallbacks(clz, CALLBACKS)方式设置Callback数组;

enhancer.setInterfaces()可用于设置生成的代理类必须实现的接口,比如你可以不设置superclass,只设置interfaces,这时也是可以正常创建出基于这个接口的动态代理实例,但是这时就要注意不能触发目标对象方法执行,如methodProxy.invokeSuper执行会报错,如下:

public Object intercept(Object obj, Method method, Object[] args, MethodProxy methodProxy)  throws Throwable { try {  before(method);//前置通知  //Object ret = methodProxy.invokeSuper(obj, args);//目标方法执行  after(method, ret);//后置通知  return ret; } catch (Exception e) {  exception();//异常通知 } finally {  afterReturning();//方法返回通知 } return null;}

基于接口创建的代理实例还是非常有用的,比如mybatis mapper就是一个没有实现类的接口,但是在spring中却可以依赖注入到service bean中,其中就是利用到上面基于接口创建动态代理的思想,注入进来的其实就是基于接口的动态代理,然后调用接口中方法时就可以进行拦截,获取到具体调用方法签名信息以及参数信息,基于这些数据进行业务逻辑处理。

invoke和invokeSuper方法区别

Callback#intercept()回调方法中执行methodProxy.invokeSuper()methodProxy.invoke()是有很大区别的,而且看不到执行流程,所以这里涉及的逻辑非常绕。

public Object intercept(Object obj, Method method, Object[] args, MethodProxy methodProxy)  throws Throwable { Object ret = methodProxy.invokeSuper(obj, args);    Object ret = methodProxy.invoke(delete, args);}

大致区别如下图:

客户端触发代理对象say方法调用,首先进入代理对象中的同名方法,然后进入方法拦截对象MethodInterceptor,这里会出现两种情况:

如果调用invokeSuper方法,流程会重新走到代理对象中,代理对象这时会识别出是调用super中同名方法,所以没有继续向下走,而是通过super.say()方式调用目标对象中的方法。如果调用invoke方法,代理对象内部其实包裹一个目标对象target,这时它是直接通过target.say方式调用目标对象。

invokeSuper()invoke()方法都可以调用到目标对象方法,但是它们之间存在的一个本质区别:上下文环境不一样;或者更直接说:目标对象中this指向不一样。通过super.say()方式调用的目标对象,this指向的是代理对象;而通过target.say()方式调用的,目标对象中this指向的就是目标对象本身。这会导致什么差异呢?

假如目标对象类型如下定义,然后使用Enhancer创建一个代理对象:

public class Target {        public void a() {        System.out.println(" a 方法");        b();    }        public void b() {        System.out.println(" b 方法");    }}

客户端触发代理对象a()方法执行,如果拦截器中使用invoke方式调用目标对象:直接调用目标对象a()方法,这个方法中又会通过this.b()调用方法b,由于是目标对象本身内部调用,所以b()方法不会被拦截的。

客户端触发代理对象a()方法执行,如果拦截器中使用invokeSuper()方式调用目标对象:这里是通过super.a()方式调用目标对象中的a()方法,然后a()方法又会通过this.b()调用方法b,注意这时的this不是目标对象本身,而是代理对象,因为代理对象继承目标对象,代理对象会有重名方法覆写了目标对象方法。所以,this.b()实际上会触发代理对象中方法b的执行,这时是会触发拦截器的。

所以,methodProxy.invokeSuper(obj, args)这个obj是代理对象;而methodProxy.invoke(obj, args)这个入参obj是目标对象。搞清楚这些基本理解清楚应该使用invoke还是invokeSuper

ProxyFactory

Enhancer只能用于创建cglib动态代理Spring中还有一个更上层点的类ProxyFactory,可以用于创建JDK动态代理cglib动态代理

public void test02() { ProxyFactory proxyFactory = new ProxyFactory(); proxyFactory.setTarget(new UserServiceImpl());    /*    调用ProxyFactory.addInterface()或setInterfaces()表示对接口进行代理,一般会使用jdk动态代理,    除非setOptimize(true)或setProxyTargetClass(true)表示使用cglib代理    cglib代理类名称格式大致为:ServiceImpl$$EnhancerBySpringCGLIB$$f2952b94    */ //setInterfaces设置这个,会基于接口代理,使用jdk动态代理方式 proxyFactory.setInterfaces(UserService.class); //proxyFactory.setOptimize(true); //proxyTargetClass=true:直接代理目标类,而不是接口,使用cglib proxyFactory.setProxyTargetClass(true); // 添加增强 proxyFactory.addAdvice(new MyBeforeAdvice02());    //内部使用了缓存,target不变时,getProxy()获取到的都是同一个    //只有target变化时,才会重新创建新的代理对象 Object proxy = proxyFactory.getProxy();}

ProxyFactory类是AOP底层实现中非常重要的一个类,另外AnnotationAwareAspectJAutoProxyCreatorBeanNameAutoProxyCreatorDefaultAdvisorAutoProxyCreator等一些高级AOP实现工具类都是通过在其父类AbstractAutoProxyCreator中借助ProxyFactory实现AOP逻辑织入的。所以,理解ProxyFactory的使用对理解Spring AOP至关重要。

ProxyFactory类控制代理的创建过程,其内部委托给DefaultAopProxyFactory的一个实例,该实例又转而委托给Cglib2AopProxyJdkDynamicAopProxy,用于创建基于cglib代理还是jdk代理,想了解这两种动态代理区别可以分析下这个类源码。

ProxyFactoryaddAdvice()方法将传入的通知封装到DefaultPointcutAdvisor(DefaultPointcutAdvisorPointcutAdvisor的标准实现)的一个实例中,并使用默认包含所有方法的切入点对其进行配置。为更加灵活细粒度的控制在哪些连接点上拦截通知,可以使用addAdVisor()方法添加一个带有切入点消息的Advisor

可以使用相同的ProxyFactory实例来创建多个代理,每个代理都有不同的切面。为了帮助实现该过程,ProxyFactory提供了removeAdvice()removeAdvisor()方法,这些方法允许从ProxyFactory中删除之前传入的任何通知或切面,同时可以使用boolean adviceIncluded(@Nullable Advice advice)检查ProxyFactory是否附有特定的通知对象。

Advice

ProxyFactoryaddAdvice()addAdvisor()两个方法分别引入了两个重要的类:AdviceAdvisor。首先,我们来看下Advice这个接口类,其可以看成需要织入增强的代码逻辑封装。AdviceSpringAPI结构如下:

大致描述:

BeforeAdvice:前置通知,该接口没有任何方法,平时主要使用其子类MethodBeforeAdvice,因为Spring中只能在方法前后织入,对应注解@BeforeAfterAdvice:后置通知,其存在两个子类AfterReturningAdviceThrowsAdvice,分别对应@AfterReturning@AfterThrowingMethodInterceptor:可以实现环绕通知,对应注解@Around

Advisor

AOP规范中有切面概念,在Spring中大概对应就是AdvisorAdvisor有两个子接口:PointcutAdvisorIntroductionAdvisor

其实真正使用比较多的是它的子类PointcutAdvisor,该接口关键就是如下两个方法:

public interface PointcutAdvisor { Advice getAdvice(); Pointcut getPointcut();}

PointcutAdvisor从接口定义大概就可以看出,其就是对AdvicePointcut的封装,Advice代表的是横切面需要织入的代码,而Pointcut定义了如何去切的问题。从之前分析来看,Advice也可以看出一种非常简单的切面,是对指定的类所有方法都进行切入,横切面太宽泛,灵活性不够,PointAdvisor引入了Pointcut后显然比Advice更加灵活、强大。

PointcutAdvisor主要有6个具体的实现类,分别介绍如下:

DefaultPointcutAdvisor:最常用的切面类型,它可以通过任意PointcutAdvice定义一个切面,一般可以通过扩展该类实现自定义的切面;NameMatchMethodPointcutAdvisor:通过该类可以定义按方法名定义切点的切面;RegexpMethodPointcutAdvisor:使用正则表达式模式定义切点,其内部通过JdkRegexpMethodPointcut构造出正则表达式方法名切点;StaticMethodMatcherPointcutAdvisor:静态方法匹配器切点定义的切面,默认情况下,匹配所有的目标类;AspecJExpressionPointcutAdvisor:用于Aspecj切点表达式定义切点的切面;AspecJPointcutAdvisor:用于AspecJ语法定义切点的切面;

其实,这些Advisor主要区别还是基于其内部封装的Pointcut实现类体现的,在实际工作中这些类使用的可能不多,这里的核心在于Pointcut如何定义切入点,所以实际开发中更多的可能会去定制Pointcut实现类,然后使用DefaultPointcutAdvisor将其包装成Advisor使用。

下面通过RegexpMethodPointcutAdvisor案例简单了解即可:

public void test1(){    AnnotationConfigApplicationContext context =            new AnnotationConfigApplicationContext("aop.demo03");    UserServiceImpl target = new UserServiceImpl();    ProxyFactoryBean proxyFactoryBean = new ProxyFactoryBean();    proxyFactoryBean.setTarget(target);    proxyFactoryBean.setProxyTargetClass(true);    RegexpMethodPointcutAdvisor advisor = new RegexpMethodPointcutAdvisor();    //设置advisor的advice    advisor.setAdvice(new MyBeforeAdvice02());    //设置advisor的pointcut,aop.demo03包下所有类中已say开头的方法才会织入    advisor.setPattern("aop.demo03..*.say*");    proxyFactoryBean.addAdvisor(advisor);    proxyFactoryBean.setBeanFactory(context);    Object obj = proxyFactoryBean.getObject();    System.out.println(obj.getClass().getName());    UserServiceImpl userService = (UserServiceImpl) obj;    System.out.println(userService.say("haha"));}

RegexpMethodPointcutAdvisor表示通过正则表达式进行切点描述的切面,它有一个pattern属性用来指定增强要应用到哪些类的哪些方法,也可以通过patterns属性指定多个表达式进行匹配。有一个advice属性用来表示要应用的增强,这样就能表示一个完整的切面了。

Pointcut

Advisor引入了一个核心接口Pointcut,其描述了对哪些类的哪些方法进行切入。Pointcut从其定义可以看出其由ClassFilterMethodMatcher构成。ClassFilter用于定位哪些类可以进行切入,然后再通过MethodMatcher定位类上的哪些方法可以进行切入,这样Pointcut就拥有了识别哪些类的哪些方法能被进行切入的能力。

public interface Pointcut { ClassFilter getClassFilter(); MethodMatcher getMethodMatcher();}

Pointcut接口API结构见下:

其中这里比较常用的AnnotationMatchingPointcut基于注解进行切入,之前分析【Spring源码】- 09 扩展点之@Import注解一节就使用到该实现类,将标记有@MyAsync注解的方法都进行增强就是利用这个实现类:

AnnotationMatchingPointcut pointcut = AnnotationMatchingPointcut.forMethodAnnotation(MyAsync.class);Advice advice = new AsyncAnnotationAdvice(executor);DefaultPointcutAdvisor advisor = new DefaultPointcutAdvisor();advisor.setPointcut(pointcut);advisor.setAdvice(advice);ProxyFactory proxyFactory = new ProxyFactory();proxyFactory.setTarget(bean);if(!this.isProxyTargetClass()){ proxyFactory.setInterfaces(bean.getClass().getInterfaces());}proxyFactory.addAdvisor(advisor);proxyFactory.copyFrom(this);return proxyFactory.getProxy();

ProxyFactoryBean

ProxyFactoryBeanProxyFactory功能和使用其实差不多,底层逻辑也基本一致,ProxyFactoryBean主要是融合了IOC功能。一方面ProxyFactoryBean类是FactoryBean的一个实现,更加方便注入IoC中,参照mybatisspring整合一节,其中关键一步就是将扫描的BeanDefinitionbeanClass由接口类替换成FactoryBean类型;另一点就是切面可以使用IoC容器bean

下面通过一个案例简单看下ProxyFactoryBean使用:

package org.simon.ioc.demo1;import org.springframework.aop.MethodBeforeAdvice;import org.springframework.stereotype.Component;import java.lang.reflect.Method;@Componentpublic class MyBeforeAdvice implements MethodBeforeAdvice { public void before(Method arg0, Object[] arg1, Object arg2) throws Throwable {  System.out.println("-----洗手-----"); }}
@Testpublic void test1(){ AnnotationConfigApplicationContext context =    new AnnotationConfigApplicationContext("org.simon.ioc.demo1"); UserService target = new UserServiceImpl(); ProxyFactoryBean proxyFactoryBean = new ProxyFactoryBean(); proxyFactoryBean.setTarget(target); proxyFactoryBean.setInterceptorNames("myBeforeAdvice", "otherAdvice*"); proxyFactoryBean.setBeanFactory(context); Object obj = proxyFactoryBean.getObject(); System.out.println(obj.getClass().getName()); UserService userService = (UserService) obj; System.out.println(userService.say("haha"));}

其中关键一步在:proxyFactoryBean.setInterceptorNames("myBeforeAdvice", "otherAdvice*");,可以使用IoC中的beanName,同时还支持通配符*IoC中查找对应Bean

高级API

前面介绍的类、接口等都是Spring AOP中一些底层API,使用起来不太方便,感觉功能不太强大,不论是ProxyFactory还是ProxyFactoryBean创建织入切面的代理,每次只能硬编码一个具体的Bean,假如我想将某个包路径下符合一定规则的类的特定方法都进行织入代理怎么办?

使用前面那些API好像都不能实现这个需求,但是结合之前分析的Spring扩展点,很容易想到可以结合BeanPostProcessor扩展点实现这个需求,postProcessAfterInitialization()这个方法回调时Bean依赖注入、初始化等都已经完成,这时就可以在这个方法中过滤出符合一定条件的Bean进行代理增强处理。

其实,在Spring中基于这种思想,已经为我们提供了三个实现类:

BeanNameAutoProxyCreator:基于beanName进行织入增强,通过setBeanNames(String... beanNames)将需要增强的beanName设置进去;DefaultAdvisorAutoProxyCreator:基于Advisor匹配机制进行织入增强,它会对容器中所有的Advisor进行扫描,自动将这些切面应用到匹配的Bean中;AnnotationAwareAspectjAutoProxyCreator:基于BeanAspectJ注解方式进行织入增强,就是实现平时使用的@Aspect@Before@AroundAspectJ注解功能支持。

下面我们就来通过DefaultAdvisorAutoProxyCreator了解下使用场景:

1、定义一个目标类,后续就是基于该类进行增强:

@Componentpublic class UserServiceImpl{ public String say(String name){  System.out.println("执行:==UserService#say===");  return "hello,"+name; }}

2、定义一个配置类:

@Configuration@ComponentScan(basePackageClasses = AopConfig.class)public class AopConfig {    @Bean    public RegexpMethodPointcutAdvisor regexpMethodPointcutAdvisor(){        RegexpMethodPointcutAdvisor advisor = new RegexpMethodPointcutAdvisor();        advisor.setAdvice(new MyBeforeAdvice02());        //aop.demo03包下所有类中带有say开头方法进行增强        advisor.setPattern("aop.demo03..*.say*");        return advisor;    }    @Bean    public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator(){        return new DefaultAdvisorAutoProxyCreator();    }}

这个类有两个关键,一个是向IoC中注入Advisor,之前分析过Advisor包含两个功能:

通过Pointcut定位哪些类的哪些方法需求切入;通过关联的Advice指定切入增强逻辑;

另一个关键就是注入DefaultAdvisorAutoProxyCreator,这个就是一个Spring内置的实现BeanPostProcessor扩展类,其在postProcessAfterInitialization()方法中对Bean进行切入增强。

3、测试:

public void test1(){        AnnotationConfigApplicationContext context =                new AnnotationConfigApplicationContext(AopConfig.class);        System.out.println(context.getBean(UserServiceImpl.class).getClass());}

context.getBean(UserServiceImpl.class)IoC容器中获取的就是使用cglib代理后的实例。

下面我们再来分析下AnnotationAwareAspectjAutoProxyCreator,平时如果项目中需要开启AOP功能,使用@EnableAspectJAutoProxy注解方式开启,我们来看下该注解干了什么?

1、@EnableAspectJAutoProxy注解使用@Import注解将AspectJAutoProxyRegistrar引入:

@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)@Documented@Import(AspectJAutoProxyRegistrar.class)public @interface EnableAspectJAutoProxy { boolean proxyTargetClass() default false; boolean exposeProxy() default false;}

2、AspectJAutoProxyRegistrarImportBeanDefinitionRegistrar接口实现类:

class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar { @Override public void registerBeanDefinitions(   AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {  //注册一个SmartInstantiationAwareBeanPostProcessor类型的实现类:AnnotationAwareAspectJAutoProxyCreator  AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);  AnnotationAttributes enableAspectJAutoProxy =    AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);  if (enableAspectJAutoProxy != null) {   if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {    AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);   }   if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {    AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);   }  } }}

其中最关键一句AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);,就是向IoC容器中注入AnnotationAwareAspectJAutoProxyCreator

这样我们就明白了@EnableAspectJAutoProxy注解方式开启AOP的本质就像向IoC中注入AnnotationAwareAspectJAutoProxyCreator,它利用BeanPostProcessor扩展点功能实现织入增强逻辑。

总结

首先,对Spring AOP底层一些最基础、最核心的API的分析梳理,相信你会对Spring AOP底层实现逻辑有了一个更加深入的理解。然后通过Spring AOP提供的高级API,理解了如何将IoCAOP集成到一起实现强大功能,对SpringAOP的整体实现思路也有了比较清晰的认识。

标签:

【Spring源码】- 10 Spring AOP核心API

Spring的两大核心:IoC和AOP,IoC作为Spring的根基,通过大量的扩展点让系统轻而易举的就可以实现良好的...

【世界速看料】天润工业:公司已完成多个商用车悬架产品平台的开发 各个产品平台下也已有多款产品实现批量供货

每经AI快讯,有投资者在投资者互动平台提问:请问1、空悬技术目前正在研发攻克哪些环节?2、在建工程不...

全球时讯:阿斯利康深化在华研发布局,2030年预计在中国市场至少推15个创新药物

阿斯利康将进一步推动全球研发及中国团队与中国临床研究机构、学术机构、中国本土创新企业的合作,深化...

当前速递!和讯个股快报:2023年03月28日 利尔化学 (002258),股价出现向上跳空缺口

受板块利好消息影响,该股快速拉升,出现向上跳空缺口,说明多方力量聚集,主力资金做多意愿明显。截至...

3月27日基金净值:华安上证180ETF最新净值3.5231,跌0.54% 世界热议

3月27日,华安上证180ETF最新单位净值为3 5231元,累计净值为3 8244元,较前一交易日下跌0 54%。历史...

2023上海樱花节,快来宝山汇“圈子”晒图赢好礼

2023上海樱花节已于3月15日在顾村公园开幕啦~~本届樱花节活动内容丰富分为五大板块共21项系列活动力求打...

天天观热点:女性长期不吃早餐的10大危害_早餐不吃有什么危害

1、不吃早餐主要有下面几大危害:不吃早餐精力不集中,情绪低落。2、经过一晚上的消化,前一天所吃的晚饭...

今日关注:光遇2022年中秋节活动

Sky光遇中有很多玩家在提高自身战斗力的时候不知道光遇2022年中秋节活动问题的解决办法,小编刚接触这款...

中国央视网官网app_中国央视网|全球报资讯

1、我爱我们伟大的祖国,我要好好学习来报答祖国。2、 辽宁省普兰店市新城小学 一年一班 巩子莲。本...

环球速读:前两月中国软件业务收入超1.4万亿元 利润总额增长12.2%

数据显示,1-2月份,中国软件业务收入14461亿元(人民币,下同),同比增长11%;软件业利润总额1769亿元,...

长城汽车新能源SUV哈弗B07官宣命名枭龙MAX

长城汽车官微3月27日宣布,哈弗新能源销售网络官宣命名哈弗龙网,四驱新能源SUV哈弗B07官宣命名枭龙MAX,SUV哈弗

股票牛市和熊市是什么意思_股票牛市

1、牛市股票市场上买入者多于卖出者,股市行情看涨称为牛市。2、形成牛市的因素很多,主要包括以下几个...

银行业风暴下市场分化,美大型科技股能否继续独领风骚?

在美股市场整体颓靡的情况下,科技巨头年初重拾的涨势仍在持续。

全球热文:优化营商环境 激发专精特新企业发展活力充分释放

央视网消息:工业和信息化部的最新数据显示,2月份,我国专精特新“小巨人”企业发展信心、创新能力和对...

勇士输了!普尔关键失误,小佩顿首秀惊艳,水花兄弟不尽人意

勇士输了!普尔关键失误,小佩顿首秀惊艳,水花兄弟不尽人意,普尔,勇士,库里,快船队,小佩顿,水花兄弟,卡...

30+选择读研:年龄不是提升学历的“限高杆” 全球独家

30+选择读研:年龄不是提升学历的“限高杆”32岁再来读研,晚吗?黎瑞(化名)的回答很明确:不晚。黎瑞...

【天天聚看点】“零接触”“零跑腿”“零差错” !长沙开启第三方评标专家劳务报酬“云”支付

长沙晚报掌上长沙3月27日讯(全媒体记者 谭晓波)优化营商环境,长

2023南通大学公开招聘报名时间+入口

报名(一)报名时间、地点、方式应聘人员通过“江苏省属事业单位公开招聘平台”报名,照片上传、资格初审...

色斑越抹越淡,脸蛋越来越白!一招让你摆脱脸部蜡黄、斑纹困扰~

每个女人都向往一张白净无瑕、莹润光泽的脸,正所谓:“一白遮百丑”,皮肤白净透亮的人,气质都会显得...

囊袋是什么意思 日语_囊袋 每日快报

1、男士内裤中的囊袋也叫阴囊托主要作用是托住阴囊,防止阴囊下垂,避免阴囊与大腿内侧相互摩擦,增加通...

稚子弄冰改写成短文500字五年级(稚子弄冰改写成短文)

1、刘,五年级一班2、冬天的清晨,一个孩子冲出家门。他跑向金盆。他在盆里发现了一小块冰。他兴奋地捡...

盯盘-2舍得酒业股票股暴力拉升 10股秒停

7月11日电,恒大地产集团公告,“20恒大01”持有人会议审议未经过以下方案:方案一:《关于改变本期债券...

聚焦:钟情湖北 樱你而来

武汉大学校史馆前的樱花绽放本报记者张锐摄李德仁院士与游客在武汉大学樱花大道上合影本报记者张锐摄武...

全球热点评!张无忌电影免费观看_张无忌电影

1、1963,倚天屠龙记(上,下)集。2、张瑛饰张翠山,白燕饰殷素素1965,倚天屠龙记(上。3、下)集(1963

重庆水轮机厂(重庆水轮厂现在效益怎么样)

本文目录一览:1、重庆水轮厂现在效益怎么样2、重庆水轮机厂有限责任公司怎么样?重庆水轮厂现在效益怎么

230亿元!利率最高的50年期国债来了

最资讯丨扣子大手是什么意思

《狂飙》里的人为啥都爱吃“饺子”

房屋产生诉讼顾客游泳年卡被催促消费?沙壁虎:不强制 全球播资讯

甘肃肃南:非遗进校园 文化“活”起来-环球聚看点

属鸡年龄查询表 对照表 对应岁数多大

东莞楼市小阳春来了吗?为什么东莞待售二手房不降反增?

朱玲玲大把年纪真敢穿,可惜长胖肩太厚,穿露肩裙仪态被拉垮 环球聚看点

明代偶像天团,在龙美术馆西岸馆等你-环球头条

天天要闻:陆振华演过的所有电视剧

锌锰电池电极反应式_锌铜电池电极反应式-环球播资讯

V观财报|豪森股份及董事长等被通报批评!多期财报财务数据与实际不符

全球报道:银河恒益混合A基金经理变动:增聘何晶为基金经理

关于中秋节的来历和传说

台州市实验中学校长_台州市实验中学

havana歌词意境_havana歌词|环球看点

华体股份与广州城投拟共同设立500万广州城投华体文化体育发展有限公司 其中公司出资额245万|全球微头条

晶瑞电材(300655.SZ):参股子公司湖北晶瑞拟引入3家战投 获得增资2.2亿元

多点发力 精准支付 宝鸡市凤翔区财政国库支付中心助推乡村振兴高质量发展 全球球精选

您拨打的电话暂时无法接通图片_您拨打的电话暂时无法接通-全球播报

【天天报资讯】运动裤搭配什么鞋子

看黄河文化、观长城古堡、寻塞上乡情……宁夏吴忠发布最新文旅线路

我和甲骨文的故事丨甲骨文识读大会初赛回眸_环球速读

桃源深处有人家上山攻略-桃源深处有人家怎么上山_当前速递

世界信息:愚人节淘宝有活动吗?4月份有哪些活动?

天天新资讯:吴立春:侨商要承担起回报社会的责任

固定资产折旧表格公式_固定资产折旧表模板带公式

环球视点!高尔基的生平简介

焦点精选!目光所及之处是你

浇头麻辣烫_浇头

甲流爆发!除了奥司他韦,还能用这些药 当前热文

未及时披露对外担保事项,ST中捷及时任董事长收浙江证监局行政处罚决定书

环球资讯:股票公司投资大参考新闻

徐令宜个人资料

腾讯2022年财报:游戏收入1707亿,至少20款产品已获版号-热资讯

环球观热点:宗申动力:子公司宗申航发公司拟引入战略投资者

法本信息:公司会持续关注AIGC并为行业客户提供优质软件技术服务|世界新资讯

微速讯:美联储宣布加息!订单缩水!江浙广进出口双双大跌!塑企下跌31%

首发 | 280㎡顶层公寓,极简风和空中花园绝配!

请问怎样开通蚂蚁花呗呢_全球热门

3人吃河豚中毒其中2例重症,绍兴疾控:切莫“以身试毒”

环球热文:花旗CEO:移动互联网使银行挤兑风险巨变 无意收购第一共和银行(FRC.US)

“湾区共话”:以STEAM汇聚“大湾区学校领导力”,点燃教育高质量发展引擎 世界独家

宝兰德:3月22日融资净买入4.95万元,连续3日累计净买入296.31万元

国安局招人有哪些条件-国安局有少校军衔 天天百事通

来自星星的你演员表

欧洲央行官员认为上周加息合理 相信银行体系经受住了考验 天天热推荐

语文教案评语_语文教案

久盛电气(301082):第五届第八次董事会会议决议,审议《关于选举公司第五届董事会各专门委员会委员的议案》

环球即时看!为什么王者荣耀今天没更新s9,王者荣耀s9季什么时候更新

x 广告
x 广告

Copyright ©  2015-2022 太平洋自然网版权所有  备案号:豫ICP备2022016495号-17   联系邮箱:93 96 74 66 9@qq.com