Spring常用配置

二.Spring常用配置

1.bean的Scope

Scope描述的是spring容器如何新建bean的实例,通常用@Scope实现。

(1)Singleton:一个spring容器中只有一个bean的实例,spring的默认配置,整个容器共享一个实例。

(2)Prototype:每次调用新建一个bean实例。

(3)Request:web项目中,给每一个HTTP request 新建一个bean实例。

(4)Session:web项目中,给每一个HTTP session 新建一个bean实例。

@Service
@Scope("prototype")
public class ProtoTypeDemo {
}

@Service
//默认是singleton,单例
public class SingletonDemo {
}

@Configuration
@ComponentScan("cn.cw.study.scope")
public class AppConfig {
}

public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
        ProtoTypeDemo protoTypeDemo = context.getBean(ProtoTypeDemo.class);
        ProtoTypeDemo protoTypeDemo2 = context.getBean(ProtoTypeDemo.class);
        System.out.println(protoTypeDemo==protoTypeDemo2);//false
        SingletonDemo singletonDemo = context.getBean(SingletonDemo.class);
        SingletonDemo singletonDemo1 = context.getBean(SingletonDemo.class);
    System.out.println(singletonDemo==singletonDemo1);//true
        context.close();
    }

2.Spring El 和资源调用

Spring El : Spring表达式语言,支持在xml和注解中使用表达式,类似于jsp的El表达式语言。

Spring开发中经常涉及调用各种资源的情况,包含普通文件、网址、配置文件、系统环境变量等。

我们可以使用spring的表达式语言实现资源注入。Spring主要在注解@Value的参数中使用表达式。

(1).准备,增加commons-io可以简化文件相关操作。

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

test.txt

生活

test.properties

book.author=ss    
book.name=spring boot

(2)需被注入的bean。

public class DemoComponent {
    @Value("其他类的属性")
    private String name;
        public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}

(3)演示配置类。

@Configuration
@ComponentScan("cn.cw.study.springel")
@PropertySource("classpath:cn/cw/study/springel/test.properties")
public class AppConfig {
    @Value("I") //注入普通字符串
    private String normal;
    @Value("#{systemProperties['os.name']}") //注入操作系统属性
    private String osName; 
    @Value("#{ T(java.lang.Math).random()*100.0}") //注入表达式结果
    private double randomNumber;
    @Value("#{demoComponent.name}")//注入其他bean属性
    private String fromAnother;
    @Value("classpath:cn/cw/study/springel/test.txt")//注入文件资源
    private Resource testFile;
    @Value("http://www.baidu.com")//注入网址资源
    private Resource testUrl;
    @Value("${book.name}")  //注入配置文件
    private String bookName;
    @Bean   //注入配置文件
    public static PropertySourcesPlaceholderConfigurer propertyConfigure(){
        return new PropertySourcesPlaceholderConfigurer();
    }
    @Autowired  //注入配置文件
    private Environment environment;

    public void test(){
        try {
            System.out.println(normal);
            System.out.println(osName);
            System.out.println(randomNumber);
            System.out.println(fromAnother);
        System.out.println(IOUtils.toString(testFile.getInputStream()));
        System.out.println(IOUtils.toString(testUrl.getInputStream()));
            System.out.println(bookName);
            System.out.println(environment.getProperty("book.author"));
        } catch (Exception e) {
            // TODO: handle exception
            e.printStackTrace();
        }
    }
}

(4)运行

public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
        AppConfig bean = context.getBean(AppConfig.class);
        bean.test();
        context.close();
    }

3.Bean的初始化和销毁

在实际开发中,经常遇到bean 在使用前或使用后做些必要的操作,spring对bean的生命周期的操作提供了支持:java配置和注解配置。

Java配置方式:使用@bean 的initMethod 和 destroyMethod (相当于xml配置的init-method 和 destroy-method)

注解方式:使用JSR-250的@PostConstruct 和 @PreDestory

添加jsr-250支持

<dependency>
      <artifactId>jsr250-api</artifactId>
      <groupId>javax.annotation</groupId>
      <version>1.0</version>
  </dependency>

public class BeanWayServiceDemo {
    public void init(){
        System.out.println("@Bean-init-method");
    }
    public BeanWayServiceDemo(){
        super();
        System.out.println("初始化构造函数-BeanWayServiceDemo");
    }
    public void destory(){
        System.out.println("@Bean-destory-method");
    }
}

