JavaEE开发的颠覆者:Spring Boot实战 学习笔记3--spring常用配置

Spring框架本身四大原则


1.使用POJO进行轻量级以及最小侵入式开发

2.通过依赖注入和基于接口式编程实现松耦合

3.通过AOP和默认习惯进行声明式编程

4.使用AOP和模板(template)减少模式化代码

控制反转和依赖注入在Spring环境下市等同的概念。


常用配置


Bean的Scope

描述Spring如何新建Bean的实例,与模式相似,由@Scope注解实现。如:@Scope("singleton")/prototype等。

Singleton:单例模式,全容器共享一个Bean实例

Prototype:非单例模式,每次调用新建一个Bean实例

Request:Web项目中,给每一个http Request新建一个Bean实例

Session:Web项目中,给每一个http Session新建一个Bean实例

GlobalSession:这个只在portal(?)应用中有用,给每一个global http Session新建一个Bean实例

singleton

@Service
//@Scope("singleton")
public class SingletonService(){

}

prototype

@Service
@Scope("prototype")
public class PrototypeService(){
}
//配置类
@Configuration
@ComponentScan("所在包名")
public class ScopeConfig(){
}
public class Main {
    public static void main(String[] args){
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ScopeConfig.class);
        DemoSingletonService singletonService1 = context.getBean(DemoSingletonService.class);
        DemoPrototypeService prototypeService1 = context.getBean(DemoPrototypeService.class);
        DemoSingletonService singletonService2 = context.getBean(DemoSingletonService.class);
        DemoPrototypeService prototypeService2 = context.getBean(DemoPrototypeService.class);
        String s1_s2 = singletonService1==singletonService2?"是":"否";//equals也可以
        String p1_p2 = prototypeService1==prototypeService2?"是":"否";
        System.out.println("singletonService1 与 singletonService2 是否为同一个Bean实例:"+s1_s2);
        System.out.println("prototypeService1 与 prototypeService2 是否为同一个Bean实例:"+p1_p2);
        int[] nums = new int[20];
        for (int i=0;i<nums.length; i++)
            System.out.println(nums[i]);
    }

EL和资源调用

在注解中使用Spring-EL表达式,和JSP中EL表达式使用类似

可参考https://blog.csdn.net/acmjk/article/details/46791603

实例:在自己定义的一个目录下新建一个test.txt文件(内容随便)和test.properties文件

需要用到的简化文件操作,事先引用

<!--简化文件相关操作  可将file转换为字符串-->
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.3</version>
        </dependency>
<!--test.properties文件内容-->
book.name = spring boot
book.author = writor
/**
*定义一个Service(Bean)实例,用于演示el表达式注入其他Bean的属性
*/
@Service
public class DemoService{
    private String fromOtherBean;
    public String getFromOtherBean(){
        return fromOtherBean;
    }
    public void getFromOtherBean(String another){
        this.fromOtherBean= another;
    }
}

配置类

@Configuration
@ComponentScan("com.wisely.highlight_spring4_idea.ch2.el")
@PropertySource("classpath:com/wisely/highlight_spring4_idea/ch2/el/test.properties")
//用PropertySource注入配置文件
public class ElConfig{
    @Value("普通字符串")
    private String normal;//注入普通字符串

    @Value("#{systemProperties['os.name']}")//注入操作系统属性
    private String osName;

    @Value("#{T(java.lang.Math).random()*100.0}")//注入表达式结果
    private double randomNum;

    @Value("#{demoService.fromAnotherBean}")//注入其他Bean属性
    private String fromAnother;

    //若使用@Value注入需要PropertySourcesPlaceholderConfigurer的Bean
    @Value("classpath:com/wisely/highlight_spring4_idea/ch2/el/test.txt")//注入文件资源
    private Resource testFile;

    @Value("http://www.baidu.com")//注入网址资源
    private Resource testUrl;

    @Value("${book.name}")//注入配置文件
    private String bookName;

    @Autowired
    private Environment environment;//注入配置文件 properties可从Environment中获得
    @Bean//若使用@Value注入需要PropertySourcesPlaceholderConfigurer的Bean
    public static PropertySourcesPlaceholderConfigurer propertyConfig(){
        return new PropertySourcesPlaceholderConfigurer ();
    }
    
