Spring

本文详细介绍了Spring框架的核心概念,包括搭建Spring环境、编写配置文件、使用IOC和AOP。重点讲解了注解实现的事务管理和AOP通知,以及如何通过配置将类转换为通知。同时,还涵盖了Spring开发Web项目时的配置文件拆分,以及Spring的IoC容器和Bean的生命周期管理。此外,文章还提到了Spring与Quartz的整合,用于实现定时异步任务。
摘要由CSDN通过智能技术生成

2002 Rod Johnon <Expoer One-on-one j2eedevelopment and Design>
Spring  2003  ,IOC  Aop
Spring data,spring boot,spring cloud,spring framework ,spring social 

IOC :控制反转 (DI:依赖注入)

1.搭建Spring环境

下载jar
https://maven.springframework.org/release/org/springframework/spring/
spring-framework-4.3.9.RELEASE-dist.zip
开发spring至少需要使用的jar(5个+1个):
spring-aop.jar        开发AOP特性时需要的JAR
spring-beans.jar    处理Bean的jar            <bean>
spring-context.jar    处理spring上下文的jar        <context>
spring-core.jar        spring核心jar
spring-expression.jar    spring表达式 
三方提供的日志jar
commons-logging.jar    日志

2.编写配置文件

为了编写时有一些提示、自动生成一些配置信息:
方式一:增加sts插件
可以给eclipse增加 支持spring的插件:spring tool suite(https://spring.io/tools/sts/all)
下载springsource-tool-suite-3.9.4.RELEASE-e4.7.3a-updatesite.zip,然后在Eclipse中安装:Help-Install new SoftWare.. - Add

方式二:
    直接下载sts工具(相当于一个集合了Spring tool suite的Eclipse): https://spring.io/tools/sts/

新建:bean configuration .. - applicationContext.xml


3.开发Spring程序(IOC)

        ApplicationContext conext = new ClassPathXmlApplicationContext("applicationContext.xml") ;
        //执行从springIOC容器中获取一个 id为student的对象
        Student student = (Student)conext.getBean("student") ;
可以发现,springioc容器 帮我们new了对象,并且给对象赋了值

SpringIOC发展史:
1.
Student student = new Student();
student.setXxx();

2.
简单工厂

3.ioc (超级工厂)

IOC(控制反转)也可以称之为DI(依赖注入):
控制反转:将 创建对象、属性值 的方式 进行了翻转,从new、setXxx()  翻转为了 从springIOC容器getBean()
依赖注入:将属性值 注入给了属性,将属性 注入给了bean,将bean注入给了ioc容器;

 
总结:ioc/di ,无论要什么对象,都可以直接去springioc容器中获取,而不需要自己操作(new\setXxx())

因此之后的ioc分为2步:1 先给springioc中存放对象并赋值   2 拿


DI:依赖注入 ,
Teacher  

Course  : cname  teacher

IOC容器赋值:如果是简单类型(8个基本+String),value; 
    如果是对象类型,ref="需要引用的id值",因此实现了 对象与对象之间的依赖关系


conext.getBean(需要获取的bean的id值)

依赖注入3种方式:
1.set注入:通过setXxx()赋值

赋值,默认使用的是 set方法();
依赖注入底层是通过反射实现的。
<property...>


2.构造器注入:通过构造方法赋值
 <constructor-arg value="ls" type="String" index="0" name="name"></constructor-arg>
需要注意:如果  <constructor-arg>的顺序 与构造方法参数的顺序不一致,则需要通过type或者index或name指定。

3.p命名空间注入
引入p命名空间
    xmlns:p="http://www.springframework.org/schema/p"

<bean id="course" class="org.lanqiao.entity.Course" p:courseHour="300" p:courseName="hadoop" p:teacher-ref="teacher">

简单类型:
    p:属性名="属性值"
引用类型(除了String外):
    p:属性名-ref="引用的id"
注意多个 p赋值的时候 要有空格。
注意:
无论是String还是Int/short/long,在赋值时都是 value="值" ,
因此建议 此种情况 需要配合 name\type进行区分

示例:
    注入各种集合数据类型: List  Set map properties

set、list、数组   各自都有自己的标签<set> <list> <array>,但是也可以混着用


给对象类型赋值null :
        <property name="name" >  
                <null/>       -->注意 没有<value>
        </property>
赋空值 ""  
        <property name="name" >  
                <value></value>  
        </property>

在ioc中定义bean的前提:该bean的类 必须提供了 无参构造

自动装配(只适用于 ref类型 ):
    约定优于配置


自动装配:
<bean ... class="org.lanqiao.entity.Course"  autowire="byName|byType|constructor|no" >  byName本质是byId
byName:  自动寻找:其他bean的id值=该Course类的属性名
byType:  其他bean的类型(class)  是否与 该Course类的ref属性类型一致  (注意,此种方式 必须满足:当前Ioc容器中 只能有一个Bean满足条件  )
constructor: 其他bean的类型(class)  是否与 该Course类的构造方法参数 的类型一致;此种方式的本质就是byType


可以在头文件中 一次性将该ioc容器的所有bean  统一设置成自动装配:
<beans xmlns="http://www.springframework.org/schema/beans"
...
default-autowire="byName">

自动装配虽然可以减少代码量,但是会降低程序的可读性,使用时需要谨慎。

使用注解定义bean:通过注解的形式 将bean以及相应的属性值 放入ioc容器

<context:component-scan base-package="org.lanqiao.dao">
</context:component-scan>Spring在启动的时候,会根据base-package在 该包中扫描所有类,查找这些类是否有注解@Component("studentDao"),如果有,则将该类 加入spring Ioc容器。

@Component细化:

dao层注解:@Repository
service层注解:@Service
控制器层注解:@Controller

1 使用注解实现事务(声明式事务)

目标:通过事务 使以下方法 要么全成功、要么全失败
public void addStudent()
{
    //增加班级
    //增加学生
    //crdu
}

a. jar包
spring-tx-4.3.9.RELEASE
ojdbc.jar
commons-dbcp.jar  连接池使用到数据源
commons-pool.jar  连接池
spring-jdbc-4.3.9.RELEASE.jar
aopalliance.jar 

b.配置
jdbc\mybatis\spring
增加事务tx的命名空间
<!-- 增加对事务的支持 -->
<tx:annotation-driven transaction-manager="txManager"  />

c.使用

将需要 成为事务的方法 前增加注解:
@Transactional(readOnly=false,propagation=Propagation.REQUIRED)

2.AOP:面向方面编程


一个普通的类    ->    有特定功能的类  
    a.继承类  b.实现接口  c.注解  d.配置
  
public class MyFilter exntends/implements Xx
{

}


类 -> “通知” :实现接口

前置通知实现步骤:
a.jar
    aopaliance.jar
    aspectjweaver.jar

b.配置


c.编写
    aop:每当之前add()之前 自动执行一个方法log();

    addStudent();  业务方法(IStudentService.java中的  addStudent())
    before();  自动执行的通知,即aop前置通知

public class Xxx
{
    @Test
    a(){}
}

如果出现异常:类似java.lang.NoClassDefFoundError: org/apache/commons/pool/impl/GenericObjectPool
则说明缺少jar


后置通知:
a.通知类  ,普通实现接口
b.业务类、业务方法
    StudentServiceImpl中的addStudent()
c.配置:
    将业务类、通知 纳入springIOC容器
    定义切入点(一端)、定义通知类(另一端),通过pointcut-ref将两端连接起来


异常通知:
    根据异常通知接口的定义可以发现,异常通知的实现类 必须编写以下方法:
    public void afterThrowing([Method, args, target], ThrowableSubclass):

    a.public void afterThrowing(Method, args, target, ThrowableSubclass)
    b.public void afterThrowing( ThrowableSubclass)

环绕通知: 在目标方法的前后、异常发生时、最终等各个地方都可以 进行的通知,最强大的一个通知;
    可以获取目标方法的 全部控制权(目标方法是否执行、执行之前、执行之后、参数、返回值等)

    在使用环绕通知时,目标方法的一切信息 都可以通过invocation参数获取到
    环绕通知 底层是通过拦截器实现的。

二、实现注解实现 通知 ,aop

a.jar
    与 实现接口 的方式相同
b.配置
    将业务类、通知 纳入springIOC容器
    开启注解对AOP的支持<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
    业务类 addStudent -  通知 

c.编写
    
    
通知:
@Aspect  //声明该类 是一个 通知
public class LogBeforeAnnotation  {

}

注意:通过注解形式 将对象增加到 ioc容器时,需要设置 扫描器
<context:component-scan base-package="org.lanqiao.aop"></context:component-scan>
    
扫描器 会将 指定的包 中的  @Componet @Service  @Respository   @Controller修饰的类产生的对象 增加到IOC容器中
@Aspect不需要 加入扫描器,只需要开启即可:<aop:aspectj-autoproxy></aop:aspectj-autoproxy>

通过注解形式 实现的aop,如果想获取 目标对象的一些参数,则需要使用一个对象:JointPoint

注解形式的返回值:
a.声明返回值 的参数名:
    @AfterReturning( pointcut= "execution(public * addStudent(..))" ,returning="returningValue" ) 
    public void myAfter(JoinPoint jp,Object returningValue) {//returningValue是返回值,但需要告诉spring
        System.out.println("返回值:"+returningValue );
注解形式实现aop时,通知的方法的参数不能多、少

实现接口形式、注解形式 只捕获声明的特定类型的异常,而其他类型异常不捕获。
cath()

三、通过 配置将 类->通知 

基于Schema配置
类似 与 实现接口的方式

接口方式通知:public class LogAfter implements AfterReturningAdvice
Schema方式通知:
    a.编写一个普通类  public class LogAfter {}  
    b.将该类 通过配置,转为一个“通知”
    

如果要获取目标对象信息:
注解、schema:JoinPoint
接口:Method method, Object[] args, Object target

schema形式 和注解形式相似,不同之处: 注解形式 使用了注册@After,  schmema形式进行了多余的配置

1.Spring开发Web项目 及 拆分Spring配置文件

a.Spring开发Web项目
   Web项目如何初始化SpringIOC容器 :思路:当服务启动时(tomcat),通过监听器将SpringIOC容器初始化一次(该监听器 spring-web.jar已经提供)
   因此用spring开发web项目 至少需要7个jar: spring-java的6个jar + spring-web.jar,注意:web项目的jar包 是存入到WEB-INF/lib中

web项目启动时 ,会自动加载web.xml,因此需要在web.xml中加载 监听器(ioc容器初始化)。

Web项目启动时,启动实例化Ioc容器:
 <!-- 指定 Ioc容器(applicationContext.xml)的位置-->
  <context-param>
          <!--  监听器的父类ContextLoader中有一个属性contextConfigLocation,该属性值 保存着 容器配置文件applicationContext.xml的位置 -->
          <param-name>contextConfigLocation</param-name>
          <param-value>classpath:applicationContext.xml</param-value>
  </context-param>  
  <listener>
      <!-- 配置spring-web.jar提供的监听器,此监听器 可以在服务器启动时 初始化Ioc容器。
          初始化Ioc容器(applicationContext.xml) ,
              1.告诉监听器 此容器的位置:context-param
              2.默认约定的位置    :WEB-INF/applicationContext.xml
       -->
      <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>


b.拆分Spring配置文件
    java项目:
        applicationContext1.xml
        applicationContext2.xml
        applicationContext3.xml

ApplicationContext conext = new ClassPathXmlApplicationContext("applicationContext3.xml") ;

    Web项目:

 根据什么拆分?

        i.三层结构   
            UI(html/css/jsp  、Servlet)  applicationController.xml
            Service :applicationService.xml
            Dao:applicationDao.xml
            公共 数据库:applicationDB.xml

        ii.功能结构
            学生相关配置 applicationContextStudent.xml   <bean id=""  class="X...Student">
            班级相关配置 applicationContextClass.xml 

        合并:如何将多个配置文件 加载
            (1)
          <context-param>
          <!--  监听器的父类ContextLoader中有一个属性contextConfigLocation,该属性值 保存着 容器配置文件applicationContext.xml的位置 -->
  <param-name>contextConfigLocation</param-name>
          <param-value>
              classpath:applicationContext.xml,
              classpath:applicationContext-Dao.xml,
              classpath:applicationContext-Service.xml,
              classpath:applicationContext-Controller.xml
          </param-value>
  </context-param>


        (2)推荐
  <context-param>
          <!--  监听器的父类ContextLoader中有一个属性contextConfigLocation,该属性值 保存着 容器配置文件applicationContext.xml的位置 -->
          <param-name>contextConfigLocation</param-name>
          <param-value>
              classpath:applicationContext.xml,
              classpath:applicationContext-*.xml
          </param-value>
  </context-param>

        (3)只在web.xml中加载主配置文件,
        <param-value>
              classpath:applicationContext.xml
          
          </param-value>
        然后在主配置问加中,加载其他配置文件
            <import resource="applicationContext-*.xml"/>
      

    Web项目:

Spring IoC容器?两种形式:    

    xml配置文件:applicationContext.xml
        存bean:  <bean id class>
        取bean:
ApplicationContext context= new ClassPathXmlApplicationContext("applicationContext.xml");
        context.getBean();

    注解:带有@Configuration注解的类(配置类)
注意:两种形式获取的Ioc容器是 独立的

    存bean
        XXX
    取bean
 ApplicationContext context  = new AnnotationConfigApplicationContext(MyConfig.class) ;

XXX:注解形式 给IoC容器中存放Bean:
    1.必须有@Configuration注解(配置类)
    
    2.形式:
        ①三层组件加入IOC容器: 给个各类加    注解 、 扫描器识别注解所在包
            a.给三层组件 分别加注解(@Controller、@Service、@Repository -> @Component)
            b.将注解所在包 纳入ioc扫描器(ComponentScan)
                纳入ioc扫描器:  ①xml配置文件 :    <context:component-scan base-package="com.yanqun.controller"  >
    </context:component-scan>
    逻辑: 在三层类上加注解  ,让ioc识别,扫描器
                        ②注解扫描器

component-scan:只对三层组件负责

给扫描器指定规则    :

    过滤类型:FilterType(ANNOTATION,ASSIGNABLE_TYPE,CUSTOM)

    ANNOTATION:三层注解类型@Controller、@Service、@Repository -> @Component

excludeFilters:排除
includeFilters:有默认行为,可以通过useDefaultFilters = false禁止

    ASSIGNABLE_TYPE:具体的类(StudentService.class)
区分:
ANNOTATION:Controller.clss 指的是 所有标有@Controller的类
ASSIGNABLE_TYPE:值得是具体的一个类 StudentController.class

CUSTOM自定义:自己定义包含规则
@ComponentScan.Filter(type= FilterType.CUSTOM ,value={MyFilter.class}

MyFilter implements TypeFilter 重写其中的match,如果return true则加入IoC容器
    

        ②非三层组件(Student.class 、IntToStringConver.class):

            i.  @Bean+方法的返回值 ,id默認就是方法名(可以通过@Bean("stu") 修改id值)
            ii. import 、FactoryBean
            


bean: 类  
    a.  非三层组件   :Student\Teacher\配置信息  : @Bean
    b.  三层组件 :Controller、Service、Dao  :@Component(@Controller、@Service、@Repository)


三层组件
    a.加入@Component等注解
    b.配置,让容器识别注解
        i.XML形式:通过扫描器  将@Component等注解所在包 扫描 
             <context:component-scan base-package="com.yanqun" >

                </context:component-scan>
            
                
        ii.注解
            @Configuration
@ComponentScan(value="com.yanqun")
public class MyConfig {...}

 
component-scan指定规则:

FilterType :
    ANNOTATION:指定类型 (@Compent @Controller  @Service  @Repository)
    ASSIGNABLE_TYPE :自定义类的类中选 StudentDao
    ASPECTJ,
    REGEX,
    CUSTOM:自定义形式  :a.@ComponentScan.Filter(type= FilterType.CUSTOM,classes ={ MyFilter.class  })},useDefaultFilters = false)
        b.MyFilter  implements TypeFilter   重写match()方法,如果返回值true
---

@Component(@Controller、@Service、@Repository):三层组件
非三层组件

---

--bean的作用域

    scope:  singleton| prototype
执行时机(产生bean的时机):
    singleton:容器在初始化时,就会创建对象(唯一的一个);以后再getBean时,不再产生新的bean。singleton也支持延迟加载(懒加载):在第一次使用时产生。 @Lazy
    prototype:容器在初始化时,不创建对象;只是在每次使用时(每次从容器获取对象时 ,context.getBean(Xxxx)),再创建对象;并且  每次getBean()都会创建一个新的对象。

--条件注解 Spring Boot
    可以让某一个Bean 在某些条件下 加入Ioc容器,其他情况下不加IoC容器。
    a.准备 bean
    b.增加条件Bean:给每个Bean设置条件 ,必须实现Condition接口
    c.根据条件,加入IoC容器        

--回顾给IoC加入Bean的方法

    注解 :全部在@Congiration配置中设置:    
        三层组件: 扫描器 + 三层注解
        非三层组件:  ① @Bean+返回值
                 ②@import
                ③FactoryBean(工厂Bean)

@import使用:    ①直接编写到@Import中,并且id值 是全类名
    ②自定义ImportSelector接口的实现类,通过selectimports方法实现(方法的返回值 就是要纳入IoC容器的Bean) 。 并且 告知程序 自己编写的实现类。 @Import({Orange.class,MyImportSelector.class})
    ③编写ImportBeanDefinitionRegistrar接口的实现类,重写方法
@Import({Orange.class,MyImportSelector.class,ImportBeanDefinitionRegistrar.class})


--FactoryBean(工厂Bean)

    1.准备bean。实现类和重写方法  2.注册bean。注册到@Bean中
        注意:需要通过&区分 获取的对象是哪一个 : 不加&,获取的是最内部真实的Apple;
        如果加了&,获取的 是FacotryBean

--IoC容器:初始化容器、..使用容器、销毁容器

---Bean的生命周期:创建(new ...)、初始化(赋初值)、  ....、销毁    (servlet)
方法一: Student.java
    适用于:@Bean+返回值方式
    init   destroy
xml:
    init-method="myInit"  destroy-method="myDestroy" 
注解:
      @Bean(value="stu",initMethod = "myInit",destroyMethod = "myDestroy") 

IoC容器在初始化时,会自动创建对象(构造方法) ->init ->.....->当容器关闭时 调用destroy...


方法二:
 三层注解 (功能性注解、MyIntToStringConverter.java):@Controller、@Service、@Repository、@Component 

-->三层注解(功能性注解【三层、功能性类】)
    三层组件: 扫描器 + 三层注解(4个)

    JAVA规范 :JSR250

    1.将响应组件 加入 @Component注解、 给初始化方法加@PostConstruct、给销毁方法加@PreDestroy
    @PostConstruct:相当于方法一的init
    @PreDestroy:相当于方法一的destroy

    如果要获取@Component注解中的bean,那么该Bean的名字就是@Component(value="xxx")的value值

方法三:两个接口
    接口:适用于三层组件(扫描器+三层组件)
    InitializingBean初始化
    DisposableBean 销毁

    初始化:只需要 实现InitializingBean中的afterPropertiesSet()方法
    销毁:实现DisposableBean 中的destroy()方法
    
问题:要在SPring IOC容器中操作:操作方式 对象:Bean+返回  ,三层组件

->如果是注解形式 , 随便写一个方法 ,然后加上相应注解即可
  如果是接口形式,必须 实现接口中规定的方法

方法四:(给容器中的所有Bean加初始化、销毁)一个接口
    接口:适用于三层组件  
    接口BeanPostProcessor:拦截了所有中容器的Bean


---自动装配  : 三层组件(4个注册+扫描器)

@Autowired
    Controller->Service->Dao
 三层组件
通过@Autowired从Ioc容器中 根据类型自动注入(没有调用setXxx()方法)
    -如果@Autowired在属性前标注,则不调用setXxx;如果标注在setXxx前面 ,则调用setXxx
    -不能放在方法的参数前
@Autowired
private Xxx xx;

public void aa()
{

}


@Autowired
public void setXxx(xx xx)
{
  
}
        
Bean+返回值:
    @Autowired  在方法的参数前(也可以省略)、方法前 (构造方法:特殊,如果只有一个有参构造方法,则构造方法前的@Autowired也可以省略)


public void setXxx(@Autowired xx xx)
{
  
}


之前:@Autowired 根据类型匹配:
        三层注入方式/@Bean+返回值
            1.如果有多个类型相同的,匹配哪个?
                    报错。 /默认值@primary
                2.能否根据名字匹配?
                    可以,结合 @Qualifier("stuDao2")使用。

            3.如果有0个类型相同,默认报错;可以修改成不注入(null),@Autowired(required=false)
            
    
自动注入方式一:    @Autowired (Spring) ,默认根据类型
自动注入方式二    @Resource(JSR250),默认根据名字 (如果 有名字,根据名字匹配;如果没有名字,先根据名字查找,如果没找到,再根据类型查找);也可以通过name或type属性 指定根据名字 或类型找。
自动注入方式一:    @Inject(JSR330),额外引入javax.inject.jar,默认根据类型匹配


---利用Spring底层组件进行开发 (三层组件)

    能够供我们使用的组件,都是Aware的子接口,即XxxxAware
    以ApplicationContextAware为例:实现步骤
        a.实现ApplicationContextAware,
        b.重写其中的方法,都包含了一个对象。只需要将该对象 赋值到属性中即可

    有什么用:例如ApplicationContextAware,可以通过该接口 获取到Ioc容器对象。
    执行时间:    如果在main()中new Ioc容器: 先执行ApplicationContextAware实现类中的方法,通过该方法传入IoC容器 供我们自己使用;  然后再将该容器通过new返回给用户

    BeanNameAware:


--环境切换:@Profile
    Spring:切换环境
    

激活方式一:
-Dspring.profiles.active=@Profile环境名
-Dspring.profiles.active=myApple

    数据库环境:
        @Profile
        127.0.0.1  scott  tiger  

        @Profile
        192.168...
激活方式二:
    硬编码

    坑:错误写法
                    ApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class) ;

        ConfigurableEnvironment environment = (ConfigurableEnvironment)context.getEnvironment();
        environment.setActiveProfiles("myBanana");

    其中AnnotationConfigApplicationContext中有一个refresh()操作:会将我们设置的一些参数还原
    没激活 |->进行激活 ->刷新 ->没激活


    流程调整:
        没激活->进行激活  |    ->刷新

