zoukankan      html  css  js  c++  java
  • Spring常用配置

    上篇文章我们简单介绍了Spring的基本配置,算是一个简单的入门,这篇文章我们再一起来看看Spring在使用的过程中一些其他的常见配置。

    Bean的Scope

    Spring中的Scope注解主要是为了解决Bean的实例问题,就是Bean在不同的场合下到底该有几个实例,是单例模式还是其他模式?一般来说,Spring的Scope有如下几种:

    1.Singleton:表示该Bean是单例模式,在Spring容器中共享一个Bean的实例
    2.Prototype:每次调用都会新创建一个Bean的实例
    3.Request:这个是使用在Web中,给每一个http request新建一个Bean实例
    4.Session:这个同样是使用在Web中,表示给每一个http session新建一个Bean实例

    OK,接下来通过一个简单的案例来看看@Scope注解要怎么使用:

    1.编写一个Bean

    Component
    @Scope("singleton")
    public class ScopeTest {
    
    }

    小伙伴们注意,这里我使用了@Scope("singleton")注解,这个注解表示该类是一个单例模式,如果想使用prototype模式,将singleton改为prototype即可。

    2.配置类

    @Configuration
    @ComponentScan("org.sang")
    public class MyConfig {
    
    }

    这个配置类很简单,没什么好说的,有疑问请查看上篇博文。

    3.使用

    public class Main {
        public static void main(String[] args) {
            AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class);
            ScopeTest bean1 = context.getBean(ScopeTest.class);
            ScopeTest bean2 = context.getBean(ScopeTest.class);
            System.out.println(bean1.equals(bean2));
            context.close();
        }
    }

    这里的我们直接获取两个ScopeTest类的实例,然后比较这两个是否是同一个就可以知道@Scope注解是否生效,运行结果如下:

    OK,接下来我们把第一步创建的类的@Scope注解修改一下,改成下面的样子:

    @Component
    @Scope("prototype")
    public class ScopeTest {
    
    }

    这个时候再运行,结果如下:

    本案例下载地址:

    本案例GitHub地址

    Spring EL和资源调用

    Spring 中的EL 表达式有点类似于JSP中的EL表达式,它支持在xml文件和注解中使用表达式。另一方面,JavaEE开发中我们可能经常要注入不同类型的文件,这些文件在注入成功之后我们要通过EL来提取其中的值,OK,那我们来看一个简单的实例。

    1.添加commons-io工具类,简化file操作

    因为本案例后面会涉及到一点IO操作,使用这个工具类可以帮助我们简化操作

            <dependency>
                <groupId>commons-io</groupId>
                <artifactId>commons-io</artifactId>
                <version>2.5</version>
            </dependency>

    2.添加t.txt文件、t.properties文件

    添加两个文件来演示文件的注入,我使用IntelliJ IDEA来做开发的,我们这两个文件放在resources文件夹中,如下:

    t.txt文件中的内容随意,t.properties文件中的内容也随意,以我的这两个文件为例:

    3.编写需要被注入的Bean

    @Service
    public class DemoService1 {
        //注入普通字符串
        @Value("老王")
        private String author;
    
        public String getAuthor() {
            return author;
        }
    
        public void setAuthor(String author) {
            this.author = author;
        }
    }

    这个很简单,不多说。

    4.编写配置类

    @Configuration
    @ComponentScan("org.sang")
    @PropertySource(value = "t.properties",encoding = "UTF-8")
    public class ELConfig {
        @Value("I Love You!")
        private String normal;
        @Value("#{systemProperties['os.name']}")
        private String osName;
        @Value("#{systemEnvironment['os.arch']}")
        private String osArch;
        @Value("#{T(java.lang.Math).random()*100}")
        private double randomNumber;
        @Value("#{demoService1.author}")
        private String author;
        @Value("t.txt")
        private Resource testFile;
    
        @Value("http://www.baidu.com")
        private Resource testUrl;
        @Value("${sang.username}")
        private String su;
        @Value("${sang.password}")
        private String sp;
        @Value("${sang.nickname}")
        private String sn;
        @Autowired
        private Environment environment;
    
        public void output() {
            try {
                System.out.println(normal);
                System.out.println(osName);
                System.out.println(osArch);
                System.out.println(randomNumber);
                System.out.println(author);
                System.out.println(IOUtils.toString(testFile.getInputStream(),"UTF-8"));
                //访问网址
                System.out.println(IOUtils.toString(testUrl.getInputStream(),"UTF-8"));
                //获取网址
                System.out.println("testUrl.getURL():"+testUrl.getURL());
                System.out.println(su);
                System.out.println(sp);
                System.out.println(sn);
                System.out.println(environment.getProperty("sang.nickname"));
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    OK ,小伙伴们看到,我们首先需要在类上使用@PropertySource来指定文件地址,将t.properties注入。在属性上我们可以直接使用@Value来完成注入,可以注入普通的字符串,也可以执行一行Java代码,可以将某一个类的属性值注入,也可以注入一个文件,等,不赘述。我们注入的t.properties除了通过${aaa.bbb}获取之外,也可以从Environment中获得。
    当然,我们还需要一个配置类,如下:

    @Configuration
    @ComponentScan("org.sang")
    public class MyConfig {
    }
    

    5.运行

    public class Main {
        public static void main(String[] args) {
            AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class);
            ELConfig bean = context.getBean(ELConfig.class);
            bean.output();
            context.close();
        }
    }

    运行结果:

    本案例下载地址
    本案例GitHub地址

    Bean的初始化和销毁

    对于Bean的操作,很多情况下不是简单的创建,我们还需要做一些必要的初始化操作,同时,用完了,该销毁的销毁,该释放的释放,这个要怎么实现呢?
    总的来说,有两种方式:

    1.Java配置方式,我们可以使用@Bean的注解中的initMethod和destroyMethod两个东东,这两个对应xml配置文件中的init-method和destroy-method。
    2.使用JSR-250中的注解@PostConstruct和@PreDestroy.

    我们来看看这两个案例。

    1. 添加JSR-250支持
        <dependency>
                <groupId>javax.annotation</groupId>
                <artifactId>jsr250-api</artifactId>
                <version>1.0</version>
            </dependency>

    2.使用Java配置的方式操作Bean

    public class BeanWayService {
        public void init() {
            System.out.println("BeanWayService-init()");
        }
    
        public BeanWayService() {
            System.out.println("BeanWayService-构造方法");
        }
        public void destroy() {
            System.out.println("BeanWayService-destroy()");
        }
    }

    3.使用JSR-250的方式操作Bean

    public class JSR250WayService {
        @PostConstruct//构造方法执行之后执行
        public void init() {
            System.out.println("JSR250WayService-init()");
        }
    
        public JSR250WayService() {
            System.out.println("JSR250WayService-构造方法");
        }
        @PreDestroy//销毁之前执行
        public void destroy() {
            System.out.println("JSR250WayService-destroy()");
        }
    }

    4.编写配置类

    @Configuration
    public class MyConfig {
        @Bean(initMethod = "init",destroyMethod = "destroy")
        BeanWayService beanWayService() {
            return new BeanWayService();
        }
        @Bean
        JSR250WayService jsr250WayService() {
            return new JSR250WayService();
        }
    }

    initMethod指定在构造方法执行完成之后执行初始化方法,destroyMethod指定在销毁之前执行destroy方法。

    5.运行

    public class Main {
        public static void main(String[] args) {
            AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class);
            BeanWayService beanWayService = context.getBean(BeanWayService.class);
            JSR250WayService jsr250WayService = context.getBean(JSR250WayService.class);
            context.close();
        }
    }

    运行结果:

    本案例下载地址:
    本案例GitHub地址

    Profile问题

    在开发中我们一个常见的需求是数据库的连接配置,在开发时数据库是一种配置方式,项目发布的时候数据库又是另外一种配置方式。对于这个问题,我们可以采用@Profile注解来简化在两种不同的配置中切换。OK,接下来我们来看看@Profile注解的使用。

    1.创建示例Bean

    public class DemoBean {
    
        private String content;
    
        public DemoBean(String content) {
            super();
            this.content = content;
        }
    
        public String getContent() {
            return content;
        }
    
        public void setContent(String content) {
            this.content = content;
        }
    }

    2.使用Profile配置

    @Configuration
    public class ProfileConfig {
        @Bean
        @Profile("dev")
        public DemoBean devDemoBean() {
            return new DemoBean("dev");
        }
    
        @Bean
        @Profile("prod")
        public DemoBean prodDemoBean() {
            return new DemoBean("prod");
        }
    }

    当Profile为dev时使用devDemoBean来实例化DemoBean,当Profile为prod时,使用prodDemoBean来实例化DemoBean。

    3.使用

    public class Main {
        public static void main(String[] args) {
            AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
            context.getEnvironment().setActiveProfiles("prod");
            context.register(ProfileConfig.class);
            context.refresh();
    
            DemoBean bean = context.getBean(DemoBean.class);
            System.out.println(bean.getContent());
    
            context.close();
        }
    }

    这里还是先获取Spring容器,这不过在获取容器时先不传入配置文件,待我们先将活动的Profile置为prod之后,再设置配置文件,设置成功之后,一定要刷新容器。
    运行结果:

    本案例下载地址:

    本案例GitHub地址

    Spring中的事件传递

    有的时候,我们可能希望当一个Bean完成某一项操作的时候,能够通知到其他的Bean,其他Bean收到消息后做出相应的处理。Spring对此也提供了相应的支持,在Spring框架内我们可以很好的完成事件的发送与接收。

    1.定义消息载体

    public class DemoEvent extends ApplicationEvent{
        private String msg;
    
        public DemoEvent(Object source, String msg) {
            super(source);
            this.msg = msg;
        }
    
        public String getMsg() {
            return msg;
        }
    
        public void setMsg(String msg) {
            this.msg = msg;
        }
    }

    2.定义事件监听器

    @Component
    public class DemoListener implements ApplicationListener<DemoEvent> {
        public void onApplicationEvent(DemoEvent demoEvent) {
            System.out.println("我收到DemoEvent的事件了:"+demoEvent.getMsg());
        }
    }

    3.定义事件发布者

    @Component
    public class DemoPublish{
        @Autowired
        ApplicationContext applicationContext;
    
        public void publish(String msg) {
            applicationContext.publishEvent(new DemoEvent(this,msg));
        }
    }

    4.配置类

    @Configuration
    @ComponentScan("org.sang")
    public class MyConfig {
    }

    5.运行

    public class Main {
        public static void main(String[] args) {
            AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class);
            DemoPublish demoPublish = context.getBean(DemoPublish.class);
            demoPublish.publish("Hello sang !");
            context.close();
        }
    }

    运行结果:

    本案例下载地址:

    本案例GitHub地址

    OK,以上就是Spring中一些常见的配置。

    参考资料:
    《JavaEE开发的颠覆者 Spring Boot实战》第二章

  • 相关阅读:
    matplotlib基础汇总_03
    matplotlib基础汇总_02
    matplotlib基础汇总_01
    水果系统(面向过程,面向对象)
    给定几位数,查看数根(使用函数实现)
    定义函数,给定一个列表作为函数参数,将列表中的非数字字符去除
    学生管理系统-明日学院的
    四平方和
    四位玫瑰数
    学生成绩表数据包括:学号,姓名,高数,英语和计算机三门课成绩,计算每个学生总分,每课程平均分,最高分和最低分
  • 原文地址:https://www.cnblogs.com/qitian1/p/6461647.html
Copyright © 2011-2022 走看看