[Spring]Annotation-based container configuration_AnotationBasis_02

@Component @Repository @Service @Controller

本质上以上四类没有区别,但是在你定义应用分层的时候 aop的时候 这些不同语义的注解 就有不同意义,未来Spring是否会给予这些语义注解特殊的意义还并不清楚


在配置java类里面注解@ComponentScan(basePackages = "com.domain")的情况下,会自动扫描com.domain包里的所有类,扫描里面带有@Componet,@Repository,@Service..等等注解的类

该句等同于在xml配置文件里面加入了

<context:component-scan base-package="com.javaconfig.domain"/> 

同时@ComponentScan可以在加载包的时候,排除掉一些类,或者包含某些类

@ComponentScan(basePackages = "org.example",
        includeFilters = @Filter(type = FilterType.REGEX, pattern = ".*Stub.*Repository"),
        excludeFilters = @Filter(Repository.class))

表示:扫描org.example包下所有带有@Component衍生的各种语义注解,同时包含该包下的匹配 .*Stub.*Repository类型的(正则匹配),排除扫描Repository.class

base-package的配置,从表面意思来看这是个“基本包”,表示下面的过滤路径是基于这个包的

更多过滤方式参考spring-reference


@Component

扫描一个类注册一个bean

@Component
public class Football {
	@Override
	public String toString() {
		// TODO Auto-generated method stub
		return "football";
	}
}
这就注册了一个名为football的bean 命名规则为首字母小写,如果起始的两个字母都是大写,则不小写首字母。

@Component
public class XYclass {

}
注册了一个XYclass的bean
XYclass xyz = ctx.getBean("XYclass",XYclass.class);
获得该bean



@Bean

以类似工厂的方式产生bean,注意@Bean所在类必须要被spring所扫描到

Tool1:

public class Hammer implements Tool {
	public void doWork() {
		System.out.println("using hammer to smash something");
	}
}
Tool2:

public class Scissors implements Tool{
	public void doWork() {
		System.out.println("using scissors to cut something");
	}
}

ToolBox:

public class ToolBox {
	private Tool[] tools;

	public ToolBox(Tool t1, Tool t2) {
		tools = new Tool[] { t1, t2 };
	}

	public Tool[] getTools() {
		return tools;
	}

	public void setTools(Tool[] tools) {
		this.tools = tools;
	}

}



BeanFactory:
@Component
public class ToolFactory {

	@Bean
	@Qualifier("t1")
	public Tool hammer() {
		return new Hammer();
	}

	@Bean
	@Qualifier("t2")
	public Tool scissors() {
		return new Scissors();
	}

	@Bean
	public ToolBox toolBox(@Qualifier("t1") Tool t1, @Qualifier("t2") Tool t2,
			@Value("this is just tool box") String description) {
		System.out.println(description);
		return new ToolBox(t1, t2);
	}
}

Unit Test:

	@Test
	public void beanTest() {
		Tool t1 = ctx.getBean("hammer",Tool.class);
		Tool t2 = ctx.getBean("scissors",Tool.class);
		t1.doWork();
		t2.doWork();
		ToolBox tb = ctx.getBean("toolBox",ToolBox.class);
		
	}

@Bean产生的bean命名方式 就是方法名字 同时@Bean也会按照类型注入参数


@Configuration 和 @Component 的区别 

@Configuration也是从@Component 衍生出来的注解,但是@Component 相比@Configuration不同点在于,@Component 并没有通过CGLIB 增强调用所注册bean的内部方法和fields调用的。还有@Configuration内的@bean注解的方法 不能为final,因为这需要被CGLIB所重写。


@Component @Repository @Service @Controller等注解 也提供了 生成bean非默认名称方式命名

@Service("myMovieLister")
public class SimpleMovieLister { // ...
}
比如该bean名称就会是myMovielister



@Scope

提供了在注册bean的时候申明该bean的lifecycle

@Scope("prototype")
@Repository
public class MovieFinderImpl implements MovieFinder {
// ...
}


@Configuration

是类级注册bean的注解,该类自身被注册为bean,并且其内的@Bean注解的方法 都会注册为bean。并且顾名思义,这就是一个配置类。

@Configuration
public class AppConfig {
	
	@Bean
	public Foo foo(Bar bar){
		return new Foo(bar);
	}
	
	@Bean
	public Bar bar(){
		return new Bar();
	}
}

这里申明的都是单例实类

Unit Test:

@Test
	public void beanTest2() {
		Foo foo = ctx.getBean("foo", Foo.class);
		Foo foo2 = ctx.getBean("foo", Foo.class);
		Bar bar = ctx.getBean("bar", Bar.class);
		Bar bar2 = ctx.getBean("bar", Bar.class);
		assertEquals(foo, foo2);
		assertEquals(bar, bar2);
		assertEquals(foo.getBar(), foo2.getBar());
	}

