(一)spring的bean注册

Spring框架中支持了两种不同形式的IOC容器初始化方式,一种是基于XML的容器初始化,另外一种是基于注解的初始化方式,初始化容器时使用的具体初始化类不同。

基于xml的方式:

ClasspathXmlApplicationContext

基于annotation的方式:

AnnotationConfigApplicationContext

他们都是AbstractApplicationContext的子类,在该类中定义了基于xml和annotation初始化容器及注册bean的公共流程,后面文章会具体分析其底层源码实现。下面先体验一下基于xml和annotation的bean注册方式。

基于xml的bean配置方式已经不再流行,这里简单介绍,能看懂代码就行。

一 基于xml的方式

1 示例bean

 1 package demo.ioc.xml;
 2 
 3 public class Person {
 4     private String uuid;
 5 
 6     public String getUuid() {
 7         return uuid;
 8     }
 9 
10     public void setUuid(String uuid) {
11         this.uuid = uuid;
12     }
13 
14     @Override
15     public String toString() {
16         return "Person{" +
17                 "uuid='" + uuid + '\'' +
18                 '}';
19     }
20 }
2 xml配置
 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <beans xmlns="http://www.springframework.org/schema/beans"
 3        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 4        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
 5 <!--    指定bean的ID以及bean对应的类型-->
 6     <bean id="person" class="demo.ioc.xml.Person">
 7 <!--        指定bean的属性名以及属性值, 此处使用基础属性
 8             也可以使用引用类型属性,来引用另外一个bean  -->
 9         <property name="uuid" value="123"></property>
10     </bean>
11 </beans>

3  测试

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestMain {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        Person person =  context.getBean("person", Person.class);
        System.out.println(person);
    }
}
输出:Person{uuid='123'}

二 基于annotation的方式

基于注解的bean配置方式,现在是主流,接下来详细介绍

(1) 基于@Component

1 示例bean

package demo.ioc.annotation.component;

import org.springframework.stereotype.Component;

@Component
public class Person {
    private String uuid;

    public String getUuid() {
        return uuid;
    }

    public void setUuid(String uuid) {
        this.uuid = uuid;
    }

    @Override
    public String toString() {
        return "Person{" +
                "uuid='" + uuid + '\'' +
                '}';
    }
}

2  测试

package demo.ioc.annotation.component;

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

public class TestMain {
    public static void main(String[] args) {
//        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        ApplicationContext context = new AnnotationConfigApplicationContext(demo.ioc.annotation.component.Person.class);
        Person person =  context.getBean("person", Person.class);

        System.out.println(person);
    }
}
输出:Person{uuid='null'}

可以看到相比xml配置方式,配置更加简单,但是没有办法注入属性值

3 注解解析

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package org.springframework.stereotype;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Component {
// 生成bean的名称,相当于xml配置文件的id,默认名称是目标Bean的Class类型第一个字符小写,例如Person的默认Bean名称是person String value()
default ""; }

@Component是spring的基础注解,使用该注解标注的类,表示spring的IOC容器会在适当的时机实例化该类,并交由IOC容器管理,因此我们就不用显示实例化该类。

(2)基于@Configuration和@Bean

1 示例Bean

package demo.ioc.annotation.configuration;

import java.util.UUID;

public class Person {
private String uuid;

public String getUuid() {
return uuid;
}

public void setUuid(String uuid) {
this.uuid = uuid;
}

@Override
public String toString() {
return "Person{" +
"uuid='" + uuid + '\'' +
'}';
}

private void init() {
uuid = UUID.randomUUID().toString();
System.out.println(uuid);
}

private void destroy() {
uuid = null;
System.out.println(uuid);
}
}

 

2  配置类

package demo.ioc.annotation.configuration;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class BeanConfig {

@Bean(initMethod = "init", destroyMethod = "destroy")
public Person getPerson() {
Person person = new Person();
person.setUuid("1234");
return person;
}
}

 

3 测试

package demo.ioc.annotation.configuration;

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.AbstractApplicationContext;

public class TestMain {
public static void main(String[] args) {
// ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
AbstractApplicationContext context = new AnnotationConfigApplicationContext(BeanConfig.class);
demo.ioc.annotation.configuration.Person person = context.getBean("getPerson", Person.class);

System.out.println(person);

context.close();
}
}
输出:
61ab9f03-544e-41a2-9ab3-767e02cf533e
Person{uuid='61ab9f03-544e-41a2-9ab3-767e02cf533e'}
null

该方法相当于@Component注解,能够设置属性,更加灵活。

 

4 注解解析

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package org.springframework.context.annotation;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.stereotype.Component;

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Configuration {
//配置类的名称 String value()
default ""; }

可以看到@Configuration注解本身也使用了@Component,表示该类也由Spring的IOC负责实例化,不过标注了@Configuration注解的类还允许使用@Bean

标注非private以及final方法,标注之后,容器在适当的时候,会扫描配置类,按照标注了@Bean注解的方法逻辑去创建Bean,并注入到容器中。

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package org.springframework.context.annotation;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.beans.factory.annotation.Autowire;
import org.springframework.core.annotation.AliasFor;

@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Bean {
//指定Bean的名称,当没有指定时,默认使用被标注的方法名作为Bean的名称
//AliasFor表示与name互为别名,效果一样,指定其一即可 @AliasFor(
"name") String[] value() default {};
//与value属性一样 @AliasFor(
"value") String[] name() default {};
//用的不多,不去了解 Autowire autowire()
default Autowire.NO;
//指定Bean的初始化方法,为Bean中的某个方法名,不受修饰符的干扰,在Bean实例化后调用 String initMethod()
default "";
//指定Bean的自动销毁方法,在Bean的生命周期结束时,会自动调用该方法,同样不受修饰符的限制 String destroyMethod()
default "(inferred)"; }

 

posted @ 2022-07-16 12:58  取名好烦呀  阅读(321)  评论(0编辑  收藏  举报