美文网首页
第3章 Spring 高级话题

第3章 Spring 高级话题

作者: 意大利大炮 | 来源:发表于2018-12-05 10:59 被阅读0次

    Spring Aware

    • Spring的依赖注入最大的亮点就是所有的Bean对Spring容器的存在是没有意识的,所以Bean之间的耦合度很低
    • 但是在项目中,我们可能会需要用到Spring容器本身的功能资源,这就需要我们的Bean能够意识到Spring的存在,这就是Spring Aware(Spring可意识到)
    • 注:如果使用了Spring Aware,我们的Bean将于Spring框架耦合
      Spring提供的Aware接口如表格所示:
    接口 用途/说明
    BeanNameAware 可以在Bean中得到它在IOC容器中的Bean的实例的名字
    BeanFactoryAware 可以在Bean中得到Bean所在的IOC容器,从而直接在Bean中使用IOC容器的服务
    ApplicationContextAware 可以在Bean中得到Bean所在的应用上下文,从而直接在Bean中使用上下文的服务
    MessageSourceAware 在Bean中可以得到消息源
    ApplicationEventPublisherAware 在bean中可以得到应用上下文的事件发布器,从而可以在Bean中发布应用上下文的事件
    ResourceLoaderAware 在Bean中可以得到ResourceLoader,从而在bean中使用ResourceLoader加载外部对应的Resource资源
    • 使用Aware接口时,首先要创建一个继承了Aware接口的bean,并实现其方法
      例:
    @Service
    public class AwareService implements ResourceLoaderAware{
      @Override
      public void setResourceLoader(ResourceLoader resourceLoader) {
        this.loader = resourceLoader;
      }
    }
    

    多线程

    • Spring通过任务执行器(TaskExecutor)来实现多线程和并发编程
    • 使用ThreadPoolTaskExecutor可实现一个基于县城池的TaskExecutor

    下面是一个例子

    • 首先实现一个实现了AsyncConfigurer 接口的配置类,并重写getAsyncExecutor()方法
    @Configuration
    @ComponentScan("com.example.demo")
    @EnableAsync                            //  使用注解开启异步任务支持
    public class TaskExecutorConfig implements AsyncConfigurer {
    
        @Override
        public Executor getAsyncExecutor() {
            ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
            taskExecutor.setCorePoolSize(5);
            taskExecutor.setMaxPoolSize(10);
            taskExecutor.setQueueCapacity(25);
            taskExecutor.initialize();
            return taskExecutor;
        }
    
        @Override
        public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
            return null;
        }
    }
    
    • 创建异步service类,通过@Async注解表明异步方法
    @Service
    public class AsyncTaskService {
    
        @Async
        public void executeAsyncTask(Integer i) {
            System.out.println("执行异步任务1:" + i);
        }
    
        @Async
        public void executeAsyncTaskPlus(Integer i) {
            System.out.println("执行异步任务2:" + i);
        }
    }
    
    • 运行
    public class Main {
        public static void main(String args[]) {
            AnnotationConfigApplicationContext context =
                    new AnnotationConfigApplicationContext(TaskExecutorConfig.class);
    
            AsyncTaskService asyncTaskService = context.getBean(AsyncTaskService.class);
            // 循环调用
            for (int i = 0; i < 10; i++) {
                asyncTaskService.executeAsyncTask(i);
                asyncTaskService.executeAsyncTaskPlus(i);
            }
            // 关闭
            context.close();
        }
    }
    

    计划任务(定时任务)

    • 通过@@EnableScheduling 注解支持多种类型的计划任务,包含cron、fixDelay、fixRate等
    @Configuration
    @ComponentScan("com.example.demo.scheduled_test.service")
    @EnableScheduling               // 开启定时任务的支持
    public class TaskSchedulerConfig {
    }
    
    • 通过@Scheduled生命计划任务方法,使用fixedRate属性每隔指定时间执行,使用cron属性可按照指定时间执行
    @Service
    public class ScheduledTaskService {
    
        @Scheduled(fixedDelay = 5000)
        public void reportCurrentTime() {
            System.out.println("每个五秒钟执行一次 ");
        }
        /**
         * 在每天的11点28分执行
         */
        @Scheduled(cron = "0 28 11 ? * *")
        public void fixTimeExecution() {
            System.out.println("在指定时间执行");
        }
    }
    
    • 运行
    public class Main {
        public static void main(String args[]) {
            AnnotationConfigApplicationContext context =
                    new AnnotationConfigApplicationContext(TaskSchedulerConfig.class);
    
        }
    }
    

    条件注解@Conditional

    • 基于条件创建Bean
    • 满足某个条件创建一个特定的Bean
      例子:windows环境下生成windowsBean,linux下生成linuxBean
    • 创建条件定义
      windows定义
    public class WindowsCondition implements Condition {
    
        @Override
        public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
            return conditionContext.getEnvironment().getProperty("os.name").contains("Windows");
        }
    }
    
    

    linux定义

    public class LinuxCondition implements Condition {
    
        @Override
        public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
            return conditionContext.getEnvironment().getProperty("os.name").contains("Linux");
        }
    }
    
    • 不同系统下面的Bean
      接口
    public interface ListService {
        String showListCmd();
    }
    

    windows下要创建的Bean

    public class WindowsListService implements ListService {
        @Override
        public String showListCmd() {
            return "dir";
        }
    }
    

    Linux下要创建的Bean

    public class LinuxListService implements ListService {
        @Override
        public String showListCmd() {
            return "ls";
        }
    }
    
    • 配置类
    @Configuration
    public class ConditionConfig {
    
        @Bean
        @Conditional(WindowsCondition.class)
        public ListService windows() {
            return new WindowsListService();
        }
        @Bean
        @Conditional(LinuxCondition.class)
        public ListService linux() {
            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("列表命令: " + listService.showListCmd());
        }
    }
    

    组合注解与元注解

    • 所谓元注解,就是可以注解到别的注解上的注解,而被注解的注解成为组合注解
    • 组合注解具备所组成的元注解的功能
    • Spring中有很多元注解和组合注解
    • 我们也可以自己实现自定义组合注解
      例:组合@Configuration和@ComponentScan注解\
    • 创建组合注解
    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Configuration
    @ComponentScan
    public @interface WiselyConfiguration {
        String[] value() default {};
    }
    
    • 创建用来演示的bean
    @Service
    public class DemoService {
        public void outPutResult() {
            System.out.println("从组合注解处照样获得的bean");
        }
    }
    
    • 创建配置类
    @WiselyConfiguration("com.example.demo.simple_conditional.service")
    public class DemoConfig {
    }
    
    • 运行
    public class Main {
        public static void main(String args[]) {
            AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(DemoConfig.class);
            DemoService demoService = context.getBean(DemoService.class);
            demoService.outPutResult();
        }
    }
    

    @Enable* 注解的工作原理

    • spring通过@Enable*开启一些功能的支持,但他的底层源码其实通过@Import注解来导入配置类的,也就说这些自动开启的实现其实是导入了一些自动配置的Beans
      导入配置的方式一般有三种:
    1. 直接导入配置类
    2. 依据条件选择配置类
    3. 动态注册Bean

    测试

    • 测试是开发工作必不可少的一部分
    • Spring通过Spring TestContext Framework对集成测试提供顶级支持。它不依赖于特定的测试框架,既可以使用Junit,也可以使用TestNG
      例:
    • 配置maven依赖
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>apring-test</artifactId>
            </dependency>
    
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>4.11</version>
            </dependency>
    
    • 创建Bean
    public class TestBean {
    
        private String content;
    
        public TestBean(String content) {
            super();
            this.content = content;
        }
    
        public String getContent() {
            return content;
        }
    
        public void setContent(String content) {
            this.content = content;
        }
    }
    
    • 创建配置类
    @Configuration
    public class TestConfig {
    
        @Bean
        @Profile("dev")
        public TestBean devTestBean() {
            return new TestBean("dev");
        }
    
        @Bean
        @Profile("prod")
        public TestBean prodTestBean() {
            return new TestBean("prod");
        }
    }
    
    • 运行
    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(classes = {TestBean.class})
    @ActiveProfiles("prod")
    public class Main {
        @Autowired
        private TestBean testBean;
    
        @Test
        public void test() {
            System.out.println(testBean.getContent());
        }
    }
    

    相关文章

      网友评论

          本文标题:第3章 Spring 高级话题

          本文链接:https://www.haomeiwen.com/subject/knavcqtx.html