03-SpringIOC基于注解配置
一、Spring基于注解配置
1.1、组件注册注解
(1)、@Configuration
用于定义配置类,可替换xml配置文件,被注解的类内部包含有一个或多个被@Bean注解的方法,这些方法将会被AnnotationConfigApplicationContext或AnnotationConfigWebApplicationContext类进行扫描,并用于构建bean定义,初始化Spring容器。
注意:@Configuration注解的配置类有如下要求:
-
@Configuration不可以是final类型;
-
@Configuration不可以是匿名类;
-
嵌套的configuration必须是静态类。
@Configuration
public class AppConfig {
}
(2)、@ComponentScan
用于指定 spring 在初始化容器时要扫描的包。 作用和在 spring 的 xml 配置文件中的:<context:component-scan base-package="org.example"/>
@Configuration
@ComponentScan(basePackages = "org.example")
public class AppConfig {
// ...
}
/*
basePackages与value: 用于指定包的路径,进行扫描
basePackageClasses: 用于指定某个类的包的路径进行扫描
nameGenerator: bean的名称的生成器
useDefaultFilters: 是否开启对@Component,@Repository,@Service,@Controller的类进行检测
includeFilters: 包含的过滤条件
FilterType.ANNOTATION:按照注解过滤
FilterType.ASSIGNABLE_TYPE:按照给定的类型
FilterType.ASPECTJ:使用ASPECTJ表达式
FilterType.REGEX:正则
FilterType.CUSTOM:自定义规则
excludeFilters: 排除的过滤条件,用法和includeFilters一样
*/
(3)、@Bean
该注解只能写在方法上,表明使用此方法创建一个对象,并且放入 spring 容器。
@Configuration
public class AppConfig {
@Bean
public TransferServiceImpl transferService() {
return new TransferServiceImpl();
}
}
(4)、@Scope
指定对象的作用范围:
- singleton :默认值,单例的.
- prototype :多例的.
- request :WEB 项目中,Spring 创建一个 Bean 的对象,将对象存入到 request 域中.
- session :WEB 项目中,Spring 创建一个 Bean 的对象,将对象存入到 session 域中.
- global session:WEB 项目中,应用在 Portlet 环境.如果没有 Portlet 环境那么globalSession 相当于 session.
@Configuration
public class FactoryMethodComponent {
@Bean @Scope("prototype")
public TestBean prototypeInstance(InjectionPoint injectionPoint) {
return new TestBean("prototypeInstance for " + injectionPoint.getMember());
}
}
(5)、@Lazy
是否延迟加载
(6)、@Conditional
按照一定的条件进行判断,满足条件给容器注册bean。
//此注解可以标注在类和方法上
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Conditional {
Class<? extends Condition>[] value();
}
从代码中可以看到,需要传入一个Class数组,并且需要继承Condition接口,实现matches方法,返回true则注入bean,false则不注入。:
public interface Condition {
boolean matches(ConditionContext var1, AnnotatedTypeMetadata var2);
}
(7)、@Import
用于导入其他配置类((4.2 版本之前只可以导入配置类,4.2版本之后 也可以导入普通类)),在引入其他配置类时,可以不用再写@Configuration 注解。功能就是和Spring XML 里面 的 一样
@Configuration
public class ConfigA {
@Bean
public A a() {
return new A();
}
}
@Configuration
@Import(ConfigA.class)
public class ConfigB {
@Bean
public B b() {
return new B();
}
}
三种用法:
- 直接填class数组方式
-
@Import({ 类名.class , 类名.class... }) public class TestDemo {}
-
- ImportSelector方式【重点】
-
public class Myclass implements ImportSelector { /* String[]: 就是我们实际上要导入到容器中的组件全类名【重点 】 AnnotationMetadata:表示当前被@Import注解给标注的所有注解信息【不是重点】 */ @Override public String[] selectImports(AnnotationMetadata annotationMetadata) { return new String[]{"com.yc.Test.TestDemo3"}; } } @Import({ 类名.class , Myclass.class... }) public class TestDemo {}
-
- ImportBeanDefinitionRegistrar方式
-
public class Myclass2 implements ImportBeanDefinitionRegistrar { /* AnnotationMetadata: 表示当前被@Import注解给标注的所有注解信息 BeanDefinitionRegistry:表示用于注册定义一个bean */ @Override public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry beanDefinitionRegistry) { //指定bean定义信息(包括bean的类型、作用域...) RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(TestDemo4.class); //注册一个bean指定bean名字(id) beanDefinitionRegistry.registerBeanDefinition("TestDemo4444",rootBeanDefinition); } } @Import({ 类名.class , Myclass2.class... }) public class TestDemo {}
-
(8)、Factorybean
public interface FactoryBean<T> {
//返回的对象实例
T getObject() throws Exception;
//Bean的类型
Class<?> getObjectType();
//true是单例,false是非单例 在Spring5.0中此方法利用了JDK1.8的新特性变成了default方法,返回true
boolean isSingleton();
}
@Component
public class FactoryBeanLearn implements FactoryBean {
@Override
public Object getObject() throws Exception {
//这个Bean是我们自己new的,这里我们就可以控制Bean的创建过程了
return new FactoryBeanServiceImpl();
}
@Override
public Class<?> getObjectType() {
return FactoryBeanService.class;
}
@Override
public boolean isSingleton() {
return true;
}
}
1.2、生命周期注解
(1)、@Bean指定初始化和销毁方法
public class Car {
public Car() {
System.out.println("无参构造初始化");
}
public void init() {
System.out.println("CarBean---init");
}
public void destory() {
System.out.println("CarBean---destory");
}
}
@Configuration
public class BeanLife {
@Bean(initMethod="init", destroyMethod="destory")
public Car car() {
return new Car();
}
}
(2)、InitializingBean和DisposableBean接口
@Component
public class Cat implements InitializingBean, DisposableBean{
public Cat() {
System.out.println("cat 构造函数...");
}
//初始化方法
public void afterPropertiesSet() throws Exception {
System.out.println("cat afterPropertiesSet");
}
//销毁方法
public void destroy() throws Exception {
System.out.println("cat destory");
}
}
(3)、@PostConstruct和@Predestory
public Class XXX {
public XXX() {}
@PostConstruct
private void init() {
System.out.println("@PostConstruct将在依赖注入完成后被自动调用" );
}
@Predestory
private void preDestory() {
System.out.println("XXX 正在被容器删除");
}
}
(4)、BeanPostProcessor接口
1.3、自动装配注解
(1)、@Autowired
自动按照类型注入。当使用注解注入属性时,set 方法可以省略。它只能注入其他 bean类型。当有多个类型匹配时,使用要注入的对象变量名称作为 bean 的 id,在 spring 容器查找,找到了也可以注入成功。找不到就报错。
(2)、@Qualifier
在自动按照类型注入的基础之上,再按照 Bean 的 id 注入。它在给字段注入时不能独立使用,必须和@Autowire 一起使用;但是给方法参数注入时,可以独立使用。
(3)、@Primary
自动装配时当出现多个Bean候选者时,被注解为@Primary的Bean将作为首选者,否则将抛出异常
(4)、@Resource
默认按名称装配,当找不到与名称匹配的bean才会按类型装配。
(5)、@Inject
基于类型来查找bean注入的,如果需要指定名称beanName
(6)、Profile
1.4、属性赋值注解
(1)、@Value
主要用于赋值,该值可以是取值配置文件中的,也可以直接赋值,也可以使用SpEl表达式进行计算的结果,抑或直接从环境变量中获取。 该注解不能处理日期类赋值。
- 基本数值
- 可以写SpEL; #{}
- 可以写${};取出配置文件【properties】中的值(在运行环境变量里面的值)
(2)、@PropertySource加载配置文件
主要用于加载配置文件,value值为classpath等价于 <context:property-placeholder location="classpath:student.properties"/>
-
若使用@Component方式注入对象,则@PropertySource放置在普通类Student或配置类中都可以
-
若使用@Bean方式注入Student对象,则@PropertySource必须放在配置类上加载
方式一:
@PropertySource({"classpath:/student.properties"})//指定配置文件classPath
@Component
public class Student {
@Value("张三")//直接赋值
private String name;
@Value("${stu.name}")//从配置文件中取值
private String alias;
@Value("${os.name}")//从容器中读取环境变量
private String system;
@Value("#{33-12}")//使用SpEL 计算
private Integer age;
// @Value("${stu.birthDate}")//不能处理日期
private Date birthDate;
@Value("${stu.hasNickName}") //布尔值
private Boolean hasNickName;
}
方式二:
public class Student {
@Value("张三")//直接赋值
private String name;
@Value("${stu.name}")//从配置文件中取值
private String alias;
@Value("${os.name}")//从容器中读取环境变量
private String system;
@Value("#{33-12}")//使用SpEL 计算
private Integer age;
// @Value("${stu.birthDate}")//不能处理日期
private Date birthDate;
@Value("${stu.hasNickName}") //布尔值
private Boolean hasNickName;
}
@Configuration
@PropertySource({"classpath:/student.properties"})
public class PropertyValueConfig {
@Bean
public Student student(){
return new Student();
}
}

浙公网安备 33010602011771号