Spring常用配置_在项目中有公司类员工类要求写出spring配置组件配置信息-程序员宅基地

技术标签: spring  java  Spring和SpringMVC框架案例  JavaEE  

上篇文章我们简单介绍了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实战》第二章

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/u012702547/article/details/53633872

智能推荐

做机械臂导航时遇到的问题4:如何订阅joint_states话题(输出关节状态)_airbot_play/joint_states-程序员宅基地

文章浏览阅读1w次,点赞19次,收藏99次。在完成用arbotix测试机械臂后,我们想控制真实的机械臂伺服电机。由于arbotix是针对舵机的,我们要想控制伺服电机,要将ROS里机械臂的关节信息(角度、角速度、加速度、力等)发给下位机,首先就是要获取关节信息。 关于让机械臂动起来,这里参考了一些大神的博客,在这里表示感谢让模型动起来: http://blog.csdn.net/yaked/article/details_airbot_play/joint_states

Ubuntu18.04 远程桌面SSH + X转发 + VNC4server(亲测延迟最低远程桌面控制)_ssh和远程桌面 哪个延迟低-程序员宅基地

文章浏览阅读1.8k次。1.SSH安装:$ sudo apt-get ssh该远程控制只能使用命令行控制,但是使用方便延迟低。ubuntu18.04下一般自带,win10需要下载putty使用。连接命令:$ ssh username@host_address#username为服务器名,host_address为服务器ip地址ubuntu下使用SSH向服务器下载或上传文件。下载文件命令:$ scp username@host_address:file_name上传命令:$ scp file_name u_ssh和远程桌面 哪个延迟低

Python web框架之tornado(龙卷风)_python tornado-程序员宅基地

文章浏览阅读7.6k次,点赞5次,收藏12次。Tornado是Python界中非常出名的一款Web框架,和Flask一样它也属于轻量级的Web框架。_python tornado

踩过的坑系列之InputStream.read(byte[])方法-程序员宅基地

文章浏览阅读854次。转自:https://www.cnblogs.com/lylife/p/5519109.html项目之前都是好好的,最近现场那边出现一个问题,报错不是合法的json字符串,这个json字符串是通过http请求访问获得的。  通过直接在浏览器上直接访问http这个请求,发现返回的json也是完全正确的。后来排查代码才发现了原来错误出在从字节流中读取数据这里:  看下之前出错代码:这..._inputstream.read(byte[])' on a null object reference

(2,1,2)卷积码BCJR译码matlab仿真_matlab bcjr-程序员宅基地

文章浏览阅读3.6k次,点赞6次,收藏45次。仿真(2,1,2)卷积码的性能,BCJR译码,级联的调制方式采用QPSK。每个码块信息比特长度为1000,要求编码最终状态归0。要求输出的结果为译码后信息比特的BER。_matlab bcjr

python 读取鼠标选中文本_送书 | 选择文本的神技-程序员宅基地

文章浏览阅读1.5k次。“欢迎关注【雷哥office】,为了回馈粉丝,最近几个月每周都会有送书活动,想要书的朋友不要错过哦~本周第二弹福利, 详情见文末”1使用鼠标⑴选中区域。将鼠标光标放在要选择的文本的开始位置,按住鼠标左键并拖曳,这时选中的文本会以阴影的形式显示,选择完成后,释放鼠标左键,鼠标光标经过的文字就被选定了。⑵选中词语。将鼠标光标移动到某个词语或单词中间,双击鼠标左键即可选中该词语或单词。⑶..._python获取鼠标选取的内容

随便推点

python 一组数据 正态分布散点图_如何在SPSS、Python、R中用Q-Q图检验数据是否服从正态分布?...-程序员宅基地

文章浏览阅读505次。正态分布广泛存在于自然现象、生产、生活的方方面面,例如试卷命题难度,产品的使用寿命、农作物产量、气温、降水量、工资收入、人类的身高体重肺活量,甚至颜值……关于正态分布的数学定义及各种性质,不在此赘述。简单理解,就是“两头小,中间大”,比如长相奇丑无比和倾国倾城的人都是少数,绝大多数人都属于大众脸。很多时候,在进行数据分析工作时,首先要看的就是数据是服从何种概率分布,而正态分布则是最重要的一种概率分..._怎么制作散点图表示采样个体在全部个体中的分布位置

C/C++中main函数的三个参数与环境变量的获取_cpp main第三个参数是啥-程序员宅基地

文章浏览阅读1.9k次。C/C++的main函数除了常见的argc、argv,还具有第三个指定的参数envp,完整的引用方式如下:main(int argc, const char *argv[], const char *envp[]) //void类型没有参数1.argc为整数2.argv为指针的指针(可理解为:char **argv or: char *argv[] or: char argv..._cpp main第三个参数是啥

nginx 代理转发 FTP_ftp nginx转发-程序员宅基地

文章浏览阅读2.9w次,点赞4次,收藏24次。这里实现的 FTP 转发,其实和 SFTP 转发是一样的。详情见我的另一篇文章 Nginx代理转发SFTP上次写的 代理转发 SFTP 是在 linux 上测试的,本篇文章则是在 Windows 环境下测试的。关于 Windows 环境怎么搭建 FTP 服务器,请参阅我的另一篇文章 图解 —— Windows 下 FTP 服务器搭建及验证全过程配置文件同样打开 nginx.conf 配置文件,做如下配置,和SFTP的转发配置完全一样stream { upstream ftp{ ._ftp nginx转发

Stata 数据分析_stata主成分分析结果解读-程序员宅基地

文章浏览阅读7.5k次,点赞2次,收藏13次。最近在学习STATA做分析的时候,发现这个软件很多功能很强大,但是背后的统计学知识要求也比较高,作为一边深入学习统计知识一遍用软件的小白,好多东西只是知其然不知其所以然,因此尝试自己把STATA的一些运算分解出来。因此这里记录一下学习内容。在做STATA的主成分分析和因子分析的时候,觉得这两个东西很像,但是其中的原理好像也不太清楚,网上查了一些文章,花了不少时间才明白怎么做的,这里演示一下具体_stata主成分分析结果解读

javaee学习笔记1_javaee的学习摘要-程序员宅基地

文章浏览阅读338次。为什么需要JavaEE我们编写的JSP代码中,由于大量的显示代码和业务逻辑混淆在一起,彼此嵌套,不利于程序的维护和扩展。当业务需求发生变化的时候,对于程序员和美工都是一个很重的负担。为了程序的易维护性和可扩展性,这就需要我们使用JavaEE技术来进行项目开发2、 什么是JavaEEJavaEE是一个开发分布式企业级应用的规范和标准。Java语言的平台有3个版本:适用于小型设备和智能卡的JavaME(Java Platform Micro Edition,Java微型版)、适用于桌面系统的Java_javaee的学习摘要

DM大规模并行处理MPP_dm mpp-程序员宅基地

文章浏览阅读316次。DM大规模并行处理MPP_dm mpp

推荐文章

热门文章

相关标签