@Configuration+@Bean的使用

89 篇文章 2 订阅
45 篇文章 1 订阅
 <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.2.12.RELEASE</version>
        </dependency>

在早期的时候,我们都是使用bean.xml的方式创建一个bean对象

<?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.xsd">

    <bean class="com.dmg.User" id="user">
        <property name="name" value="zhangsan"></property>
        <property name="age" value="18"></property>
    </bean>
</beans>
public class User {

    private String name;
    private int age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
public class Test {

    public static void main(String[] args) {
        ApplicationContext applicationContext=new ClassPathXmlApplicationContext("bean.xml");
        User user = (User) applicationContext.getBean("user");
        System.out.println(user);
    }
}

但是当我们使用注解的时候可以这样使用,注入到ioc容器中

@Configuration表示这是一个配置类,对应bean.xml

@Bean 表示 <bean class="com.dmg.User" id="user">

这里的user2就是bean id

@Configuration
public class TestConfig {



    @Bean
    public User user2(){
        User user=new User();
        user.setAge(66);
        user.setName("李四");
        return user;
    }
}

AnnotationConfigApplicationContext 表示注解配置应用上下文

使用了@Configuration这个注解,我们都可以访问到

public class Test {

    public static void main(String[] args) {
        ApplicationContext applicationContext=new AnnotationConfigApplicationContext(TestConfig.class);
        User user = (User) applicationContext.getBean("user2");
        System.out.println(user);
    }
}

我们也可以在@Bean(这里该改名字)

我们可以通过 applicationContext.getBeanDefinitionNames()来获取容器中的bean定义名称信息

AnnotationConfigApplicationContext能返回ApplicationContext是因为

最终继承的ApplicationContext,所以可以返回ApplicationContext

我们的容器中的user对象默认是单实例的,来看下场景

可以看到2次获取的时候都是true,这就是单实例

我们把applicationContext.getBean注释掉

在箭头位置加入一行数据

可以看到在单实例作用域下,先给容器加载数据,所以在容器中获取bean的时候直接从容器拿

我们在看下多实例,使用@Scope("prototype")

我们启动的时候,并没有看到打印的那一行内容,只有加载完毕的信息

我们把获取bean的注释放开

可以看到,获取一次bean,打印一次,结果为false,这就是多实例

我们可以在单实例环境下设置@Lazy 延时加载

等获取bean的时候,才创建对象

可以看到,获取bean也只打印一次,返回true

我们来看下@Bean手动指定初始化和销毁的方法

手动指定bean的生命周期

public class Sp   {


    public Sp(){
        System.out.println("对象创建了");
    }

    public void init(){
        System.out.println("对象初始化了");
    }

    public void destory(){
        System.out.println("对象销毁了");
    }
}

在initMethod写上初始化的方法

在destroyMethod写上销毁的方法

@Configuration
public class TestConfig {


    @Bean(initMethod = "init",destroyMethod = "destory")
    public Sp sp(){
        return new Sp();
    }

}

单实例环境下,容器启动的时候会创建对象,

容器销毁的时候,会销毁对象


public class Test {

    public static void main(String[] args) {
        AnnotationConfigApplicationContext applicationContext=new AnnotationConfigApplicationContext(TestConfig.class);

        System.out.println("容器创建完成了");
        applicationContext.close();
    }
}

我们在看下多实例的场景

设置@Scope("prototype")

可以看到并没去创建对象,只有在获取bean的时候,才创建对象

销毁的时候,容器也不会去销毁这个对象

我们还可以通过实现InitializingBean, DisposableBean

来写属性赋值之后的方法,销毁的方法

public class Sp implements InitializingBean, DisposableBean {


    private String name;

    public Sp(){
        System.out.println("对象创建了");
    }

    public void setName(String name) {
        System.out.println("属性赋值");
        this.name = name;
    }

    public void afterPropertiesSet() throws Exception {
        System.out.println("属性赋值之后执行");
    }

    public void destroy() throws Exception {
        System.out.println("对象销毁了");
    }
}
@Configuration
public class TestConfig {


    @Bean
    public Sp sp(){
        Sp sp=new Sp();
        sp.setName("aaa");
        return sp;
    }

}

我们还可以使用@PostConstruct 来设置对象创建完成并且属性赋值之后,进行初始化

使用@PreDestroy 在容器销毁bean之前执行此方法


public class Sp {


    private String name;

    public Sp(){
        System.out.println("对象创建了");
    }

