GroupID是项目组织唯一的标识符,比如我的项目叫test001,那么GroupID应该是com.lixiaoming.test001,域名.公司名.项目名
ArtifactID就是项目的唯一的标识符, 一般是项目名-xxx,比如test001-model
GroupID是项目组织唯一的标识符,实际对应JAVA的包的结构,是main目录里java的目录结构。
ArtifactID就是项目的唯一的标识符,实际对应项目的名称,就是项目根目录的名称。一般GroupID就是填com.info.test.这样子。
GroupId一般分为多个段,这里我只说两段,第一段为域,第二段为公司名称。域又分为org、com、cn等等许多,其中org为非营利组织,com为商业组织。举个apache公司的tomcat项目例子:这个项目的GroupId是org.apache,它的域是org(因为tomcat是非营利项目),公司名称是apache,ArtifactId是tomcat。
IOC
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.8.RELEASE</version>
</dependency>
@configuration
- 相当于配置开发的配置文件
- 导入组件方法一:在里面使用@Bean可以注入实例对象,对象名就是方法名或者bean中value,优先使用value中的对象名。导入第三方包就用这个。
- 导入组件方法二:在这个注解下加入@ComponentScan(“包名”),会扫描指定的包下的类看看是否注解了@Controller/@Service/@Repository/@Component,有则注入对象。也可以指定只注入或者不注入哪些组件。
- 导入组件方法三:import,id默认是组件的全类名。
- 也可以通过传入importSelector的实现类返回的全类名数组来导入组件
- 还可以通过传入ImportBeanDefinitionRegistrar的实现类,手动的向容器中添加组件
- 导入组件方法四:使用factoryBean
@Scope
指定多实例还是单实例
prototype多实例
singleton单实例(默认)
request同一次请求创建一个实例
session同一个session创建一个实例
@Lazy
懒加载,针对单实例来说的,只有在使用的时候才加载
@Conditional
按照条件注册bean,需要传入一个Condition接口的实现类,所以需要实现一个Condition接口重写里面的match方法
@Bean的初始化和销毁
方法一:
@Bean(initMethod=“方法名”,destroyMethod=“方法名”)
单实例Bean:对象创建完成并且赋值好就会调用initMethod。IOC容器关闭的时候调用destroyMethod
多实例Bean:使用的时候初始化,不会进行销毁
方法二:
让Bean实现InitializingBean,实现DisposableBean
方法三:
初始化:@PostConstruct
销毁:@PreDestroy,容器销毁Bean之前进行清理工作
BeanPostProcessor
后置处理器
postProcessBeforeInitialization,任何初始化调用(以上三种都可以)之前进行工作
postProcessAfterInitialization,初始化调用之后进行工作
原理:
try {
populateBean(beanName, mbd, instanceWrapper);//属性赋值
initializeBean(beanName, exposedObject, mbd);//初始化
}
initializeBean{
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName); //1
}
try {
invokeInitMethods(beanName, wrappedBean, mbd); //2调用初始化函数
}
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName); //3
}
}
XXXAware
向组件中注入IOC容器:
实现ApplicationContextAware,重写setApplicationContext方法来设置applicationContext容器即可,底层就会有对应的后置处理器进行处理。
@Value
使用value赋值:
- 基本数值
- 可以写SpEL;#{}
- 可以写${};取出配置文件中的【properties】中的值
@Data
public class Person {
@Value("张三")
private String name;
@Value("#{20-2}")
private Integer age;
@Value("${person.nickName:如花}")//这个从配置文件中加载,如果没有配置默认是“如花”
private String nickName;
}
@PropertySource
@PropertySource(value = {"classpath:/person.properties"})//加载类路径下的配置文件
@Configuration
@Autowired
自动装配:可以标注在属性,方法,构造器,形参上,会给参数自动装配上。如果@Bean标注的方法中有参数,也会从容器中获取。
默认按照类型装配,如果有多个相同类型的对象,则按照名字装配,可以使用@Qualifier明确指定装配哪一个;也可以在注入容器时给组件加上@Primary注解,说明这是一个首选的组件,就算有多个也会优先注入这个组件。
默认是一定要装配上,容器中没有可以装配的对象就会报错。但是可以指定不一定要装配:
boolean required() default true;//设置为false
自动装配除了@Autowired外,还有@Resource和@Inject(这两个都是java规范里面的,@Autowired是Spring规范中的),@Resource不能支持@Primary(Spring规范中的,搭配@Autowired使用的)和不能设置required。@Inject功能和@Autowired一样,但是要导包才能使用,不能设置required。
如果要使用Spring底层的一些组件,只要实现XXXAware接口。底层就会有对应的后置处理器进行处理。
public class Student implements ApplicationContextAware, BeanNameAware, EmbeddedValueResolverAware {
private ApplicationContext applicationContext;
//获取IOC容器
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
//获取bean的id
@Override
public void setBeanName(String name) {
System.out.println("BeanName is " + name);
}
//字符串解析器
@Override
public void setEmbeddedValueResolver(StringValueResolver resolver) {
String value = resolver.resolveStringValue("我是${os.name},今年#{20-2}岁");
System.out.println(value);
}
}
//BeanName is student
//我是Windows 10,今年18岁
@Profile
根据环境(默认、测试、生产、开发)来指定哪些Bean可以加到容器中
设置环境方式:
-
-Dspring.profiles.active=***
-
/** * Profile * 设置环境 */ @Test void test2() { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); //context.getEnvironment().setActiveProfiles("test","dev"); context.getEnvironment().setActiveProfiles("test"); context.register(MyConfig.class); context.refresh(); }
AOP
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>5.2.8.RELEASE</version>
</dependency>
使用
@EnableAspectJAutoProxy
@EnableAspectJAutoProxy
@Configuration
@ComponentScan("com.ysj.study.aop")
public class AOPConfig {
@Bean
public LogAspects logAspects() {
return new LogAspects();
}
@Bean
public MathCalculator mathCalculator() {
return new MathCalculator();
}
}
@Aspect
@Aspect
public class LogAspects {
@Pointcut("execution(public int com.ysj.study.aop.MathCalculator.*(..))")//MathCalculator类的任意方法,参照官方文档
public void pointCut(){}
@Before("pointCut()")
public void logBefore(JoinPoint jp) {//JoinPoint要写在参数的最前面
System.out.println("方法执行前...Before...params{"+Arrays.toString(jp.getArgs())+"}");
}
@After("com.ysj.study.aop.LogAspects.pointCut()")//外部类就是这样写
public void logAfter() {
System.out.println("方法执行完成...After");
}
@AfterReturning(value = "pointCut()",returning = "result")
public void logReturn(Object result) {
System.out.println("方法正常返回...AfterReturning...result{"+result+"}");
}
@AfterThrowing("pointCut()")
public void logThrowing() {
System.out.println("方法异常...AfterThrowing");
}
}
原理
凡是@EnableXXX就看有没有给容器中注册组件,给容器中注册了什么组件,这个组件什么时候工作,这个组件有什么功能。
@EnableAspectJAutoProxy作用:
- @EnableAspectJAutoProxy
- @Import(AspectJAutoProxyRegistrar.class)
- class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar
- 如果registry中有没有id为org.springframework.aop.config.internalAutoProxyCreator组件,如果没有这个组件就注册这个组件,这个组件是AnnotationAwareAspectJAutoProxyCreator,id为internalAutoProxyCreator。
AnnotationAwareAspectJAutoProxyCreator作用:
翻译:注解装配模式的切面自动代理创建器
- 继承树:AnnotationAwareAspectJAutoProxyCreator->
- AspectJAwareAdvisorAutoProxyCreator->
- AbstractAdvisorAutoProxyCreator->
- AbstractAutoProxyCreator->
- implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware,实现了一个后置处理器(在Bean初始化前后做一些事情),还要自动注入BeanFactory
倒序分析:
-
AbstractAutoProxyCreator.postProcessBeforeInstantiation
AbstractAutoProxyCreator.postProcessAfterInitialization
AbstractAutoProxyCreator.setBeanFactory
-
AbstractAdvisorAutoProxyCreator.setBeanFactory–>initBeanFactory
-
AnnotationAwareAspectJAutoProxyCreator.initBeanFactory
创建和注册流程:
-
传入主配置类,创建IOC容器
-
注册配置类,refresh()刷新容器
-
registerBeanPostProcessors(beanFactory);注册bean的后置处理器,来拦截Bean的创建
4. beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);获取IOC容器中已经定义了(解析配置类的时候获取的)的需要创建对象的BeanPostProcessor
2. 给容器中加入BeanPostProcessorChecker的BeanPostProcessor
3. 优先注册实现了PriorityOrdered的BeanPostProcessor
4. 再注册实现了Ordered的BeanPostProcessor
5. 其次再注册没有实现优先级接口的BeanPostProcessor
6. 注册BeanPostProcessor,实际上就是创建BeanPostProcessor对象,保存在容器中- 以创建internalAutoProxyCreator的BeanPostProcessor【AnnotationAwareAspectJAutoProxyCreator】为例
- 创建Bean实例
- populateBean,给Bean的各种属性赋值
- initializeBean,初始化Bean
- invokeAwareMethods:处理Aware接口的方法回调
- applyBeanPostProcessorsBeforeInitialization:获取所有的BeanPostProcessor执行postProcessBeforeInitialization方法
- invokeInitMethods:执行自定义的初始化方法
- applyBeanPostProcessorsAfterInitialization:获取所有的BeanPostProcessor执行postProcessAfterInitialization方法
- BeanPostProcessor【AnnotationAwareAspectJAutoProxyCreator】创建成功
- 在BeanFactory中添加BeanPostProcessor
执行流程:
- 在Bean创建对象之前会调用所有的InstantiationAwareBeanPostProcessor的postProcessBeforeInstantiation()方法。而InstantiationAwareBeanPostProcessor<-SmartInstantiationAwareBeanPostProcessor<-…<-AnnotationAwareAspectJAutoProxyCreator
- 判断当前bean是不是在advisedBeans(保存了所有增强的bean)中
- 判断当前bean是不是Advice、Pointcut、Advisor、AopInfrastructureBean的子类或者子接口,或者判断有没有@Aspect注解
- 判断是不是需要跳过
- 拿到所有候选增强器(增强器就是切面里面的通知方法)
扩展
/**
* 1、BeanFactoryPostProcessor:beanFactory的后置处理器。
* 执行时机:在beanFactory标准初始化之后调用,所有bean的定义已经保存加载到beanFactory中,但是bean的实例还未创建。
* 2、BeanDefinitionRegistryPostProcessor:
* 执行时机:在所有bean定义信息将要被加载,bean的实例还未创建。(在BeanFactoryPostProcessor之前执行)
* 3、ApplicationListener:监听容器中发布的事件,事件驱动模型开发。
* 步骤:
* 1、写一个监听器来监听事件(ApplicationEvent及其子类)
* 或者@EventListener({ApplicationEvent.class}):例如UserService
* 原理:
* 使用EventListenerMethodProcessor解析,EventListenerMethodProcessor实现SmartInitializingSingleton。
* refresh()->finishBeanFactoryInitialization(beanFactory)->beanFactory.preInstantiateSingletons()->首先实例化所有
* 单实例bean,然后在所有单实例bean中找到实现了SmartInitializingSingleton的实例调用afterSingletonsInstantiated()方法
* 进行解析。
* 2、把监听器加入到容器中
* 3、只要容器中有相关事件的发布,我们就能监听这个事件
* ContextRefreshedEvent:容器刷新完成(所有bean创建完成)会发布这个事件。
* ContextClosedEvent:关闭容器会发布这个事件。
* 4、发布一个事件
*/
Spring容器创建
this();
register(componentClasses);
都是做的预处理和解析工作
refresh();
容器的创建和刷新工作(重要内容)
-
prepareRefresh();刷新前的预处理
- initPropertySources();初始化一些属性配置,空方法,自定义个性化的属性设置。
- getEnvironment().validateRequiredProperties();属性校验,验证必须的属性。
- earlyApplicationListeners容器刷新之前就注册了的本地监听器
- applicationListeners静态指定的监听器
- earlyApplicationEvents = new LinkedHashSet<>();保存容器中一些早期的事件,一旦多播器可用就发布
-
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();获取beanFactory
-
refreshBeanFactory();刷新beanFactory
beanFactory在AnnotationConfigApplicationContext容器创建的时候就已经生成
继承树:AnnotationConfigApplicationContext->GenericApplicationContext->AbstractApplicationContext
public GenericApplicationContext() {this.beanFactory = new DefaultListableBeanFactory();}
解释:创建子类对象的时候如果没有指定调用父类的带参构造函数,会默认调用父类的无参构造器。
- 仅仅设置了beanFactory的序列号ID
- return getBeanFactory();
- return this.beanFactory;仅仅返回GenericApplicationContext创建好的DefaultListableBeanFactory对象
-
-
prepareBeanFactory(beanFactory);beanFactory的预准备工作(对beanFactory进行一些设置,和前面prepareRefresh();(刷新前的预处理,对AnnotationConfigApplicationContext做一些设置)一样)
- 设置类加载器、标准的Bean表达式解析器等
- 添加BeanPostProcessor【ApplicationContextAwareProcessor】,目的是为了处理实现了ApplicationContextAware接口的类
- ignoreDependencyInterface:设置忽略自动装配接口【EnvironmentAware、EmbeddedValueResolverAware…】,目的是为了即使实现了这些自动装配的接口也不会起作用,因为容器通过其他方式解决了注入属性。
- registerResolvableDependency:注册可以解析的自动装配,我们能直接在任何组件中自动注入:BeanFactory、ResourceLoader、ApplicationEventPublisher、ApplicationContext
- 添加BeanPostProcessor【ApplicationListenerDetector】
- 添加编译时的AspectJ
- 给BeanFactory注册一些可用的组件:
- environment【ConfigurableEnvironment】
- systemProperties【Map<String, Object>】
- systemEnvironment【Map<String, Object>】
-
postProcessBeanFactory(beanFactory);BeanFactory准备工作完成后进行的后置处理工作
- 空方法。子类通过重写这个方法来在BeanFactory创建并预准备完成之后做进一步的设置。
-
invokeBeanFactoryPostProcessors(beanFactory);执行BeanFactoryPostProcessor
BeanFactoryPostProcessor:BeanFactory的后置处理器,在BeanFactory标准初始化(前面的4个步骤)之后执行
BeanFactoryPostProcessor的两个主要接口:BeanFactoryPostProcessor、BeanDefinitionRegistryPostProcessor
-
执行BeanFactoryPostProcessor的方法
先执行BeanDefinitionRegistryPostProcessor方法
- 获取所有的BeanDefinitionRegistryPostProcessor
- 先执行实现了PriorityOrdered优先级接口的BeanDefinitionRegistryPostProcessor
- invokeBeanDefinitionRegistryPostProcessors->
- postProcessor.postProcessBeanDefinitionRegistry(registry)
- 再执行实现了Ordered顺序接口的BeanDefinitionRegistryPostProcessor
- invokeBeanDefinitionRegistryPostProcessors->
- postProcessor.postProcessBeanDefinitionRegistry(registry)
- 最后执行没有实现PriorityOrdered优先级接口和Ordered顺序接口的BeanDefinitionRegistryPostProcessor
- invokeBeanDefinitionRegistryPostProcessors->
- postProcessor.postProcessBeanDefinitionRegistry(registry)
再执行BeanFactoryPostProcessor方法
- 获取所有的BeanFactoryPostProcessor
- 先执行实现了PriorityOrdered优先级接口的BeanFactoryPostProcessor
- invokeBeanFactoryPostProcessors->
- postProcessor.postProcessBeanFactory(beanFactory)
- 再执行实现了Ordered顺序接口的BeanFactoryPostProcessor
- invokeBeanFactoryPostProcessors->
- postProcessor.postProcessBeanFactory(beanFactory)
- 最后执行没有实现PriorityOrdered优先级接口和Ordered顺序接口的BeanFactoryPostProcessor
- invokeBeanFactoryPostProcessors->
- postProcessor.postProcessBeanFactory(beanFactory)
-
-
registerBeanPostProcessors(beanFactory);注册BeanPostProcessor(Bean的后置处理器:拦截Bean的创建过程)
不同的BeanPostProcessor在Bean创建前后执行时机是不一样的:
BeanPostProcessor、
DestructionAwareBeanPostProcessor【Bean销毁之前回调】、
InstantiationAwareBeanPostProcessor【Bean实例创建之前和实例创建之后属性赋值之前就会调用,作用:调用Before方法可以直接返回一个实例对象】、
SmartInstantiationAwareBeanPostProcessor(InstantiationAwareBeanPostProcessor接口的扩展,增加了一个预测Bean处理后的类型的回调)、
MergedBeanDefinitionPostProcessor【合并BeanDefinition时候回调,放在internalPostProcessors中,在Bean创建实例之后会调用】
- 获取所有的BeanPostProcessor名字,根据名字获取所有的BeanPostProcessor实例,BeanPostProcessor都默认可以通过PriorityOrdered、Ordered接口来指定优先级。
- 对不同优先级的BeanPostProcessor排序并进行注册(加到BeanFactory中),MergedBeanDefinitionPostProcessor是最最最后注册的,在注册没有实现优先级接口的BeanPostProcessor之后注册。然后在添加一个ApplicationListenerDetector(监听器探查器:如果Bean是一个ApplicationListener,会加到容器的applicationListeners中)
-
initMessageSource();初始化MessageSource组件(做国际化功能,消息绑定,消息解析)
- 获取beanFactory
- 看beanFactory中有没有包含id为messageSource,类型为MessageSource的组件
- 如果有就赋给messageSource属性;如果没有就创建一个DelegatingMessageSource类型的MessageSource的组件。
- 把创建好的MessageSource注册到容器中,以后获取国际化配置文件中的值的时候可以自动注入MessageSource并调用它的方法getMessage()(MessageSource:取出国际化配置文件中的某个key值,能按照区域信息获取)
-
initApplicationEventMulticaster();初始化事件多播器(派发器)
- 获取beanFactory
- 从beanFactory中获取id为applicationEventMulticaster的ApplicationEventMulticaster组件
- 如果获取不到,就创建SimpleApplicationEventMulticaster,并注册到beanFactory中,以后要使用事件派发器可以自动注入
-
onRefresh();
- 空方法。子类可以在初始化单实例之前实例化一些特殊的bean
-
registerListeners();将项目里面所有的ApplicationListener注册进来
- 获得容器中的所有ApplicationListener加到派发器中
- 从beanFactory中获取并注册所有的ApplicationListener加到派发器中
- 派发保存在容器中一些早期的事件(参见1.prepareRefresh();)
-
finishBeanFactoryInitialization(beanFactory);初始化所有剩下的单实例Bean
- 在beanFactory中添加ConversionService(如果有的话,类型转换有关的)、EmbeddedValueResolver(值解析器有关的)、LoadTimeWeaverAware(AspectJ有关的,如果有的话)
- beanFactory.setTempClassLoader(null);停用零时的类加载器进行匹配
- beanFactory.freezeConfiguration();允许缓存所有Bean的元数据,并且不能更改
- beanFactory.preInstantiateSingletons();初始化所有剩下的单实例Bean
- 获取所有的Bean定义信息RootBeanDefinition
- 判断Bean不是抽象,是单实例,不是懒加载
- 判断是不是FactoryBean(实现了FactoryBean的接口),是的话利用工厂创建对象
- 没有实现FactoryBean的话,利用getBean(beanName);创建对象
- doGetBean(name, null, null, false);->
- getSingleton(beanName);尝试从单实例缓存(singletonObjects:一级缓存)中获取Bean。如果缓存中没有就开始创建
- markBeanAsCreated(beanName);标记当前Bean已经被创建,防止多线程同时创建。
- mbd = getMergedLocalBeanDefinition(beanName);获取bean的定义信息
- mbd.getDependsOn();获取bean所依赖的其他bean。如果有依赖的bean还是按照getBean(beanName);的方式将依赖的bean创建出来
- 如果bean是单实例的,就开始创建调用getSingleton()创建bean->createBean(beanName, mbd, args);
- Object bean = resolveBeforeInstantiation(beanName, mbdToUse);让BeanPostProcessor【InstantiationAwareBeanPostProcessors】提前拦截bean,触发postProcessBeforeInstantiation(),如果postProcessBeforeInstantiation返回不是null则继续触发【所有BeanPostProcessor】的postProcessAfterInitialization()返回一个代理对象。
- 如果没有返回一个代理对象,那么执行doCreateBean(beanName, mbdToUse, args);
- 创建对象:createBeanInstance(beanName, mbd, args);利用工厂方法或者对象的构造器创建实例。。。如果bean是在配置类里面利用@Bean注解创建,那么会调用instantiateUsingFactoryMethod(beanName, mbd, args);这个方法创建对象。
- applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);调用【MergedBeanDefinitionPostProcessors】的postProcessMergedBeanDefinition(),对@Autowired进行扫描和解析。
- 将其加入singletonFactories
- 属性赋值:populateBean(beanName, mbd, instanceWrapper);
- 赋值之前:执行【InstantiationAwareBeanPostProcessor】的postProcessAfterInstantiation()方法
- 赋值之前:执行【InstantiationAwareBeanPostProcessor】的postProcessProperties()方法
- 赋值之前:执行【InstantiationAwareBeanPostProcessor】的postProcessPropertyValues()方法
- 赋值:applyPropertyValues(beanName, mbd, bw, pvs);利用Bean属性的值,为属性利用setter方法等进行赋值
- 初始化Bean:initializeBean(beanName, exposedObject, mbd);
- invokeAwareMethods(beanName, bean);执行xxxAware方法进行其他属性赋值
- applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);执行所有【BeanPostProcessor】的postProcessBeforeInitialization()(初始化之前)方法
- 执行初始化:invokeInitMethods(beanName, wrappedBean, mbd);如果实现了InitializingBean接口或者如果自定义了初始化方法的话
- applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);执行所有【BeanPostProcessor】的postProcessAfterInitialization()(初始化之后)方法
- registerDisposableBeanIfNecessary(beanName, bean, mbd);注册销毁方法
- 如果实现了DisposableBean、AutoCloseable
- addSingleton(beanName, singletonObject);将创建好的bean加入到singletonObjects中
- doGetBean(name, null, null, false);->
- 创建完所有实例后检查所有实例有没有实现SmartInitializingSingleton接口的,如果有就调用这个接口的afterSingletonsInstantiated()方法
-
finishRefresh();完成BeanFactory的初始化创建工作,IOC容器创建完成
- initLifecycleProcessor();初始化生命周期处理器,如果容器中有id为lifecycleProcessor的LifecycleProcessor组件,就将其赋给lifecycleProcessor属性。如果没有就创建一个默认的类型为DefaultLifecycleProcessor生命周期处理器,将其赋给lifecycleProcessor属性,并将其注册进单实例缓存中。
- getLifecycleProcessor().onRefresh();首先拿到lifecycleProcessor,回调onRefresh()方法
- publishEvent(new ContextRefreshedEvent(this));发布容器刷新完成的事件
- LiveBeansView.registerApplicationContext(this);
总结
- Spring容器在启动的时候,先会保存所有注册进来的Bean的定义信息
- xml
- 注解
- Spring会在合适的时机创建这些Bean
- 用到这些Bean的时候,会利用getBean()创建Bean,创建好之后会保存在单例缓存中
- 统一创建所有剩下的Bean,finishBeanFactoryInitialization(beanFactory)
- 后置处理器
- 每一个Bean创建完成,都会使用各种后置处理器进行处理来增强Bean
- AutowiredAnnotationBeanPostProcessor:处理Autowired注解的
- AnnotationAwareAspectJAutoProxyCreator:处理动态代理(AOP)的
- 。。。
- 事件驱动模型
- ApplicationListener:事件监听
- ApplicationEventMulticaster:事件派发