SpringBoot系列(1)---无配置文件配置基础1
来源:互联网 发布:淘宝美工知乎 编辑:程序博客网 时间:2024/05/16 13:28
今天开始写关于SpringBoot的笔记,当然这个笔记也是主要给我自己看的。如果有其他开发者也在看我写的笔记的话,提醒一下 SpringBoot的笔记是建基于你已经熟悉使用Spring的前提地下去看的,当然我也会尽可能去重温一下Spring的东西。
关于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)@Documentedpublic @interface Action { String name();}
2、编写代织入测试的service类
@Servicepublic 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@Componentpublic 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")@EnableAspectJAutoProxypublic 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 Fuckexecution 拦截方式:addDemoMethodService 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。
调用之后输出如下结果:
ABCMac OS X57.69163813970949valueATONYABCDEFGURL调用忽略太长了.....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")@EnableAspectJAutoProxypublic 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-constructorBeanWayService-inittrueBeanWayService-destroy
当然我们也可以定义他的scope,下面是两个定义scope的方法:
@Configuration@ComponentScan("com.tony")@EnableAspectJAutoProxypublic 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-constructorBeanWayService-initBeanWayService-constructorBeanWayService-initfalse
如果是使用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")@EnableAspectJAutoProxypublic 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接口
@Componentpublic 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、创建发送事件的类
@Componentpublic 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系列(1)---无配置文件配置基础1
- SpringBoot系列(2)---无配置文件配置基础2
- SpringBoot系列(3)---无配置文件SpringMVC
- SpringBoot系列—基础配置
- springBoot基础系列--properties配置
- springBoot基础系列--properties配置
- springBoot基础系列--properties配置
- SpringBoot基础(1)
- SpringBoot 入门基础1
- SpringBoot配置属性系列
- SpringBoot配置文件以及配置项
- SpringBoot-自动配置1
- SpringBoot MyBatis基础配置
- 【SpringBoot系列】二:SpringBoot配置详解
- SpringBoot系列(5)---SpringBoot-Web和SpringBoot基础
- SpringBoot系列—SSL配置
- Git系列学习(1)-基础配置
- SpringBoot整合Dubbox(无XML配置)
- java 与数据库连接 实现用户的注册和登录
- 4K 对齐与固态硬盘检测工具
- 数据结构与算法的js描述总结
- 在一个WildFly实例中简单设置Drools KIE WorkBench和KIE服务器
- 2017.07.05【NOIP提高组】模拟赛A组 邮递员
- SpringBoot系列(1)---无配置文件配置基础1
- 微信公众平台开发(71)OAuth2.0网页授权
- Java中 Cloneable 、Serializable 接口详解
- [Leetcode] 266. Palindrome Permutation 解题报告
- 前后端分离为什么不利于网站的SEO?
- Uva1336 修长城 【有关未来费用的区间dp】
- Qt平台C++拖动功能实现
- 使用js提交form表单的两种方法
- Java中四种访问权限总结