spring注解学习--如何将可重用组件(bean)加入spring容器

2 篇文章 0 订阅

导语

学了ssm很久以后,再来回顾spring框架的时候发觉已经忘了不少东西了,但是这个忘了不少的情况却让我蛋疼了一天,所以今天专门花个时间来记录下spring是如何创建bean的,创建bean的方式有哪些,做一个总结

spring本质是一个对象容器,也可以认为是组件容器,总之就是用来装可重用(java)组件的,传统方式是使用new这个关键词来获取对象,有了spring后不仅可以在系统之间减少耦合性,也改变了业界构建系统的方式方法。在spring中大量使用java反射创建对象,这种创建对象的方式在jdk1.8后有了翻倍的性能提升,所以现在业界也普遍使用jdk1.8原因所在

目录

导语

环境声明

理解要点

java技术体系中获得类实例(对象)的方式有哪些?

1.new

2.反射

spring获取bean的注解

1.spring完全注解开发充要条件

2.申明类的实例化对象存入到spring容器的注解

@Component

@Service

@Repository

@Controller

 通过spring容器来使用以上被注解的类

3.申明方法返回对象存入到spring容器的注解

@Bean


环境声明

  • jdk version : 1.8
  • IDE : idea community 2019.2
  • maven version : 3.6.2
  • spring version : 5.2.1.RELEASE

理解要点

  1. spring的@Component()用于标注在类上,标注上该注解的类在运行时,会被加入到spring容器中
  2. spring中,被@Server() 、@Controller() 、@Repository三个注解的类,在运行时也会被放入spring容器中,但是他们相比@Component又有了明显web分层概念,Component就单纯的吧该类添加进spring容器,而其他三个就还做了其他事情
  3. spring既然有了bean管理,那么bean在很多地方是有bean的生命周期的,比如有的bean仅仅需要使用一次就会被废弃(比如初始化组件),而有些bean是需要重复使用的(持久层组件),这个时候就spring就引入了Scope的概念,也就是
  4. spring的本质上是bean容器,所以他的主要目的在于管理bean(或者说在于解决代码之间的依赖关系)bean的生命周期
  5. spring-boot是基于spring的

java技术体系中获得类实例(对象)的方式有哪些?

1.new

在开始学习java面向对象的时候,我们都是通过new来获得一个实实在在的对象的,但是这种方式获得对象,一旦这个类不能存在的时候就麻烦了,连编译都通不过,更别说运行了!但有时候我们对这个类的依赖性有并不强,又影响整体的创建对象的方式有时候很让人头疼,而且一旦出错就影响整个线程的。

2.反射

我们知道在学jdbc操作数据库的时候有个Class.forName()这个就是通过路径来加载我们需要的类,这个时候返回一个类的信息,我们通过类信息来模拟出一个对象,也可以获得一个类实例,这就是spring创建类实例的基础。这样创建对象的方式就算类不存在也不影响程序的编译,就算出错也可以控制,不至于把整个线程搞崩。这是反射的优势所在

spring获取bean的注解

1.spring完全注解开发充要条件

要想完全通过注解的方式开发,就必须使用Configuration以及ComponentScan注解,因为这两个注解分别代表了spirng的xml配置文件,以及配置文件中指定要扫描的包范围。因为spring还是离不开配置信息,spring只有通过配置信息才能工作,这也是大部分框架为了实现解耦的常用方式。配置信息中需要注明spring要扫描哪些包,扫描包的动机就在于扫描包中的类是否有需要spring接管(装入spring容器)的类,那么spring扫描了又怎么知道需不需要spring接管呢,那就是通过注解呗,因为反射可以得到类的注解信息。

package TT.config;

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

@Configuration
@ComponentScan(basePackages = "TT")
public class AppConfig {}

2.申明类的实例化对象存入到spring容器的注解

@Component

这种方式就是单纯的将被注解的类添加到spring容器,请看实例

package TT.entity;

import org.springframework.stereotype.Component;
//申明当前的类可以由spring容器接管(被加入到spring容器中),并给当前类取名叫person1
@Component("person1")
public class Person {
    public void sayHello(){
        System.out.println("你好我是"+this.getClass().getName());
    }
}

@Service

这个注解就是声明当前类为service层,也会被存入到spring容器,但是跟Component不一样,spring也是做过一些工作的

