茂展的分享博客

spring注解驱动开发(一)

spring注解驱动开发(一)

初步介绍

spring注解驱动开发随着springboot这个简洁化开发,约定大于配置的大环境下,spring注解版知识点使用的也开始越来越多,所以我已经学习了基础springboot之后果断停止,开始学习spring注解驱动开发,下面是我总结的一些注解知识,这个页面会一直更新,用于以后的查阅

1、@Configurable注解以及@Bean的使用

Configurable表示这个一个配置类,代替原先xml配置
之前我们用xml做DI(依赖注入),现在我们可以通过class的方式来声明一个配置类
xml配置

1
2
3
4
5
6
7
8
9
10
11
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">

<bean id="person" class="cn.itcast.pojo.Person">
<property name="username" value="lmx"></property>
<property name="password" value="123"></property>
</bean>

</beans>

现在可以使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package cn.itcast.config;

import org.springframework.beans.factory.annotation.Configurable;
import org.springframework.context.annotation.Bean;

import cn.itcast.pojo.Person;

@Configurable
public class MyConfig {

@Bean(name="lmx")
public Person person() {
return new Person("lmz","456");
}
}

上面的bean代替旧的即<bean/>可以实现向容器注册组件,其中bean的name属性指的是注册组件在容器中的ID,默认是方法名作为组件的ID

然后通过下面的测试,果然简单有效,赞!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
package cn.itcast.test;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import cn.itcast.config.MyConfig;
import cn.itcast.pojo.Person;

public class MainTest {

public static void main(String[] args) {
// ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
// Person person = (Person)applicationContext.getBean("person");
// System.out.println("姓名:"+person.getUsername());
// System.out.println("密码:"+person.getPassword());

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class);
Person bean = context.getBean(Person.class);
System.out.println("姓名:"+bean.getUsername());
System.out.println("密码:"+bean.getPassword());
String[] beanNamesForType = context.getBeanNamesForType(Person.class);
for (String string : beanNamesForType) {
System.out.println(string);
}
}
}


2、@ComponentScan包扫描注解

context:component-scan主要用于扫描对应包下面的注解到容器中,一般有以下注解

  1. @Controller
  2. @Service
  3. @Repository
  4. @Component

对应的xml配置

<context:component-scan base-package="cn.itcast"/>’

用class类文件的方式,把下面配置配在config文件的上面,这样可以实现包扫描
@ComponentScan(basePackages= {“cn.itcast”})’

@excludeFilters可以除去不想扫描进容器的注解

1
2
3
4
@ComponentScan(basePackages= {"cn.itcast"},excludeFilters= {
@Filter(type=FilterType.ANNOTATION,classes=Controller.class),
@Filter(type=FilterType.ANNOTATION,classes=Service.class)
})

use-default-filters这个语句主要是关闭默认扫描对应包下面的所有注解

@includeFilters中要把use-default-filters设置成false

xml中这样写

<context:component-scan base-package="cn.itcast" use-default-filters="false" />

使用class文件这样写就ok了

1
2
3
4
@ComponentScan(basePackages = {"cn.itcast"},includeFilters = {
@Filter(type=FilterType.ANNOTATION,classes=Controller.class),
@Filter(type=FilterType.ANNOTATION,classes=Service.class)
},useDefaultFilters = false)

由于java8以上才有@Repeatable这个注解,表示可以注解重复,但是java8以下不支持,所以我们要做兼容性
有一个注解@ComponentScans,可以包含多个@ComponentScan


3、 @Scope注解

扫描到容器的默认是单实例的我们可以通过scope改变默认值
xml中我们是这样来表示scope的

1
2
3
4
<bean id="person" class="cn.itcast.pojo.Person" scope="prototype">
<property name="username" value="lmx"></property>
<property name="password" value="123"></property>
</bean>

class类方式在@Bean注解上添加@Scope

注: 单实例是ioc容器启动的时候就就把对象创建放进容器了,但多实例是什么时候调用就什么时候创建

例如:@Scope('prototype')这个表明扫描进容器的组件是多实例的,当然我们也可以使用@Scope('singleton')或者不写,可以实现单实例

1
2
3
4
5
@Scope(value="SCOPE_PROTOTYPE")
@Bean(name="lmx")
public Person person() {
return new Person("lmz","456");
}


4、 @Lazy懒加载的使用

把这个注解放在@Bean的上面表示懒加载,即IOC容器启动的时候创建,什么时候使用什么时候创建

注:这个属性主要针对的是单实例

5、 @Conditional条件注解的使用

这个注解在springboot的底层源码用的最多,所以有必要好好深挖一下
我写了一个demo

1
2
3
4
5
6
7
8
9
10
11
@Conditional(WindowsCondition.class)
@Bean(name="bill")
public Person person01() {
return new Person("Bill Gates","123");
}

@Conditional(LinuxCondition.class)
@Bean(name="linus")
public Person person02() {
return new Person("linus","456");
}

分别创建WindowsCondition、LinuxCondition,都要实现Condition接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public class LinuxCondition implements Condition{

//参数 context 上下文环境
// 参数 metadata 当前注释此注解的信息
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {

// //获得ioc使用的beanfactory
// ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
//
// //获取类加载器
// ClassLoader classLoader = context.getClassLoader();
//
// //获取bean定义的注册类
// BeanDefinitionRegistry registry = context.getRegistry();

// //判断对应的bean是不是在ioc容器中已经存在
// boolean isExist = registry.containsBeanDefinition("lmx");
//
//获取当前系统环境信息
Environment environment = context.getEnvironment();
//获取操作系统属性
String property = environment.getProperty("os.name");
if(property.contains("Linux"))
return true;
return false;
}

}

1
2
3
4
5
6
7
8
9
10
11
12
public class WindowsCondition implements Condition{

public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
// TODO Auto-generated method stub
Environment environment = context.getEnvironment();
String property = environment.getProperty("os.name");
if(property.contains("Windows"))
return true;
return false;
}

}

然后做测试

1
2
3
4
5
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class);
String[] strings = context.getBeanNamesForType(Person.class);
for (String string : strings) {
System.out.println(string);
}

结果:由于我的系统是Windows,所以ioc容器中注册的组件id是 bill

下一篇还有spring注解驱动开发(二)

------本文结束感谢阅读------
🐶 您的支持将鼓励我继续创作 🐶