    public void outputResource(){
        try {
            System.out.println(normal);
            System.out.println(osName);
            System.out.println(randomNum);
            System.out.println(fromAnother);
            System.out.println(IOUtils.toString(testFile.getInputStream()));
            System.out.println(IOUtils.toString(testUrl.getInputStream()));
            //本人测试为null,正在查找原因
            System.out.println(bookName);
            //System.out.println(bookAuthor);
            System.out.println(environment.getProperty("book.author"));
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

Main(本人按教材例子和IDEA实现,经常报test.properties文件不存在错误,但是文件路径没错,且在找到文件后读出打印数据又为null)

public class Main{
    public static void main(String[] args){
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ElConfig.class);
        ElConfig resorceService = context.getBean(ElConfig.class);
        resorceService.outputResource();
        context.close();    } 
}

错误原因和解决:

编译后配置文件没带过去,这是使用IDEA时会遇到的错误。

用的是IDEA,会发现target文件夹里只有class没有properties和txt。

手动复制过去或者把properties放在resource里就可以了。后者是默认地址就不用加前面的路径了。

(但是复制在resource中时,我仍然会报这个错误,而复制在target里的就不会报错)
原因网上有说是:
对于MAVEN项目,Eclipse会自动把项目src\main\java\目录下的配置文件(.xml)和资源文件(.properties)搬运到target目录下,而intellij idea默认是不会帮我们做这件事的。

Bean的初始化和销毁

即定义在Bean的使用之前和之后需要做的操作

(1)java配置方式:使用@Bean的init()和destroy()方法

(2)注解:在定义的方法前使用JSR-250的@PostCustruct和@PreDestroy,注解需要引入

<!--增加JSR250支持-->
        <dependency>
            <groupId>javax.annotation</groupId>
            <artifactId>jsr250-api</artifactId>
            <version>1.0</version>
        </dependency>
public class BeanWayService {
    public void init(){
        System.out.println("@Bean-init-method");
    }
    public BeanWayService(){
        super();
        System.out.println("初始化构造函数-BeanWayService");
    }
    public void destory(){
        System.out.println("@Bean-destory-method");
    }
}
public class JSR250WayService {
    @PostConstruct//构造函数执行之后执行
    public void init(){
        System.out.println("jsr250-init-method");
    }
    public JSR250WayService(){
        super();
        System.out.println("初始化构造函数:JSR250WayService");
    }
    @PreDestroy//Bean销毁之前执行
    public void destory(){
        System.out.println("jsr250-destory-method");
    }
}
@Configuration
@ComponentScan("com.wisely.highlight_spring4_idea.ch2.prepost")
public class PrepostConfig {
    @Bean(initMethod = "init",destroyMethod = "destory")//指定BeanWayService类的init和destory在构造之后、Bean销毁之前执行
    BeanWayService beanWayService(){
        return new BeanWayService();
    }
    @Bean
    JSR250WayService jsr250WayService(){
        return new JSR250WayService();
    }
}
public class Main {
    public static void main(String[] args){
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(PrepostConfig.class);
        BeanWayService beanWayService = context.getBean(BeanWayService.class);
        System.out.println("----------");
        JSR250WayService jsr250WayService = context.getBean(JSR250WayService.class);
        context.close();
    }
}

Profile

版本控制

//模拟Bean
public class DemoBean{
    String msg;
    public DemoBean(String msg){
        super();
        this.msg = msg;
    }
    public void setMsg(String msg){
        this.msg = msg;
    }

    public String getMsg(){
        return msg;
    }

}
/**
*关键配置
*/
@Configuration
public class ProfileConfig{
    @Bean
    @Profile("dev")//环境配置 Profile为dev时实例化devDemoBean
    public DemoBean devDemoBean(){return new DemoBean("Profile-dev:devDemoBean")}
    @Bean
    @Profile("pre")
    public DemoBean preDemoBean(){return new DemoBean("Profile-pre:preDemoBean")}
}

Main方法中

public class Main{
    public static void main(String[] args){
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
        context.getEnvironment().setActiveProfiles("pro");//将活动的profile设置为"pre"
        context.register(ProfileConfig.class)//后置注册Bean配置类,否则会报Bean未定义错误
        context.refresh();//刷新容器
        DemoBean bean = context.getBean(DemoBean.class);
        System.out.println(bean.getMsg);
        context.close();
    }
}

Event

自定义事件继承ApplicationEvent(类+方法)-->定义事件监听器实现ApplicationListener接口并指定监听的事件类型ApplicationListener<T>(加入Spring容器管理)-->定义事件发布类,注入ApplicationContext用来发布事件(加入Spring容器管理)

public calss DemoEvent extends ApplicationEvent{
    private String msg;
    public DemoEvent(Object source,String msg){
        super(source);
        this.msg = msg;
    }/*若没有自带属性,则构造函数只初始化父类Object source属性
        public DemoEvent(Object source){
            super(source);
        }*/
    public String getMsg() { return msg; }

    public void setMsg(String msg) { this.msg = msg; }
}
@Component
public class DemoEventListener implements ApplicationListener{
    @Override
    public void onApplicationEvent(Event1 event) {
        System.out.println("监听器 接收发布消息:"+event.getMsg);
    }
}
@Component
public class DemoEventPubisher{
    @Autowired
    ApplicationContext applicationContext;//注入ApplicationContext用来发布事件
    public void publish(String msg){
        applicationContext.publishEvent(new Event(this,msg));
    }

}
public class Main {
    public static void main(String[] args){
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(EventConfig.class);
        DemoPublisher publisher = context.getBean(DemoPublisher.class);
        //Event1Publisher event1 = context.getBean(Event1Publisher.class);
        publisher.publish("我爱你");
        //event1.pubish("I Love You");
        context.close();
    }
}

猜你喜欢

转载自blog.csdn.net/huofuman960209/article/details/82691491