package TT.entity;

import org.springframework.stereotype.Service;

/**
 * 分层中的service层
 */
@Service
public class ServiceTT extends Person {

}

@Repository

用来声明持久层的代码,会被存入到spring容器中,跟但是跟Component不一样,spring也是做过一些工有关持久层的工作

package TT.entity;

import org.springframework.stereotype.Repository;

@Repository
public class RepositoryTT  extends Person{
}

@Controller

用来声明控制层的代码

package TT.entity;

import org.springframework.stereotype.Controller;

@Controller
public class ControllerTT extends Person{
}

 通过spring容器来使用以上被注解的类

package TT;

import TT.config.AppConfig;
import TT.entity.ControllerTT;
import TT.entity.Person;
import TT.entity.RepositoryTT;
import TT.entity.ServiceTT;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class Application {
    public static void main(String[] args) {
        //通过spring容器来使用我们之前被注解过的类
        ApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);
        //通过我们的别名获取类实例
        Person p=(Person) ac.getBean("person1");
        p.sayHello();
        //通过传入类信息获得类实例
        ServiceTT d = ac.getBean(ServiceTT.class);
        d.sayHello();
        ControllerTT c=ac.getBean(ControllerTT.class);
        c.sayHello();
        RepositoryTT r=ac.getBean(RepositoryTT.class);
        r.sayHello();
    }
}

 结果:

你好,我是TT.entity.Person
你好,我是TT.entity.ServiceTT
你好,我是TT.entity.ControllerTT
你好,我是TT.entity.RepositoryTT

3.申明方法返回对象存入到spring容器的注解

要说通过方法返回对象的形式要追溯到设计模式中去,这个设计模式就是工厂模式

假设我们代码中需要调用别人已经写好的工具包,而且这个工具包中的代码也已经无法修改了,他们代码中也没有使用spring框架,所以我们没有办法通过@ComponentScan扫面到别人的代码加入spring,因为别人的代码中没有@service、@Component、@Controller以及@Repository。

但我们可以通过调用工具包中的工厂方法来调用实例类,也可以通过直接实例化来调用别人写好的类,工具包中的工厂代码如下:

package TT.old_code.factory;

import TT.old_code.entity.ControllerTT;
import TT.old_code.entity.Person;
import TT.old_code.entity.RepositoryTT;
import TT.old_code.entity.ServiceTT;

public class BeanFactory {

    public static Person getControllerTT() {
        return new ControllerTT();
    }
    public static Person getService(){
        return new ServiceTT();
    }
    public static Person getRepositoryTT(){
        return new RepositoryTT();
    }
    public static Person getPerson(){
        return new Person();
    }
}

 所以,这时候spring的@Bean就诞生了

@Bean

我就将之前的代码改一改,现在AppConfig大概长这样

package TT.newCode.config;

import TT.old_code.entity.Person;
import TT.old_code.entity.RepositoryTT;
import TT.old_code.factory.BeanFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class AppConfig {
//现在我们可以调用别人代码中的工厂对象返回的对象存入spring容器
    @Bean("controllerTT1")
    public Person getControllerTT() {
        return BeanFactory.getControllerTT();
    }

    @Bean("service1")
    public Person getService() {
        return BeanFactory.getService();
    }
//我们也可以直接实例化别人工具代码中的类存入spring容器
    @Bean("repositoryTT1")
    public Person getRepositoryTT() {
        return new RepositoryTT();
    }

    @Bean("person")
    public Person getPerson() {
        return new Person();
    }
}

现在我们仍然正常使用spring容器,跟我们写的代码没有任何区别

package TT.newCode;

import TT.newCode.config.AppConfig;
import TT.old_code.entity.ControllerTT;
import TT.old_code.entity.ServiceTT;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class ApplicationOnBeanFactory {
    public static void main(String[] args) {
        ApplicationContext ac= new AnnotationConfigApplicationContext(AppConfig.class);
        ControllerTT configuration=(ControllerTT)ac.getBean("controllerTT1",ControllerTT.class);
        configuration.sayHello();
        ServiceTT s=ac.getBean(ServiceTT.class);
        s.sayHello();
    }
}

结果:

你好,我是TT.old_code.entity.ControllerTT
你好,我是TT.old_code.entity.ServiceTT

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值