public class JSR250WayServiceDemo {
    @PostConstruct  //在构造函数执行完之后执行
    public void init(){
        System.out.println("@jsr250-init-method");
    }
    public JSR250WayServiceDemo(){
        super();
        System.out.println("初始化构造函数-JSR250WayServiceDemo");
    }
    @PreDestroy //在bean销毁之前执行
    public void destory(){
        System.out.println("@jsr250-destory-method");
    }
}

@Configuration
@ComponentScan("cn.cw.study.initAnddestroy")
public class PrePostConfig {
    @Bean(initMethod="init",destroyMethod="destory")//在构造函数后、bean销毁前执行
    public BeanWayServiceDemo getBeanWayServiceDemo(){
        return new BeanWayServiceDemo();
    }
    @Bean
    public JSR250WayServiceDemo getJSR250WayServiceDemo(){
        return new JSR250WayServiceDemo();
    }
}

public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(PrePostConfig.class);
        PrePostConfig bean = context.getBean(PrePostConfig.class);
        BeanWayServiceDemo beanWayServiceDemo = bean.getBeanWayServiceDemo();
        JSR250WayServiceDemo jsr250WayServiceDemo = bean.getJSR250WayServiceDemo();
        context.close();
    }

4.Profile相关知识点

Profile为在不同环境下使用不同的配置提供了支持(开发环境下的配置和生产环境下配置肯定是不同的,例如,数据库的配置)

(1).通过设定Environment 的ActiveProfiles来设定当前context需要使用的配置环境。开发中使用@Profile注解类或者方法,达到在不同情况下选择实例化不同的bean。

(2)通过设定jvm的spring.profiles.active参数来设置配置环境。

(3)Web项目设置在servlet的context parameter中。

Servlet2.5及以下:

<servlet>
    <servlet-name>dispatcher</servlet-name>
  <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>spring.profiles.active</param-name>
        <param-value>production</param-value>
    </init-param>
</servlet>

Servlet3.0及以上:

public class WebInit implements WebApplicationInitializer{
    @Override
    public void onStartup(ServletContext container) throws ServletException{
        container.setInitParameter("spring.profiles.default","dev");
    }
}

profile代码示例:

@Configuration
public class ProfileConfig {
    @Bean
    @Profile("dev") //实例化devDemoBean
    public DemoBean devDemoBean(){
        return new DemoBean("from development profile");
    }
    @Bean
    @Profile("prod") //实例化prodDemoBean
    public DemoBean prodDemoBean(){
        return new DemoBean("from production profile");
    }
}
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;
    }

}
public class AppMain {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();

        context.getEnvironment().setActiveProfiles("dev"); //将活动的profile设置为prod
        context.register(ProfileConfig.class); //后置注册bean配置类,不然会报bean未定义的错误
        context.refresh();//刷新容器
        DemoBean bean = context.getBean(DemoBean.class);
        System.out.println(bean.getContent());
        context.close();
    }
}

5.事件(application event)

Spring的事件(application event)为bean与bean之间的消息通信提供了支持,当bean处理完一个任务之后,希望另外的一个bean知道并能做相应的处理,这时需要让另外一个bean监听当前bean所发送的事件。

Spring事件需要遵循如下流程:

(1)自定义事件,继承 applicationEvent。

(2)定义事件监听器,实现applicationEvent。

(3)使用容器发布事件。

代码示例:

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;
    }
}

@Component
public class DemoListerner implements ApplicationListener<DemoEvent>{

    @Override
    public void onApplicationEvent(DemoEvent event) {
        // TODO Auto-generated method stub
        String msString = event.getMsg();
        System.out.println("demolisterner 接收到了 bean--> demopublish 发布的消息:"+msString);
    }
}

@Component
public class DemoPublisher {
    @Autowired
    ApplicationContext context;

    public void publishTest(String msg){
        context.publishEvent(new DemoEvent(this, msg));
    }
}

@Configuration
@ComponentScan("cn.cw.study.applicationEvent")
public class EventConfig {

}
public class AppMain {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(EventConfig.class);
        DemoPublisher bean = context.getBean(DemoPublisher.class);
        bean.publishTest("test publish!");
        context.close();
    }
}

文章标题:Spring常用配置

发布时间:2019-11-14, 16:44:14

最后更新:2019-11-14, 16:44:14