前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >spring-bean配置讲解

spring-bean配置讲解

作者头像
Java开发者之家
修改2021-09-01 11:01:08
4580
修改2021-09-01 11:01:08
举报
文章被收录于专栏:Java开发者之家Java开发者之家

# SpringIOC/DI概述:

# 配置bean

1.配置方式:基于XML文件的方式,基于注解的方式

2.Bean的配置方式:通过全类名(反射)、通过工厂方法啊(静态方法&实例化工厂方法)、FactoryBean

3.IOC容器BeanFactory&ApplicationContext

  • 依赖注入方式:属性注入、构造器注入
  • 注入属性值细节
  • 自动装配
  • bean直接关系:继承、依赖
  • bean的作用域:singleton/prototype/web环境-session、global session

# Spring Bean的讲解

# 继承

1.Spring允许继承bean的配置

2.子bean从父bean中继承配置,包括bean的属性配置

2.父bean可以作为模板,可以设置的abstract属性为true,这样就不会实例化bean

4.若一个bean的属性没有指定,则该bean必须为一个抽象bean

# 依赖

depends-on

代码语言:javascript
复制
<bean id="address" class="top.finen.spring.autowire.Address">
        <property name="city" value="Shanghai"></property>
        <property name="street" value="lujiazui"></property>
    </bean>
    <bean id="address2" class="top.finen.spring.autowire.Address" parent="address">
<!--    <property name="city" value="Shanghai"></property>-->
        <property name="street" value="Waitang"></property>
    </bean>
    <bean id="address3" class="top.finen.spring.autowire.Address" parent="address2">
        <!--            <property name="city" value="Shanghai"></property>-->
        <property name="street" value="Waitang"></property>
    </bean>
    <bean id="car" class="top.finen.spring.autowire.Car">
        <property name="brand" value="Audi"></property>
        <property name="price" value="300000"></property>
    </bean>
    <!-- 要求在配置Person时,必须有一个关联的car,这个bean必须依赖于Car这个bean -->
    <bean id="person" class="top.finen.spring.autowire.Person" depends-on="car">
        <property name="name" value="Tom"></property>
        <property name="address" ref="address3"></property>
    </bean>

# Bean的作用域

代码语言:javascript
复制
使用bean的scope属性来配置bean的作用域
默认值:singleton,容器初始化时创建bean实例,在整个容器的生命周期内只创建一个bean,单例的,初始化时就创建出来。
prototype:原型。在容器初始化时不创建bean的实例,而在每次请求时都创建一个新的bean实例,并返回
代码语言:javascript
复制
<!--
    使用bean的scope属性来配置bean的作用域
    默认值:singleton,容器初始化时创建bean实例,在整个容器的生命周期内只创建一个bean,单例的,初始化时就创建出来。
    prototype:原型。在容器初始化时不创建bean的实例,而在每次请求时都创建一个新的bean实例,并返回
-->
<bean id="car"
      class="top.finen.spring.autowire.Car"
      scope="prototype">
    <property name="brand" value="Audi"></property>
    <property name="price" value="300000"></property>
</bean>

# Spring的IOC容器中Bean的生命周期

1.SpringIOC容器可以管理Bean的生命周期。

代码语言:javascript
复制
public class Car {
    public Car() {
        System.out.println("Car's Constructor");
    }
    private String brand;

    public String getBrand() {
        return brand;
    }

    public void setBrand(String brand) {
        System.out.println("SetBrand...");
        this.brand = brand;
    }

    public void init() {
        System.out.println("init....");
    }

    public void destory() {
        System.out.println("destory...");

    }
}

2.SpringIOC容器可以对Bean的生命周期进行管理。

​ ①.通过构造器或者工厂方法创建Bean实例。

​ Bean的后置处理器允许在调用初始化方法前后对Bean进行额外处理。

​ Bean后置处理器对IOC容器里的所欲Bean实例逐一处理。

