Spring框架之Bean的初级装配

Bean的基础配置

装配机制

Spring提供了三种装配机制:

  • 自动化装配
  • Java代码装配
  • XML装配

自动化装配bean

Spring从两个角度来实现自动化装配:

  • 组件扫描(component scanning):Spring会自动发现应用上下文中所创建的bean。
  • 自动装配(autowiring):Spring自动满足bean之间的依赖。

Spring装配bean首先需要知道装配那些bean,即范围和标志,所以需要组件扫描Spring上下文中需要创建bean的标志。

Spring通过@ComponentScan注解启动扫描,@ComponentScan有一个属性basePackages可以设置要扫描的基础包,注意基础包路径为全路径,当然可能你注意到了basePackages是一个复数,所以可以配置多个基础包,若只配置一个基础包,可以省略basePackages;若不配置基础包,那么扫描的是配置类当前的包以及其子包。

@Configuration
@ComponentScan( "com.cxd.javaweb.service")
public class ComponentConfig {
}

或者

@Configuration
@ComponentScan(basePackages = "com.cxd.javaweb.service")
public class ComponentConfig {
}

或者

@Configuration
@ComponentScan(basePackages = {"com.cxd.javaweb.service","com.cxd.javaweb.bussiness"})
public class ComponentConfig {
}


@Configuration注解是表示这个类是配置类

若扫描的不是包,也可以扫描具体的类可以使用注解@ComponentScan的另外一个属性basePackageClasses,用法与basePackages类似

现在使用注解@Configuration创建了配置类,使用@ComponentScan启动自动扫描了,那么创建bean的标志是什么呢?

@Component注解就可以作为类创建bean的标识,如:

@Component
public class HuaweiComputer implements IComputer {
    public String getName(){
        return "Huawei";
    }
}

Spring应用上下文中所有bean都有一个ID,默认bean的ID是类名首字母小写,如上类HuaweiComputer的ID为huaweiComputer,但是@Component可以设置bean的ID,使用属性value,如:

//注解@Component的value属性可以省略
@Component("LenovoPc")
public class LenovoComputer implements IComputer {
    public String getName() {
        return "Lenovo";
    }
}

简单的说,自动装配就是融Spring自动满足bean依赖的一种方法,在满足依赖的过程中,会在Spring应用上下文中寻找匹配某个bean,为了声明要进行自动装配我们需要借助一些注解,比如@Autowired,@Resource。

测试自动装配

@Configuration
@ComponentScan(basePackages = {"com.cxd.javaweb.service"} )
public class ComponentConfig {
}
public interface IComputer {
    public String getName();
}
@Component("LenovoPc")
public class LenovoComputer implements IComputer {
    public String getName() {
        return "Lenovo";
    }
}
//@ContextConfiguration加载配置类,使用属性classes
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = ComponentConfig.class)
public class ComputerTest {

    @Autowired
    @Qualifier("LenovoPc")
    private IComputer iComputer;

    @Test
    public void testName(){
        String name = iComputer.getName();
        System.out.println(name);
    }
}
结果:Lenovo

1、 @Component是基础注解,还有 @Controller,@RestController,@Service,@Repository 这些注解为了程序的可读性,以及不同层次使用的与@Component作用相同

@Controller和@RestController用于视图层,常作用于接口

@Service用于业务层

@Repository用于数据访问层

注意:@RestController和@Controller的区别

@RestController是ResponseBody + Controller,使用@RestController返回的是对象

@Controller可以与视图解析器InternalResourceViewResolver配合使用返回页面

​ 2、自动装配bean的注解有:@Autowired,@Resource

注意:常比较的是@Autowired与@Resource

(1)@Autowired是Spring的注解,@Resource是JSR-250Java规范注解

(2)@Autowired按byType自动注入,而@Resource默认按 byName自动注入,@Autowired可以与@Qualifier配合使用实现通过name自动注入

(3)@Resource装配顺序

  1. 如果同时指定了name和type,则从Spring上下文中找到唯一匹配的bean进行装配,找不到则抛出异常
  2. 如果指定了name,则从上下文中查找名称(id)匹配的bean进行装配,找不到则抛出异常
  3. 如果指定了type,则从上下文中找到类型匹配的唯一bean进行装配,找不到或者找到多个,都会抛出异常
  4. 如果既没有指定name,又没有指定type,则自动按照byName方式进行装配;如果没有匹配,则回退为一个原始类型进行匹配,如果匹配则自动装配;

建议使用@Resource

JAVA代码装配bean

​ 尽管在很多场景下通过组件扫描和自动装配实现Spring的自动化装配是更为推荐的方式,但是有时候自动化配置的方案行不通,因此需要明确配置Spring。比如:你想要将第三方库中的组件装配到你的应用中,就不能使用@Component和@Autowired注解了。

首先需要创建配置类,声明简单的bean,如下:

@Configuration
public class SqlfxConfiguration {

	@Bean(name = "sqlfxClient",initMethod="init")
	public ClientMain sqlfx(){
		return new ClientMain();
	}
}

以上实例是公司添加sql分析需要配置的bean,其中ClientMain是第三方jar包

@Configuration注解标识该类为配置类

@Bean注解告诉Spring这个方法将返回一个对象,该对象要注册为Spring应用上下文中的bean。bean的ID与带有@Bean注解的方法名一样,但是我们可以通过@Bean的一些属性改变其默认值,比如通过name属性改变bean的ID,如上面的例子,该bean的ID为“sqlxClient”,也可以使用属性value。

