【Spring】配置Bean的攻略汇总(自动注解方式+xml配置文件方式)


在这里插入图片描述
前一篇 博客之后,HelloWorld这个信仰已经可以完成了。IOC容器是Spring的重要组成,下面我们来详细了解下在spring IOC(Inversion of Control)容器(也可以说依赖注入DI(Dependency Injection)容器)里配置Bean。
☞机制理解:当某个角色(可能是一个Java实例,调用者)需要另一个角色(另一个Java实例,被调用者)的协助时,传统方式通常由调用者来创建被调用者的实例。但在Spring里,创建被调用者的工作不再由调用者来完成,因此称为 控制反转IOC。创建被调用者,实例的工作通常由Spring容器来完成,然后注入调用者,因此也称为 依赖注入DI
值得注意的是:
spring IOC容器只有实例化之后,才可以读取Bean配置创建Bean实例(即对象),以供程序获取/注入该Bean实例并使用

//1.实例化Spring的IOC容器
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("day1hello.xml");
//2.从IOC容器中获取Bean实例
Hello hello = (Hello) ctx.getBean("hello");
//Hello hello = ctx.getBean(Hello.class); //若容器中有多个同类的Bean则该方式会报错
//3.使用bean
hello.hello();
//4.关闭容器
ctx.close();

1. Bean配置

通过全类名反射(得提供一个空参构造器)
开始之前先说一下IDEA复制粘贴全类名的快捷键:ctrl+shift+alt+c/v

1.1 xml方式

day1hello.xml

<!-- 配置一个 bean -->
<bean id="hello" class="xu.day1.hello.Hello"> 
	<!-- 为属性赋值 -->
	<!-- 通过属性注入: 利用空参构造器创建实例,再通过setter方法注入属性值 故这里需提供一个空参构造器 -->
        <property name="name" value="zhangfei"></property>
</bean>

<!-- 通过构造器注入属性值 -->
<bean id="car2" class="xu.day1.hello.Car">
	<!-- 要求: 在 Bean 中必须有对应的构造器.-->
        <constructor-arg>
                <value><![CDATA[<ATRZA>]]></value>
        </constructor-arg>
        <constructor-arg value="130" index=1></constructor-arg>
        <constructor-arg value="3000" type="double"></constructor-arg>
</bean>

<!--<bean id="user2" class="xu.day1.hello.User">-->
        <!--<property name="name" value="Rose"></property>-->
        <!--<property name="car">-->
        <!-- 内部 bean, 类似于匿名内部类对象. 不能被外部的 bean 来引用, 也没有必要设置 id 属性 -->
                <!--<bean class="xu.day1.hello.Car">-->
                        <!--<constructor-arg value="baoma" index="0"></constructor-arg>-->
                        <!--<constructor-arg value="130" index="1"></constructor-arg>-->
                        <!--<constructor-arg value="3000" type="double"></constructor-arg>-->
                <!--</bean>-->
        <!--</property>-->
<!--</bean>-->

<!-- 声明集合类型的 bean -->
<util:list id="cars">
        <ref bean="car1"></ref>
        <ref bean="car2"></ref>
</util:list>

<bean id="user3" class="xu.day1.hello.User">
        <property name="name" value="Tom"></property>
        <!-- 引用外部声明的 list,通过 ref 属性值指定当前属性指向哪一个 bean! -->
        <property name="cars" ref="cars"></property>
</bean>

<!--简洁的p命名空间配置-->
<bean id="user4" class="xu.day1.hello.User" p:name="xu" p:cars-ref="cars"></bean>

<!--使用 parent 来完成继承 --> 
<bean id="user5" parent="user4" init-method="initMethod" destroy-method="destroyMethod"
      p:name="li">
</bean>
<!--使用depents-on来指定前置依赖的Bean:前置依赖的bean会在本bean实例化之前创建好 -->

<!-- 配置 bean 后置处理器: 不需要配置 id 属性, IOC 容器会识别到他是一个 bean 后置处理器, 并调用其方法 -->
<bean class="xu.day1.hello.auto.myBeanPostProcessor"></bean>

<!-- 导入外部的资源文件 -->
<context:property-placeholder location="classpath:db.properties"/>
<!-- 配置数据源 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="user" value="${jdbc.user}"></property>
        <property name="password" value="${jdbc.password}"></property>
        <property name="jdbcUrl" value="${jdbc.jdbcUrl}"></property>
        <property name="driverClass" value="${jdbc.driverClass}"></property>
        <property name="initialPoolSize" value="${jdbc.initPoolSize}"></property>
        <property name="maxPoolSize" value="${jdbc.maxPoolSize}"></property>
</bean>