代码语言:javascript
复制
public class MyBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object o, String s) throws BeansException {
        System.out.println("postProcessBeforeInitialization " + o + "," + s);
        return o;
    }

    @Override
    public Object postProcessAfterInitialization(Object o, String s) throws BeansException {
        System.out.println("postProcessAfterInitialization " + o + "," + s);
        return null;
    }
}
代码语言:javascript
复制
<bean id="car" class="top.finen.spring.cycle.Car" init-method="init" destroy-method="destory"></bean>
<!--
实现BeanPostProcessor接口,并具体提供Object postProcessBeforeInitialization(Object o, String s):init-method之前被调用
和Object postProcessAfterInitialization(Object o, String s)的实现:init-method之后被调用
bean:bean实力本身
beanName:IOC容器配置的bean的名字
返回值:是实际上返回给用户的那个Bean,注意:可以再以上两个方法中修改返回的bean甚至返回一个新的bean。
-->
<!--配置bean的后置处理器,不需要配置id,IOC是一个自动识别BeanPostProcessor-->

​ ②.为Bean的属性设置值和对其他的Bean的引用。

​ ③.调用Bean的初始化方法

​ ④.Bean的使用

​ ⑤.当容器关闭时,调用Bean的销毁方法。

3.为Bean的声明里设置init-method和destory-method属性,为bean指定初始化和销毁方法

# Spring通过工厂方法创建bean

代码语言:javascript
复制
<!--通过静态方法来配置bean,不是通过配置静态工厂方法实例,而是配置bean实例-->
<!--
    class属性:指向静态工厂方法全类名
    factory-method: 指向静态工厂方法的名字
    constructor-arg:如果工厂方法需要传入参数,则通过constructor-arg传入参数
-->
<bean id="car1"
      class="top.finen.spring.beans.factory.StaticCarFactory"
      factory-method="getCar">
    <constructor-arg value="audi"></constructor-arg>
</bean>

<bean id="carFactory" class="top.finen.spring.beans.factory.InstanceCarFactory"></bean>

<!--
    factory-bean属性:指向实例工厂方法的全类名
    factory-method: 指向静态工厂方法的名字
    constructor-arg:如果工厂方法需要传入参数,则通过constructor-arg传入参数
-->
<!--通过实例工厂方法来配置bean-->
<bean id="car2" factory-bean="carFactory" factory-method="getCar">
    <constructor-arg value="audi"></constructor-arg>
</bean>

代码语言:javascript
复制
/**
 * 静态工厂方法:直接调用某一个类的静态方法就可以返回bean的实例
 */
public class StaticCarFactory {
    private static Map<String, Car> cars = new HashMap<String, Car>();
    static{
        cars.put("audi", new Car("audi", 30000));
        cars.put("ford", new Car("ford", 50000));
    }

    //静态工厂方法
    public static Car getCar(String name) {
        return cars.get(name);
    }
}
代码语言:javascript
复制
/**
 * 实例工厂方法:实例工厂的方法,既现需要创建工厂本身,再调用工厂的实例方法实例方法来返回bean的实例
 */
public class InstanceCarFactory {
    private Map<String, Car> cars = null;

    public InstanceCarFactory() {
        cars = new HashMap<String, Car>();
        cars.put("audi", new Car("audi", 30000));
        cars.put("ford", new Car("ford", 50000));
    }

    public Car getCar(String brand) {
        return cars.get(brand);
    }
}

# Spring通过FactoryBean创建bean

代码语言:javascript
复制
<!--
通过FactoryBean来配置Bean的实例
class:指向FactoryBean的全类名
property:配置FactoryBean的属性

但是实际返回的实例却是FactoryBean的getObject()方法返回的实例
-->
<bean id="car" class="top.finen.spring.beans.factorybean.CarFactoryBean">
    <property name="brand" value="BMW"></property>
</bean>
代码语言:javascript
复制
//自定义的FactoryBean需要实现FactoryBean
public class CarFactoryBean implements FactoryBean<Car> {
    private String brand;

    /**
     * @return 返回bean的对象
     * @throws Exception
     */
    @Override
    public Car getObject() throws Exception {
        return new Car(brand, 500000);
    }

    /**
     *
     * @return 返回bean的类型
     */
    @Override
    public Class<?> getObjectType() {
        return null;
    }

    @Override
    public boolean isSingleton() {
        return false;
    }

    public void setBrand(String brand) {
        this.brand = brand;
    }
}

# 使用注解来配置bean

代码语言:javascript
复制
基于注解方法配置bean
使用注解来装配bean的属性

1.在classpath中扫描组件对于扫描到的组件,对于扫描的组件,Spring有默认的命名策略:使用非限定类名,第一个字母小写,也可以通过在注解中配置value属性值表示组件的名称