@Bean注解中initMethod属性表示初始化后要执行ClientMain类中的init()方法,还有一个属性destroyMethod表示bean销毁前要执行的方法

小知识:spring中若某个类中的某个方法需要在项目启动的时候执行,那么该类可以实现InitializingBean接口,重写afterPropertiesSet()方法,通过这个方法调用要执行的那个方法。

当然创建bean的方式不一定都是使用new的方式,如下:

@Configuration
public class CacheConfiguration {

    @Bean(name = "RcpEhCacheManager")
    public CacheManager ehCacheManager() throws CacheException, IOException {
        return CacheManager.newInstance(new ClassPathResource(
                "/cache/caseEhcache.xml").getInputStream());
    }
}

此实例是配置Ehcache缓存的方法,需要读取xml文件,使用newInstance创建CacheManager对象。

XML装配bean

​ xml装配bean的方式是Spring最早的装配bean 的方案,但是随着自动装配方式和Java代码装配方式的出现,xml装配方式逐渐被人们弃用了,但是我们可以通过学习xml配置能很好的理解自动装配和Java代码装配的原理,所以还是要了解的。

在使用JavaConfig的时候,需要创建一个带有@Configuration注解的类,而在xml配置中需要创建一个xml文件,并且要以**<beans>**元素为根,如下:

<?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.cxd.javaweb.bean.DellComputer" id="dellComputer"></bean>
</beans>

bean的属性:

id:唯一标识,ioc容器中的Bean的key值,从ioc容器中获取一个实例的时候,需要通过id来获取

name:可以通过name从容器中获取Bean,Bean的别名,有id的情况下,id为Bean的key,没有id的情况下,name为实例的key

class:将哪一个类进行实例化,写的是类的完全限定名(包名+类名)

使用反射对一个类进行实例化,如果写错了,在反射时会报ClassNotFoundException

lazy-init:延迟初始化,默认是在容器启动的时候就进行加载,true是延迟加载,什么时候从容器中获取该Bean什么时候才实例化,只有在单例模式下生效

parent:指定该类的父类,将会继承父类实例化后的所有属性,实例化该类的时候,会先触发父类的实例化,在该类进行实例化时,可以覆盖继承父类中某个属性的值,要求该类与父类是同一个类型(继承),当然首先要将父类装入容器中,parent写的是父类Bean的id

abstract:不会在容器中创建该类的实例,如果从容器中获取,会报错

depend-on:依赖检查,要实例化A类,但是实例化A类需要依赖B类,首先要保证B类已经实例化过了,B类的id。指定该Bean在实例化的时候依赖Bean,所依赖的Bean会将该Bean实例化之前进行实例化。depend-on写的某个Bean的id

init-method:初始化方法,该Bean在实例化时会自动调用一个方法,该方法必须是无参的,直接写方法名,不写小括号,只在单例模式下生效

destroy-method:容器关闭时调用的方法,该方法必须是无参的,且只有单例模式下才能生效。调动ctx.close()就是关闭容器

构造器初始化bean

构造器初始化bean有两种方案:

  • <constructor-arg>元素
  • 使用Spring3.0所引入的c-命名空间

Java代码中构造函数如下:

public class Computer {

    private DellComputer dellComputer;

    public Computer(DellComputer dellComputer){
        this.dellComputer = dellComputer;
    }

    public String getName(){
        return  dellComputer.getName();
    }
}

xml配置如下:

<?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.cxd.javaweb.bean.DellComputer" id="dellComputer">
    </bean>

    <bean class="com.cxd.javaweb.service.Computer" id="computer">
        <constructor-arg ref="dellComputer"/>
    </bean>

</beans>

测试类如下:

//@ContextConfiguration加载配置文件,使用属性locations
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath*:/spring-bean.xml")
public class XmlConfigTest {

    @Resource
    private DellComputer dellComputer;

    @Test
    public void testDell(){
        String name = dellComputer.getName();
        System.out.println(name);
    }
}

或者

@RunWith(SpringJUnit4ClassRunner.class)
public class XmlConfigTest {

    @Test
    public void testDellName(){
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-bean.xml");
        Computer dellComputer = (Computer)applicationContext.getBean("computer");
        String name = dellComputer.getName();
        System.out.println(name);
    }
}

结果:dell

装配集合

集合有list ,set其泛型可能是对象也可能是基本数据类型

若泛型为对象,如下:

<?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.cxd.javaweb.service.Computer" id="computer">
        <constructor-arg>
        	<list>
        		<ref bean="huaweiComputer">
        		<ref bean="levonoComputer">
        		<ref bean="dellComputer">
        	</list>
        </constructor-arg>
    </bean>

</beans>

若泛型为基本数据类型,如下:

<?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.cxd.javaweb.service.Computer" id="computer">
        <constructor-arg>
        	<list>
        		<value>品牌名:华为</value>
        		<value>品牌名:联想</value>
        		<value>品牌名:戴尔</value>
        	</list>
        </constructor-arg>
    </bean>

</beans>

属性赋值

设置属性用<property>元素为属性的setter方法所提供的功能与<constructor-arg>元素为构造器所提供的功能是一样的。如:

<?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.cxd.javaweb.bean.DellComputer" id="dellComputer">
    </bean>

    <bean class="com.cxd.javaweb.service.Computer" id="computer">
        <constructor-arg ref="dellComputer"/>
        <property name="cname" value="电脑"/>
        <property name="colour" value="黑色"/>
    </bean>

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值