上一节,我们讲到SpringBoot的IOC思想
现在主要讲解模式注解中的@Configuration(配置类)
上一节的例子中,如果执行代码需要切换类,依然需要修改主业务逻辑的代码(如从Diana类切换到Fox类)
如何应对面向对象中的变化呢?
- 策略模式:制定一个interface,然后多个类实现一个interface
- 防御模式:一个类实现interface,然后通过修改类的属性即可完成需求
demo1策略模式:引入@Configuration
1.1、 在sample/hero创建一个类,并命令为Xing
切记该类不能加入Component,不然会报错
package com.fcors.fcors.sample.hero;
import com.fcors.fcors.sample.ISkill;
public class Xing implements ISkill {
public Xing(){
System.out.println("xing 被实例化~");
}
public void q(){
System.out.println("xing Q");
}
public void w(){
System.out.println("xing W");
}
}
1.2、在sample创建一个类,命名为HeroConfiguration
在类的方法中前加入@Configuration;在具体的实现中加入@Bean
package com.fcors.fcors.sample;
import com.fcors.fcors.sample.hero.Xing;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class HeroConfiguration {
@Bean
public ISkill xing(){
return new Xing();
}
}
1.3、在具体的执行代码调用
package com.fcors.fcors.api.v1;
import com.fcors.fcors.sample.ISkill;
import com.fcors.fcors.sample.hero.Diana;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Lazy;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/v1/api/")
public class TestController {
@Autowired
private ISkill xing;
@GetMapping("/test3")
public String test2(){
xing.q();
return "Hello Fox is testing3~";
}
}
demo2:通过构造函数或者Setter(),通过修改属性完成需求(防御模式)
demo2.1 构造函数方式的(防御模式)
2.1.1、修改demo1的Xing类
package com.fcors.fcors.sample.hero;
import com.fcors.fcors.sample.ISkill;
import org.springframework.stereotype.Component;
public class Xing implements ISkill {
private String Name ="Xing";
/* 属性注入 */
public Xing(String Name){
this.Name=Name;
System.out.println(String.format("%s 被实例化~",this.Name));
}
public void q(){
System.out.println(String.format("%s Q",this.Name));
}
public void w(){
System.out.println(String.format("%s W",this.Name));
}
}
2.1.2、修改demo1的HeroConfiguration类
package com.fcors.fcors.sample;
import com.fcors.fcors.sample.hero.Xing;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class HeroConfiguration {
@Bean
public ISkill xing(){
return new Xing("HEllo");
}
}
构造型传参完成
下面进行Setter传参讲解
2.2.1、修改demo1的Xing类
选中定义的参数,右键”Generate”–>Setter
package com.fcors.fcors.sample.hero;
import com.fcors.fcors.sample.ISkill;
import org.springframework.stereotype.Component;
public class Xing implements ISkill {
private String Name ="Xing";
public void setName(String name) {
Name = name;
}
public void q(){
System.out.println(String.format("%s Q",this.Name));
}
public void w(){
System.out.println(String.format("%s W",this.Name));
}
}
2.2.2、修改demo1的HeroConfiguration类
package com.fcors.fcors.sample;
import com.fcors.fcors.sample.hero.Xing;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class HeroConfiguration {
@Bean
public ISkill xing(){
Xing aaa = new Xing();
aaa.setName("Fcors");
return aaa;
}
}
为什么要隔离到配置文件中
- 配置文件集中性
- 清晰(没有业务逻辑)
demo3:把参数放在文件中
3.1把参数添加到main/resources/application.properties中
server.port=8081
mysql.port=3306
mysql.url=192.168.8.8
3.2在sample创建一个package(database)
在package中创建一个MySQL类,在sample下面创建一个接口(IConnect),让MySql类实现
MySql类。因为该类是通过configuration注入容器,所以不需要加入@component,如果此处加了,在配置类Configuration的文件添加@ Configuration 会报错
package com.fcors.fcors.sample.database;
import com.fcors.fcors.sample.IConnect;
public class MySql implements IConnect {
private String Ip;
public void setIp(String ip) {
Ip = ip;
}
public void setPort(String port) {
Port = port;
}
private String Port;
public void connent(){
System.out.println(String.format("IP:%s,+Port:%s",this.Ip,this.Port));
}
}
IConnect的源码
package com.fcors.fcors.sample;
public interface IConnect {
void connent();
}
3.3在/sample中创建一个配置类Configuration
此处采用Setter的方式。如果需要引用文件配置的参数,则在参数上面声明@Value(“${mysql.port}”)
package com.fcors.fcors.sample;
import com.fcors.fcors.sample.database.MySql;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class DatabaseConfiguration {
@Value("${mysql.ip}")
private String ip;
@Value("${mysql.port}")
private String port;
@Bean
public IConnect mysql(){
MySql aaa = new MySql();
aaa.setIp(this.ip);
aaa.setPort(this.port);
return aaa;
}
}
3.4、调用具体的bean
package com.fcors.fcors.api.v1;
import com.fcors.fcors.sample.IConnect;
import com.fcors.fcors.sample.ISkill;
import com.fcors.fcors.sample.database.MySql;
import com.fcors.fcors.sample.hero.Diana;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Lazy;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/v1/api/")
public class TestController {
@Autowired
private IConnect mysql;
@GetMapping("/test3")
public String test2(){
mysql.connent();
return "Hello Fox is testing~";
}
}
实验结束。
为什么需要把@Configuration单独一节讲解。因为把配置独立在文件中,才更好符合ICO的思想,才更好实现OCP【开闭原则】