SpringBoot系列(1)---无配置文件配置基础1
2017-07-05 21:34
846 查看
今天开始写关于SpringBoot的笔记,当然这个笔记也是主要给我自己看的。如果有其他开发者也在看我写的笔记的话,提醒一下 SpringBoot的笔记是建基于你已经熟悉使用Spring的前提地下去看的,当然我也会尽可能去重温一下Spring的东西。
关于SpringBoot 这个技术其实近段时间随着SpringCloud越来越火(所谓的微服务)SpringBoot也随着火起来了。其实Spring在3.X已经提供了纯annotation的配置,随着servlet3.0 无配置文件变得流行起来。不需要额外的WEB服务,因为WEB容器已经直接嵌入到你的项目当中,启动程序你只需要执行你写好的main方法即可启动web应用,听起来的确是挺让人兴奋的,笔者在上年 年初学习的SpringBoot,最近也准备认真研究一下SpringCloud 所以特意将SpringBoot的笔记写一下,顺便帮自己重温SpringBoot的技术。别废话马上开始····
首先我们老规矩,贴出maven 的依赖:
注意如果你想加载的快,建议用Spring的repository:
聪明的你或许已经看见我有写上Aspect的依赖了,所以我们先做一下AOP的测试,关于Spring-aspects的使用,我以前有一篇详细到我自己都不知道原来写得这么详细,给出哆啦B梦的任意门:Spring
AOP 之 Aspect
一、AOP AspectJ
然后我们尝试使用Anntation注解织入和execution表达式织入的AOP
1、定义目标 annotation
2、编写代织入测试的service类
3、编写织入配置类
到目前为止都是我们原来在Spring当中熟悉的东西,然后我们去掉我们应用的配置文件,使用类+annotation的方式代替配置文件的角色,由于我上面写了脏话,所以我的博客低于16岁不许看。
下面是配置:
1、@Configuration:代表这个是一个配置类
2、@ComponentScan : 这个很熟悉了,就是扫描的类。
3、@EnableAspectJAutoProxy:启动AspectJ 动态代理。
非常简单,也没有什么难度。
运行看看:
运行结果如下:
二、在annotation使用SpringEL
可以看到使用无配置文件的方式EL表达式也是如此的强大,接下来我们看看main方法:
对没错,ApplicationConfig配置类本身也将会成为一个实体bean。
调用之后输出如下结果:
需要注意的是,如果我们读取文件的时候出现异常,需要添加如下的依赖支持:
三、使用配置类方式配置bean
刚刚上面已经看见了,除了常规的annotation配置bean的方式,也可以使用以下这种方式:
没有配置任何的@Service @Repository 等标签
上面应该都懂了,先初始化的时候调用init方法,在销毁的时候调用destroy方法。注意:虽然我们没有在代码上显性定义为单例,但是事实上是单例:
运行输出如下:
当然我们也可以定义他的scope,下面是两个定义scope的方法:
Main方法:
可能你已经发现,我定义bean的方法的方法名改了,相对应的我在main方法当中的bean名称也发生了改变,由此得出定义bean的方法名其实就是定义bean的id
以下是运行结果:
如果是使用annotation定义bean的话,我们只需要在类中打上@Scope标签即可:
四、使用Profile
profile的主要作用是,当我们需要在不同环境当中获得不同的配置,或者不同的环境中获得不同的bean,这个时候就可以使用Profile。
设置当前的Profile有如下3种方式:
1、通过Environment的ActiveProfiles 设置当前的context的环境。
2、通过JVM的spring.profiles.active参数来进行指定context的环境。
3、WEB项目通过Servlet中的context parameter进行设置
3.1 servlet2.5以下:在DispatcherServlet 中的init-param标签,添加spring.profiles.active的配置。
3.2 servlet3.0以上:在ServletContext 对象中setInitParameter("spring.profiles.default","当前环境字符串") 进行配置。
由于我当前不是web项目,所以我使用第一种方式进行演示:
定义个demoBean类:
配置类如下:
可以看见我使用了@Profile指定了不同环境的名称,由于我们不可能写两个相同方法名称的方法,所以我们使用了@Bean中的name属性去定义bean的名称。
main方法:
我们一开始在AnntationConfigApplicationContext的构成中并没有去定义具体的配置类,获得contex对象之后更改profile 然后注册ApplicationConfig配置类,然后刷新配置。以下是运行结果:
五、事件
如果有android开发经验的同学应该已经有用过EventBus了,而Spring中的事件与ANDROID中的EventBus非常相似。Spring中的事件主要提供多个bean进行某个Event的事件监听。以下就开始上代码:
1、我们需要继承ApplicationEvent定义自定义事件
2、创建需要监听事件的类,需要实现ApplicationListener接口
3、创建发送事件的类
4、main方法调用并输出如下结果:
输出:got a message from <class com.tony.event.DemoPublisher> :ABC
注意:事实上我们监听事件可以不止一个监听事件的bean,所有继承并监听DemoEvent的类对象都会获得事件消息。
关于SpringBoot 这个技术其实近段时间随着SpringCloud越来越火(所谓的微服务)SpringBoot也随着火起来了。其实Spring在3.X已经提供了纯annotation的配置,随着servlet3.0 无配置文件变得流行起来。不需要额外的WEB服务,因为WEB容器已经直接嵌入到你的项目当中,启动程序你只需要执行你写好的main方法即可启动web应用,听起来的确是挺让人兴奋的,笔者在上年 年初学习的SpringBoot,最近也准备认真研究一下SpringCloud 所以特意将SpringBoot的笔记写一下,顺便帮自己重温SpringBoot的技术。别废话马上开始····
首先我们老规矩,贴出maven 的依赖:
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aspects</artifactId> <version>${spring.version}</version> </dependency>
注意如果你想加载的快,建议用Spring的repository:
<repositories> <repository> <id>io.spring.repo.maven.release</id> <url>http://repo.spring.io/release/</url> </repository> </repositories>
聪明的你或许已经看见我有写上Aspect的依赖了,所以我们先做一下AOP的测试,关于Spring-aspects的使用,我以前有一篇详细到我自己都不知道原来写得这么详细,给出哆啦B梦的任意门:Spring
AOP 之 Aspect
一、AOP AspectJ
然后我们尝试使用Anntation注解织入和execution表达式织入的AOP
1、定义目标 annotation
@Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface Action { String name(); }
2、编写代织入测试的service类
@Service public class DemoAnntationService { @Action(name = "What the Fuck") public void add(){ System.out.println("add executed!"); } }
@Service @Scope("prototype") public class DemoMethodService { public void add(){ System.out.println("DemoMethodService add() executed!"); } }
3、编写织入配置类
@Aspect @Component public class LogAspect { @Pointcut("@annotation(com.tony.config.Action)") public void annotationPointCut() { } @After("annotationPointCut()") public void after(JoinPoint joinPoint) { MethodSignature signature = (MethodSignature) joinPoint.getSignature(); Method method = signature.getMethod(); Action action = method.getAnnotation(Action.class); System.out.println("注解方式拦截:" + action.name()); } @Before("execution(* com.tony.service.DemoMethodService.add())") public void before(JoinPoint joinPoint) { MethodSignature signature = (MethodSignature) joinPoint.getSignature(); Method method = signature.getMethod(); System.out.println("execution 拦截方式:" + method.getName()); } }
到目前为止都是我们原来在Spring当中熟悉的东西,然后我们去掉我们应用的配置文件,使用类+annotation的方式代替配置文件的角色,由于我上面写了脏话,所以我的博客低于16岁不许看。
下面是配置:
@Configuration @ComponentScan("com.tony") @EnableAspectJAutoProxy public class ApplicationConfig { }
1、@Configuration:代表这个是一个配置类
2、@ComponentScan : 这个很熟悉了,就是扫描的类。
3、@EnableAspectJAutoProxy:启动AspectJ 动态代理。
非常简单,也没有什么难度。
运行看看:
public class App { public static void main( String[] args ) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ApplicationConfig.class); DemoAnntationService anntationService = context.getBean(DemoAnntationService.class); DemoMethodService methodService = context.getBean(DemoMethodService.class); anntationService.add(); methodService.add(); context.close(); } }
运行结果如下:
add executed! 注解方式拦截:What the Fuck execution 拦截方式:add DemoMethodService add() executed!
二、在annotation使用SpringEL
@Configuration @ComponentScan("com.tony") @EnableAspectJAutoProxy //导入配置文件,但是使用这个注解需要依赖PropertySourcesPlaceholderConfigurer @PropertySource("classpath:test.properties") public class ApplicationConfig { //普通注入字符串 @Value("ABC") private String normal; //通过systemProperties的bean获得系统名称 @Value("#{systemProperties['os.name']}") private String osName; //获得Spring 容器中其中一个bean的属性 @Value("#{T(java.lang.Math).random() * 100.0}") private double randomNumber; @Value("#{demoServiceForEL.username}") private String serviceUsername; //获得本地文件的resource对象 @Value("classpath:text.txt") private Resource testFile; //获得配置文件中的配置项 @Value("${test.propertyA}") private String propertyA; //获得配置文件中的配置项 @Value("${test.propertyB}") private String propertyB; //通过URL获得resource对象 @Value("http://www.baidu.com") private Resource testUrl; //这里通过environment获得property @Autowired private Environment environment; //注册一个PropertySourcesPlaceholderConfigurer的Bean @Bean public static PropertySourcesPlaceholderConfigurer propertyConfigure(){ return new PropertySourcesPlaceholderConfigurer(); } public void outputResource() throws IOException { System.out.println(normal); System.out.println(osName); System.out.println(randomNumber); System.out.println(propertyA); System.out.println(serviceUsername); System.out.println(IOUtils.toString(testFile.getInputStream())); System.out.println(IOUtils.toString(testUrl.getInputStream())); System.out.println(environment.getProperty("test.propertyB")); } }
可以看到使用无配置文件的方式EL表达式也是如此的强大,接下来我们看看main方法:
public static void main( String[] args ) throws IOException { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ApplicationConfig.class); ApplicationConfig config = context.getBean(ApplicationConfig.class); config.outputResource(); context.close(); }
对没错,ApplicationConfig配置类本身也将会成为一个实体bean。
调用之后输出如下结果:
ABC Mac OS X 57.69163813970949 valueA TONY ABCDEFG URL调用忽略太长了..... valueB
需要注意的是,如果我们读取文件的时候出现异常,需要添加如下的依赖支持:
<dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.5</version> </dependency>
三、使用配置类方式配置bean
刚刚上面已经看见了,除了常规的annotation配置bean的方式,也可以使用以下这种方式:
public class BeanWayService { public void init(){ System.out.println("BeanWayService-init"); } public BeanWayService(){ System.out.println("BeanWayService-constructor"); } public void destroy(){ System.out.println("BeanWayService-destroy"); } }
没有配置任何的@Service @Repository 等标签
@Configuration @ComponentScan("com.tony") @EnableAspectJAutoProxy public class ApplicationConfig { @Bean(initMethod = "init",destroyMethod = "destroy") public BeanWayService beanWayService(){ return new BeanWayService(); } }
上面应该都懂了,先初始化的时候调用init方法,在销毁的时候调用destroy方法。注意:虽然我们没有在代码上显性定义为单例,但是事实上是单例:
public static void main( String[] args ) throws IOException { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ApplicationConfig.class); BeanWayService wayServiceA = (BeanWayService) context.getBean("beanWayService"); BeanWayService wayServiceB = (BeanWayService) context.getBean("beanWayService"); System.out.println(wayServiceA == wayServiceB); context.close(); }
运行输出如下:
BeanWayService-constructor BeanWayService-init true BeanWayService-destroy
当然我们也可以定义他的scope,下面是两个定义scope的方法:
@Configuration @ComponentScan("com.tony") @EnableAspectJAutoProxy public class ApplicationConfig { @Bean(initMethod = "init",destroyMethod = "destroy") @Scope("prototype") public BeanWayService wayService(){ return new BeanWayService(); } }
Main方法:
public static void main( String[] args ) throws IOException { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ApplicationConfig.class); BeanWayService wayServiceA = (BeanWayService) context.getBean("wayService"); BeanWayService wayServiceB = (BeanWayService) context.getBean("wayService"); System.out.println(wayServiceA == wayServiceB); context.close(); }
可能你已经发现,我定义bean的方法的方法名改了,相对应的我在main方法当中的bean名称也发生了改变,由此得出定义bean的方法名其实就是定义bean的id
以下是运行结果:
BeanWayService-constructor BeanWayService-init BeanWayService-constructor BeanWayService-init false
如果是使用annotation定义bean的话,我们只需要在类中打上@Scope标签即可:
@Service @Scope("prototype") public class DemoServiceForEL { public String username = "TONY"; }
四、使用Profile
profile的主要作用是,当我们需要在不同环境当中获得不同的配置,或者不同的环境中获得不同的bean,这个时候就可以使用Profile。
设置当前的Profile有如下3种方式:
1、通过Environment的ActiveProfiles 设置当前的context的环境。
2、通过JVM的spring.profiles.active参数来进行指定context的环境。
3、WEB项目通过Servlet中的context parameter进行设置
3.1 servlet2.5以下:在DispatcherServlet 中的init-param标签,添加spring.profiles.active的配置。
3.2 servlet3.0以上:在ServletContext 对象中setInitParameter("spring.profiles.default","当前环境字符串") 进行配置。
由于我当前不是web项目,所以我使用第一种方式进行演示:
定义个demoBean类:
public class DemoBean { private String content; public String getContent() { return content; } public void setContent(String content) { this.content = content; } public DemoBean(String content) { this.content = content; } }
配置类如下:
@Configuration @ComponentScan("com.tony") @EnableAspectJAutoProxy public class ApplicationConfig { @Profile("dev") @Bean("demoBean") public DemoBean devDemoBean(){ return new DemoBean("DEV"); } @Profile("prod") @Bean("demoBean") public DemoBean prodDemoBean(){ return new DemoBean("PROD"); } }
可以看见我使用了@Profile指定了不同环境的名称,由于我们不可能写两个相同方法名称的方法,所以我们使用了@Bean中的name属性去定义bean的名称。
main方法:
public class App { public static void main( String[] args ) throws IOException { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); context.getEnvironment().setActiveProfiles("dev"); context.register(ApplicationConfig.class); context.refresh(); //记得刷新一下配置 DemoBean demoBean = (DemoBean) context.getBean("demoBean"); System.out.println(demoBean.getContent()); } }
我们一开始在AnntationConfigApplicationContext的构成中并没有去定义具体的配置类,获得contex对象之后更改profile 然后注册ApplicationConfig配置类,然后刷新配置。以下是运行结果:
DEV如果换环境只需要我们将setActiveProfiles修改为prod即可。
五、事件
如果有android开发经验的同学应该已经有用过EventBus了,而Spring中的事件与ANDROID中的EventBus非常相似。Spring中的事件主要提供多个bean进行某个Event的事件监听。以下就开始上代码:
1、我们需要继承ApplicationEvent定义自定义事件
public class DemoEvent extends ApplicationEvent { private String msg; public String getMsg() { return msg; } public void setMsg(String msg) { this.msg = msg; } public DemoEvent(Object source,String msg) { super(source); this.msg = msg; } }
2、创建需要监听事件的类,需要实现ApplicationListener接口
@Component public class DemoListener implements ApplicationListener<DemoEvent> { public void onApplicationEvent(DemoEvent demoEvent) { String msg = demoEvent.getMsg(); System.out.println("got a message from <"+demoEvent.getSource().getClass().toString()+"> :" + msg); } }
3、创建发送事件的类
@Component public class DemoPublisher { @Autowired ApplicationContext applicationContext; public void publish(String msg){ applicationContext.publishEvent(new DemoEvent(this,msg)); } }
4、main方法调用并输出如下结果:
public class App { public static void main( String[] args ) throws IOException { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ApplicationConfig.class); DemoPublisher publisher = context.getBean(DemoPublisher.class); publisher.publish("ABC"); } }
输出:got a message from <class com.tony.event.DemoPublisher> :ABC
注意:事实上我们监听事件可以不止一个监听事件的bean,所有继承并监听DemoEvent的类对象都会获得事件消息。
相关文章推荐
- SpringBoot系列(2)---无配置文件配置基础2
- Spring Boot干货系列:(二)配置文件解析
- Spring基础——在Spring Config 文件中配置 Bean(看了一半,看整个系列)
- Spring-Boot之基础 POM 文件和自动配置(maven)
- SpringBoot系列(3)---无配置文件SpringMVC
- Spring Boot教程(二)--- 推荐的基础 POM 文件和自动配置
- Spring Boot基础教程——配置文件-多环境配置
- (转)SpringBoot系列—基础配置
- Spring Boot干货系列:(二)配置文件解析
- 13-SpringBoot——Spring MVC基础-高级配置-文件上传
- SpringBoot 基础知识学习(二)——配置文件多环境配置
- Spring Boot系列 - 4. 读取配置文件(application.yml)中的属性值
- Spring Boot基础4-配置文件-多环境配置
- Spring Boot系列教程五:使用properties配置文件实现多环境配置
- Spring boot系列:配置文件(二)
- Spring Boot系列教程五:使用properties配置文件实现多环境配置
- 使用Gradle构建SpringBoot工程系列:第四篇:项目初始化(编辑build.gradle文件,引入项目基本配置及依赖)
- Spring Boot系列教程四:配置文件详解properties
- Spring Boot系列(二):Spring Boot的配置文件
- Spring Boot 系列(2) 配置文件的加载