什么时候设置 保存点|: 配置类的编写处
IoC容器在使用时必须refresh() ;如果是有参构造,内部已经刷新;如果无参构造,需要手工刷新。


---Spring重要组件BeanPostProcessor

    接口BeanPostProcessor:拦截了所有中容器的Bean,并且可以进行bean的初始化 、销毁
    创建->初始化->...-》销毁
    BeanPostProcessor
    BeanFactoryPostProcessor:拦截了容器
    BeanDefinitionRegistryPostProcessor:即将被加载之前(解析之前,称为BeanDefination对象之前)

    
BeanDefinitionRegistryPostProcessor(a)  -》加载bean->BeanFactoryPostProcessor(b)->实例化bean->BeanPostProcessor


同一个方法 在不同地方(类、接口)的出现时机问题:a继承b,因此a中必然包含b中的方法(记c ):虽然a和b中都有c,但是 因此c出现的时机不同, 则c的执行顺序也不同: 如果是在a中出现,则先执行;如果是在b中执行 则后执行

在同一个地方(类、接口),的不同方法的出现时机问题

监听器:

    可以监听事件 ,监听的对象必须是 ApplicationEvent自身或其子类/子接口
方式一:
    1必须实现ApplicationListener接口,
     

方式二:注解
    
(语法上 可以监听任意事件,但建议 ApplicationEvent自身或其子类/子接口)
Spring:要让SPring识别自己,必须加入IOc容器(Bean+返回值| 注解+扫描器)

自定被监听事件
    a.自定义类 实现ApplicationEvent接口(自定义事件)
    b.发布事件
     context.publishEvent(自定义事件);

Quartz  :定时异步任务

    任务:做什么事情....  StudentService 
    触发器:定义时间
    调度器:将任务、触发器 一一对应
实现步骤:(独立使用)
1.jar
2.
任务(Serivce..)  :Job

3.测试方法:Job 、 触发器  、调度器 

scheduler.shutdown():立刻关闭
scheduler.shutdown(false):shutdown()立刻关闭
scheduler.shutdown(true):将当前任务执行完毕后 再关闭

异步任务


触发器:CronScheduleBuilder

Cron表达式:
6-7个个参数,以空格隔开
秒    分    时    天(月)    月    天(周)     (年)
2,10     3-6    12/3       L                        2019-2022


--Spring整合Quartz

1.jar
    spring基础包(spring-context-support.jar/spring-tx.jar)+quartz


2.
a.将Job信息封装到一个 实体类中
b.spring配置文件


调度器  ->触发器(Job、执行时间)

    


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值