Spring高级
来源:互联网 发布:windows字体大小设置 编辑:程序博客网 时间:2024/05/26 12:57
1、Spring Aware
Spring Aware目的是为了让Bean获得Spring容器的服务,因为ApplicationContext接口集成了MessageSOurce接口、ApplicationEventPublisher接口和ResourceLoader接口,所以Bean继承ApplicationContextAware就可以获得spring容器的所有服务
AwareService
实现BeanNameAware, ResourceLoaderAware接口,这样就获得Bean名称和资源加载的服务
@Servicepublic class AwareService implements BeanNameAware, ResourceLoaderAware { private String beanName; private ResourceLoader loader; @Override public void setResourceLoader(ResourceLoader resourceLoader) { this.loader = resourceLoader; } @Override public void setBeanName(String name) { this.beanName = name; } public void outputResult() { System.out.println("Bean的名称为" + beanName); Resource resource = loader.getResource("classpath:spring/aware/test.txt"); try { System.out.println("ResourceLoader加载的文件内容为:" + resource.getInputStream().toString()); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } }}
配置类
@Configuration@ComponentScan("spring.aware")public class AwareConfig {}
运行类
public class Main { public static void main(String[] args) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AwareConfig.class); AwareService awareService = context.getBean(AwareService.class); awareService.outputResult(); context.close(); }}
2、多线程
Spring通过任务执行器(TaskExecutor)来实现多线程和并发编程,使用ThreadPoolTaskExecutor 来实现基于线程池的TaskExecutor。我们需要在配置类通过@EnableAsync开启对异步任务的支持,通过在实际执行的Bean的方法使用@Async注解来声明一个异步任务
配置类
@Configuration@ComponentScan("spring.executor")@EnableAsync //开启异步public class TaskExectorConfig implements AsyncConfigurer{ @Override public Executor getAsyncExecutor() { ThreadPoolTaskExecutor taskExecutor=new ThreadPoolTaskExecutor(); taskExecutor.setCorePoolSize(5);//线程池维护线程的最少数量 taskExecutor.setMaxPoolSize(10);//线程池维护线程的最大数量 taskExecutor.setQueueCapacity(25);//线程池所使用的缓冲队列 taskExecutor.initialize(); return taskExecutor;//返回基于线程池TaskExecutor } @Override public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() { // TODO Auto-generated method stub return null; }}
任务执行类
@Servicepublic class AsyncTaskService { @Async //声明一个异步任务 public void executeAsyncTask(Integer i){ System.out.println("执行异步任务:"+i); } @Async public void executeAsyncTaskPlus(Integer i){ System.out.println("执行异步任务+1:"+(i+1)); }}
运行
public class Main { public static void main(String[] args) { AnnotationConfigApplicationContext context= new AnnotationConfigApplicationContext(TaskExectorConfig.class); AsyncTaskService asyncTaskService=context.getBean(AsyncTaskService.class); for(int i=0;i<10;i++){ asyncTaskService.executeAsyncTask(i); asyncTaskService.executeAsyncTaskPlus(i); } context.close(); }}
并发执行的运行结果
3、计划任务
Spring通过@Scheduled支持多种类型的计划任务,包括cron、fixDelay、fixRate等
计划任务执行类
@Servicepublic class ScheduledTaskService { private static final SimpleDateFormat dateFormat= new SimpleDateFormat("HH:mm:ss"); @Scheduled(fixedRate=2000) //fixedRate属性每隔固定时间执行 public void reportCurrentTime(){ System.out.println("每隔2秒执行一次"+dateFormat.format(new Date())); } @Scheduled(cron="0 28 11 ? * *") //cron属性可按照指定时间执行,这里指每天11点28分执行,cron是Linux系统的定时任务 public void fixTimeExecution(){ System.out.println("在指定时间 "+dateFormat.format(new Date())+"执行"); }}
配置类
@Configuration@ComponentScan("spring.schedule")@EnableScheduling //开启对计划任务的支持public class TaskSchedulerConfig {}
运行
public class Main { public static void main(String[] args) { AnnotationConfigApplicationContext context= new AnnotationConfigApplicationContext(TaskSchedulerConfig.class); } }
4、条件注解@Conditional
@Conditional根据满足某一个特定条件创建一个特定的Bean,比如只有某个Bean被创建后才会创建另一个Bean,总而言之,就是根据特定条件来控制Bean的创建行为。下面以不同的操作系统作为条件,通过实现Condition接口,并重写器matches方法来构建判断条件
判断条件定义
(1)判断windows
public class WindowCondition implements Condition{ @Override public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { // TODO Auto-generated method stub return context.getEnvironment().getProperty("os.name").contains("Windows"); }}
(2)判断Linux
public class LinuxCondition implements Condition{ @Override public boolean matches(ConditionContext context, AnnotatedTypeMetadata arg1) { // TODO Auto-generated method stub return context.getEnvironment().getProperty("os.name").contains("Linux"); }}
不同系统下的Bean的类
(1)接口
public interface ListService { public String showListCmd();}
(2)windows下所要创建的Bean类
public class WindowListService implements ListService{ @Override public String showListCmd() { // TODO Auto-generated method stub return "dir"; }}
(3)linux下所要创建的Bean类
public class LinuxListService implements ListService{ @Override public String showListCmd() { // TODO Auto-generated method stub return "ls"; }}
配置类
@Configurationpublic class ConditionConfig { @Bean @Conditional(WindowCondition.class) //符合Windows条件实例化windowsListService public ListService windowsListService(){ return new WindowListService(); } @Bean @Conditional(LinuxCondition.class) //符合Linux条件实例化linuxListService public ListService linuxListService(){ return new LinuxListService(); }}
运行
public class Main { public static void main(String[] args) { AnnotationConfigApplicationContext context= new AnnotationConfigApplicationContext(ConditionConfig.class); ListService listService = context.getBean(ListService.class); System.out.println(context.getEnvironment().getProperty("os.name") +"系统下的列表命令为"+listService.showListCmd()); }}
组合注解与元注解
元注解是可以注解到别的注解上的注解,被注解的注解称为组合注解,下面将两个元注解组合一个组合注解,也就只需一个注解就可以表示两个注解
组合注解
@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)@Documented@Configuration //组合@Configuration元注解@ComponentScan //组合@ComponentScan元注解public @interface WiselyConfiguration { String value();//覆盖value参数}
演示服务bean
@Servicepublic class DemoService { public void outputService(){ System.out.println("从组合注解配置照样获得bean"); }}
新配置类
@WiselyConfiguration("spring.annotation")//使用@WiselyConfiguration组合注解代替@Configuration @ComponentScanpublic class DemoConfig {}
运行
public class Main { public static void main(String[] args) { AnnotationConfigApplicationContext context= new AnnotationConfigApplicationContext(DemoConfig.class); DemoService demoService=context.getBean(DemoService.class); demoService.outputService(); context.close(); }}
6、@Enable*注解的工作原理
观察下这些@Enable*注解的源码,可以发现所有的注解都有一个@Import注解。
@Import注解是用来导入配置类的,这也就是说这些自动开启的实现其实是导入了一些自动配置的Bean。
这些导入配置方式主要分为以下三种类型。
第一类:直接导入配置类
@Target({ElementType.TYPE})@Retention(RetentionPolicy.RUNTIME)@Import({SchedulingConfiguration.class})@Documentedpublic @interface EnableScheduling {}
直接导入配置类SchedulingConfiguration,这个类注解了@Configuration,且注册了一个scheduledAnnotationProcessor的Bean,源码如下:
@Configuration@Role(BeanDefinition.ROLE_INFRASTRUCTURE)public class SchedulingConfiguration { @Bean(name = TaskManagementConfigUtils.SCHEDULED_ANNOTATION_PROCESSOR_BEAN_NAME) @Role(BeanDefinition.ROLE_INFRASTRUCTURE) public ScheduledAnnotationBeanPostProcessor scheduledAnnotationProcessor() { return new ScheduledAnnotationBeanPostProcessor(); }}
第二类:依据条件选择配置类
@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)@Documented@Import(AsyncConfigurationSelector.class)public @interface EnableAsync { Class<? extends Annotation> annotation() default Annotation.class; boolean proxyTargetClass() default false; AdviceMode mode() default AdviceMode.PROXY; int order() default Ordered.LOWEST_PRECEDENCE;}
AsyncConfigurationSelector通过条件来选择需要导入的配置类,
AsyncConfigurationSelector的根接口为ImportSelector,这个接口需要重写selectImports方法,在此方法内进行事先条件判断。
在下面的源码中,若adviceMode为PORXY,则返回ProxyAsyncConfiguration这个配置类。
若activeMode为ASPECTJ,则返回AspectJAsyncConfiguration配置类。
源码如下:
public class AsyncConfigurationSelector extends AdviceModeImportSelector<EnableAsync> { private static final String ASYNC_EXECUTION_ASPECT_CONFIGURATION_CLASS_NAME = "org.springframework.scheduling.aspectj.AspectJAsyncConfiguration"; @Override public String[] selectImports(AdviceMode adviceMode) { switch (adviceMode) { case PROXY: return new String[] { ProxyAsyncConfiguration.class.getName() }; case ASPECTJ: return new String[] { ASYNC_EXECUTION_ASPECT_CONFIGURATION_CLASS_NAME }; default: return null; } }}
第三类:动态注册Bean
@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)@Documented@Import(AspectJAutoProxyRegistrar.class)public @interface EnableAspectJAutoProxy { boolean proxyTargetClass() default false;}
AspectJAutoProxyRegistrar 事先了ImportBeanDefinitionRegistrar接口,ImportBeanDefinitionRegistrar的作用是在运行时自动添加Bean到已有的配置类,通过重写方法:
@Override public void registerBeanDefinitions( AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry)
其中,AnnotationMetadata参数用来获得当前配置类上的注解;
BeanDefinittionRegistry参数用来注册Bean。
源码如下:
class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar { @Override public void registerBeanDefinitions( AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry); AnnotationAttributes enableAJAutoProxy = AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class); if (enableAJAutoProxy.getBoolean("proxyTargetClass")) { AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry); } }}
- Spring高级
- Spring框架高级编程
- Spring Bean 高级装配
- spring高级功能
- Spring容器高级主题
- spring(3)高级装配
- Spring容器高级主题
- Spring MVC 高级配置
- 【Spring 核心】高级装配
- Spring MVC高级配置
- Spring 高级装配
- Spring高级事务管理
- Spring 高级装配
- 【Spring】高级装配
- 【Spring】高级装配
- Spring容器高级主题
- Spring高级装配
- Spring之高级装配
- Maven之setting.xml配置文件详解
- 第三章 获取请求参数值-跟赵大笨笨学SpringMVC
- 链表逆置(给出一个链表和数k)
- 让世界充满AI—时代的开拓者(程序员)
- Mybatis的初次使用及配置文件
- Spring高级
- sklearn 流水线(pipeline)使用
- Android:installLocation的用法
- Centos 删除软件
- C++实训心得
- Node.js升级版本
- 正则表达式匹配url
- Android NDK编译librtmp 三重奏 -- (二)编译polarssl
- HDU 5876 Disharmony Trees(离散化 树状数组)