特定组件:

​ 1.@Component:基本注解,标识一个手Spring管理的组件

​ 2.@Repository:标识持久化组件

​ 3.@Service:标识服务层(业务层)组件

​ 4.@Controller:标识表现层组件

2.在组件类使用特定的注解以后,还需要在Spring的配置文件中声明<context:component-scan>

  • base -package属性指定一个需要扫描的基类包,Spring容器将会扫描这个基类暴力以及其子类包的所有类。
  • 当需要扫描多个包时,可以使用逗号分隔
  • 如果仅希望扫描特定的类而非基类包下的所有类,可以使用resource-pattern属性过滤特定的类
    • <context:include-filter> 子节点表示包含的目标类
    • <context:exclude-filter> 子节点表示要排除在外的目标类
    • <context:component-scan>下可以拥有若干个<context:exclude-filter><context:include-filter>
代码语言:javascript
复制
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">

    <!-- 配置自动扫描的包: 需要加入 aop 对应的 jar 包 -->
    <!-- 可以通过resource-pattern指定扫描的类 -->
    <!-- context:exclude-filter子节点排除那些指定的表达式的组件 -->
    <!-- context:include-filter子节点指定包含那些表达式的组件,该子节点需要use-default-filters -->

    <context:component-scan
            base-package="top.finen.spring.beans.annotation">
<!--        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Repository"/>-->
<!--        <context:include-filter type="annotation" expression="org.springframework.stereotype.Repository"/>-->
<!--        <context:exclude-filter type="assignable" expression="top.finen.spring.beans.annotation.repository.UserRepository"/>-->
    </context:component-scan>

</beans>
代码语言:javascript
复制
@Component
public class TestObject {

}
代码语言:javascript
复制
@Service
public class UserService {
    public void add() {
        System.out.println("UserService add...");
    }
}//其中一个示例
# 使用Autowired自动装配Bean

@Autowired注解自动装配具有兼容类型的单个Bean属性

构造器,普通字段,一切具有参数的方法都可以使用@Autowired注解。

代码语言:javascript
复制
@Autowired
private UserRepository userRepository;

@Autowired
public void setUserRepository(UserRepository userRepository) {
    this.userRepository = userRepository;
}
//以上两种方法都可以

默认情况下,所有使用@Autowired注解的属性都需要被设置,当Spring招不到匹配的Bean装配置是,会抛异常。当某一属性允许不被设置,可以设置@Autowired注解的required属性为false。

默认情况下,当IOC容器里面存在多个类型兼容的Bean时,通过类型的自动装配将无法工作,此时可以在@Qualifier注解里提供Bean的名称,Spring允许对方法的入参标注@Qualifier已指定注入Bean的名称。

代码语言:javascript
复制
//使用Qualifier注解指定
@Autowired
@Qualifier("userRepositoryImpl")
public void setUserRepository(UserRepository userRepository) {
    this.userRepository = userRepository;
}

@Autowired注解也可以应用在数组类型的属性上,此时Spring将会把所有匹配的Bean进行自动装配。

@Autowired也可以应用在集合属性上,此时Spring读取该集合的类型信息,然后自动装配所有与之配置的Bean。

Autowired注解在java.util.Map上时,若该Map的键值为String,那么Spring将自动装配与之Map类型兼容的Bean,此时Bean得到名称作为键值。

# Spring泛型依赖注入

代码语言:javascript
复制
public class BaseService<T> {
    @Autowired
    protected BaseRepository<T> repository;
    
    public void add() {
        System.out.println("add...");
        System.out.println(repository);
    }
}
代码语言:javascript
复制
public class Main {
    public static void main(String[] args) {
        ApplicationContext ctx = new ClassPathXmlApplicationContext("beans-generic.di.xml");
        UserService userService = (UserService) ctx.getBean("userService");
        userService.add();
    }
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019-02-02 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • # SpringIOC/DI概述:
    • # 配置bean
    • # Spring Bean的讲解
      • # 继承
        • # 依赖
        • # Bean的作用域
        • # Spring的IOC容器中Bean的生命周期
        • # Spring通过工厂方法创建bean
        • # Spring通过FactoryBean创建bean
        • # 使用注解来配置bean
          • # 使用Autowired自动装配Bean
          • # Spring泛型依赖注入
          相关产品与服务
          容器服务
          腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档