    public void setName(String name) {
        System.out.println("属性赋值");
        this.name = name;
    }

    @PostConstruct
    public void aa(){
        System.out.println("对象创建之后,并且属性赋值之后执行");
    }

    @PreDestroy
    public void bb(){
        System.out.println("容器销毁对象之前执行");
    }
}

我们还可以实现BeanPostProcessor 后置bean处理器,来进行初始化之前的操作,初始化之后的操作


public class Linux implements BeanPostProcessor {


    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("在初始化之前执行:"+beanName);
        return bean;
    }

    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("在初始化之后执行:"+beanName);
        return bean;
    }

}
@Configuration
public class TestConfig {


    @Bean
    public Sp sp(){
        Sp sp=new Sp();
        sp.setName("aaa");
        return sp;
    }



    @Bean
    public Linux linux(){
        return new Linux();
    }


}

我们来看下源码分析,在postProcessBeforeInitialization方法打个断点

执行之后会先进入applyBeanPostProcessorsBeforeInitialization 执行bean后置处理器之前初始化方法

在这个result就拿到了bean的信息

然后再进入applyBeanPostProcessorsAfterInitialization

执行bean后置处理器之后初始化方法

等方法执行到postProcessAfterInitialization这里的时候,就会进入

我们linux类的postProcessAfterInitialization方法

初始化之前的操作和初始化之后的操作,都是在initializeBean这个方法里面去执行的

我们也可以实现ApplicationContextAware接口,在创建完对象,并且属性赋值之后,

使用应用程序上下文

public class Sp implements ApplicationContextAware {


    private ApplicationContext applicationContext;


    private String name;

    public Sp(){
        System.out.println("对象创建了");
    }

    public void setName(String name) {
        System.out.println("属性赋值");
        this.name = name;
    }

    @PostConstruct
    public void aa(){
        System.out.println("对象创建之后,并且属性赋值之后执行");
    }

    @PreDestroy
    public void bb(){
        System.out.println("容器销毁对象之前执行");
    }

    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext=applicationContext;
        System.out.println("在容器中使用应用上下文");
    }
}

进入源码ApplicationContextAwareProcessor类

可以看到他也是实现的BeanPostProcessor

我们进入invokeAwareInterfaces方法

可以看到当这个bean是实现了ApplicationContextAware

那么会进入对应的类去执行setApplicationContext方法

这样就能拿到应用程序上下文了,然后在其他方法就可以使用这个了

我们使用@PostConstruct和@PreDestroy这2个注解能执行

就是因为他的BeanPostProcessor类的postProcessBeforeInitialization方法

我们进入源码InitDestroyAnnotationBeanPostProcessor类

可以看到,在这里就能拿到初始化和销毁的方法,然后执行之后就进入了

对应的注解的方法

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
@Configuration和@Bean是Spring框架中用于定义Bean的注解。 @Configuration注解用于标记一个类,声明该类是一个配置类,用于替代传统的XML配置文件。在@Configuration注解的类中,可以使用@Bean注解来定义Bean对象,Spring会自动扫描@Configuration注解的类,并将其中的@Bean注解生效,创建相应的Bean对象。 下面是一个@Configuration + @Bean的案例: ```java @Configuration public class AppConfig { @Bean public HelloService helloService() { return new HelloServiceImpl(); } @Bean public WorldService worldService() { return new WorldServiceImpl(helloService()); } } ``` 在上面的代码中,AppConfig类使用@Configuration注解标记,表示这是一个配置类。该类中定义了两个@Bean注解的方法,分别用于创建HelloService和WorldService的Bean对象。 为了验证这个配置类是否生效,我们可以通过ApplicationContext获取相应的Bean对象,如下所示: ```java public static void main(String[] args) { ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class); HelloService helloService = context.getBean(HelloService.class); WorldService worldService = context.getBean(WorldService.class); System.out.println(helloService.sayHello()); System.out.println(worldService.sayHelloWorld()); } ``` 运行上面的代码,可以看到输出结果为: ``` Hello, World! Hello, World! - Hello from HelloServiceImpl ``` 说明我们成功地从ApplicationContext中获取了HelloService和WorldService的Bean对象,并且这些Bean对象是通过AppConfig类中的@Bean注解方法创建的。 总的来说,@Configuration注解用于标记配置类,@Bean注解用于定义Bean对象,并且这两个注解可以替代传统的XML配置文件,使得Spring框架更加简单、灵活和易于维护。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值