<!-- scope 属性来指定 bean 的作用域-->
<!--  
  prototype: 原型的. 每次调用 getBean 方法都会返回一个新的 bean. 且在第一次调用 getBean 方法时才创建实例
  singleton: 单例的. 每次调用 getBean 方法都会返回同一个 bean. 且在 IOC 容器初始化时即创建 bean 的实例. 默认值 
 -->
 <bean id="user6" class="xu.day1.hello.User" p:name="xu" p:cars-ref="cars" scope="prototype"></bean>

①②③④⑤⑥×✔✘☞☜√
☞注意:

  1. id:Bean的名称 ①在IOC容器里必须是唯一的②若id没有指定,将默认为类名首字母小写作为Bean 的名字
  2. 构造器注入时,为唯一匹配构造器的参数,可通过参数的index(从0开始),type分别限定(只能用其一)
  3. 若value中含特殊字符,可通过 <![CDATA[]]包裹
  4. 抽象bean:abstract属性为true的bean,这样的bean不能被IOC容器实例化,只用来继承配置。若某个bean的class属性没有指定,则该bean必须是抽象bean
<bean id="user9" p:name="zhangFei" p:cars-ref="cars" abstract="true"></bean>
  1. 生命周期:
    默认单例下:IOC容器实例化后便自动执行Bean实例化(即调用构造器)-》将Bean实例传递给Bean后置处理器的postProcessBeforeInitialization-》指定类中自定义的init-method-》将Bean实例传递给Bean后置处理器的postProcessAfterInitialization-》该Bean可以供程序获取了-》当容器关闭,调用类中自定义的destroy-method
    若scope="prototype"则在第一次调用 getBean 方法时才创建实例(即调用构造器)
//后置处理器。BeanPostProcessor的实现类
public class myBeanPostProcessor implements BeanPostProcessor {
    
    
    @Override
    public Object postProcessBeforeInitialization(Object o, String s) throws BeansException {
    
    
        if (s.equals("user5")) {
    
     //bean实例较多,故通过equals匹配指定的Bean名称即id,然后再进行对应操作
            System.out.println("postProcessBeforeInit: "+s);
            User user = (User) o;
            user.setName("张");
        }
        return o;
    }

    @Override
    public Object postProcessAfterInitialization(Object o, String s) throws BeansException {
    
    
        if (s.equals("user5")) {
    
     
            System.out.println(o+" :"+s);
        }
        return o;
    }
}

其余的java类就不赘述,这里就暂且给出类成员结构
在这里插入图片描述在这里插入图片描述

1.2 注解方式

机制理解:在base-package寻找标注了@Component、@Service、@Controller、@Repository注解的类,并把这些类注册为bean纳入进Spring容器中管理。

<!-- 配置自动扫描的包--> <!--可通过resource-pattern指定需要扫描的资源 这里的路径是相对于base-package-->
<context:component-scan base-package="xu.day1.hello.auto.annotation" resource-pattern="/*.class">
	<!-- 子节点排除指定表达式的组件-->
        <!-- <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Repository"/> -->

</context:component-scan>

☞注意:①②③④
①排除or包含指定的表达式组件。包含需将use-default-filters=‘false’,而排除不用默认为true。注意type="annotation"为目标是否采取指定组件注解进行过滤,type="assinable"目标是继承或扩展某个特定类进行过滤
在这里插入图片描述

xu.day1.hello.auto.annotation下的java类

@Component
public class Bike {
    
    
...
}
@Repository("userDao")  //通过value指定组件名称/bean名称userDao 默认是类名首字母小写
public class UserDao implements BaseDao<Customer> {
    
    
...
}
@Service("userService")
public class UserSerivce implements BaseService<Customer> {
    
    
    @Autowired  //默认根据类型匹配自动装配注入:将IOC容器里对应类型的Bean实例给该变量
    //@Qualifier("Bean名称") //属性装配指定Bean,适用于多个同类型bean的自动装配
    private Bike bike;
    @Autowired
    private UserDao userDao;
    ...
}    
public interface BaseDao<T> {
    
    
...
}
public interface BaseService<T> {
    
    
...
}
public class Customer {
    
    
...
}

☞注意:

  1. 四大注解组件:@Repository:持久层组件如实现DAO、@Service:服务层组件如装配注入DAO、@Constroller:表现控制层组件如装配注入服务、@Component:基本注解组件,将普通类Bean实例化至IOC容器,想必调用的是空参构造器
  2. 若是类的属性含@Autowired自动装配,则该类的对象一定得是获取Bean实例的方式,否则new出来该自动装配属性为null
  3. @Autowired遇到多个同类型的Bean,则需@Qualifier(“Bean名称”)
  4. 若某一属性允许不被设置,则可@Autowired(required=false)

1.3 工厂方法注入(不推荐):可以通过实现FactoryBean,也可以自己创建工厂,然后配置Bean。由于不常用,这里就不赘述了

猜你喜欢

转载自blog.csdn.net/qq_40265247/article/details/106202479