测试通过


@Import

导入配置类

@Configuration @Import(ConfigA.class) public class ConfigB {
@Bean
public B b() { return new B();
} }



@ImportResource

导入配置文件

@ImportResource(value = "TestCase_01.xml")



@Condtional

@Conditional注解主要用在以下位置:
类级别可以放在注标识有@Component(包含@Configuration)的类上
作为一个meta-annotation,组成自定义注解
方法级别可以放在标识由@Bean的方法上
如果一个@Configuration的类标记了@Conditional,所有标识了@Bean的方法和@Import注解导入的相关类将遵从这些条件。

简单的说就是根据某些情况选择合适的类进行注册

首先需要编写条件,条件类必须实现Condtion接口的matches方法

判断是否为Mac os

public class MacOsCondition implements Condition{
	public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
		
		return context.getEnvironment().getProperty("os.name").contains("Mac OS X");
	}
}
判断是否为Linux

public class LinuxCondition implements Condition{
	public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
		// TODO Auto-generated method stub
		return context.getEnvironment().getProperty("os.name").contains("Linux");
	}
}

注册bean的时候或者注册整个类的时候用上

	@Bean(name = "systemService")
	@Conditional(LinuxCondition.class)
	public SystemService linuxService() {
		return new LinuxService();
	}

	@Bean(name = "systemService")
	@Conditional(MacOsCondition.class)
	public SystemService macService() {
		return new MacOsService();
	}

根据操作系统不同选择不同的服务

Unit Test:

@Test
	public void conditionTest() {
		SystemService service = ctx.getBean("systemService",SystemService.class);
		service.service();
	}



@Profile

如果在开发时进行一些数据库测试,希望链接到一个测试的数据库,以避免对开发数据库的影响。

该注解提供了灵活的在多个副本之间切换的方法

注册了一个用于开发测试的mockDBService和一个release的MysqlDBService

	@Bean(name = "dbService")
	@Profile("dev")
	public DBService mockDBService(){
		return new MockDBService();
	}
	
	@Bean(name = "dbService")
	@Profile("rc")
	public DBService MysqlDBService(){
		return new MysqlDBService();
	}
	

在进行单元测试的时候

使用@ActiveProfiles(value = "dev")激活所要使用的副本

Unit Test:

@Test
	public void profileTest() {
		DBService dbService = ctx.getBean(DBService.class);
		System.out.println(dbService.count("select * from users"));
	}

也可以使用java激活方式

ctx.getEnvironment().setActiveProfiles("dev");
		ctx.register(AppConfig.class);
		ctx.refresh();




Spring Boot Configuration Processor 是一个用于生成配置元数据的注解处理器,可以帮助我们在编译时生成配置元数据,方便 IDE 自动生成配置属性的提示和文档,提高开发效率。 下面是使用 Spring Boot Configuration Processor 的步骤: 1. 添加 Maven 依赖: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> <optional>true</optional> </dependency> ``` 2. 在配置类上添加 `@ConfigurationProperties` 注解,指定配置属性的前缀: ```java @ConfigurationProperties(prefix = "myconfig") public class MyConfig { private String name; private int age; // getters and setters } ``` 3. 在配置属性上添加 `@ConfigurationProperties` 注解,指定属性名和默认值: ```java public class MyConfig { @ConfigurationProperties("name") private String name = "default"; @ConfigurationProperties("age") private int age = 18; // getters and setters } ``` 4. 在配置类同级目录下创建 `META-INF/spring-configuration-metadata.json` 文件,配置属性的元数据信息: ```json { "groups": [ { "name": "myconfig", "type": "com.example.demo.MyConfig", "sourceType": "com.example.demo.MyConfig" } ], "properties": [ { "name": "myconfig.name", "type": "java.lang.String", "description": "Name of the user", "defaultValue": "default" }, { "name": "myconfig.age", "type": "java.lang.Integer", "description": "Age of the user", "defaultValue": 18 } ] } ``` 5. 在 IDE 使用配置属性时,会自动提示和补全属性名、类型、描述和默认值等信息。 注意:在使用 `@ConfigurationProperties` 注解时,需要在配置类上添加 `@EnableConfigurationProperties` 注解,或者在 Spring Boot 应用程序主类上添加 `@EnableConfigurationProperties(MyConfig.class)` 注解,才能使属性生效。 参考文档:https://docs.spring.io/spring-boot/docs/current/reference/html/appendix-configuration-metadata.html#configuration-metadata-annotation-processor
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值