Spring-2 配置bean

总的来说,配置bean有两个大的方向,一个是基于XML文件配置bean,如helloworld中的配置例子,另一个是使用注解装配。

先记录基于xml文件的装配。
在Spring-1的hello world例子,配置helloWorld bean的方式是:

<bean id="helloWorld" class="com.csu.hello.helloworld">
    <property name="name" value="Jerry"></property>
</bean>

这种方式实际上就是 通过全类名(反射)配置。

还有两种配置方式,分别是工厂方法 和 FactoryBean。

  1. 工厂方法
    从字面上来理解,工厂自然是一个生产产品的场所,在Spring里,我们生产bean,工厂则是生产bean 的一个类。
    工厂方法又分为静态工厂方法和实例工厂方法。
    (1)静态工厂方法:
    直接调用某个类的静态方法,该方法返回bean实例。
    在src下新建一个包com.csu.factory
    在该包下新建Car.java
package com.csu.factory;

public class Car {
    private String name;
    private float price;
    private int speed;

    //全类名配置法必须带有无参构造器
    public Car()
    {}
    //采用构造器注入方式需要带参构造器
    public Car(String name, float price, int speed) {
        super();
        this.name = name;
        this.price = price;
        this.speed = speed;
    }

    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public float getPrice() {
        return price;
    }
    public void setPrice(float price) {
        this.price = price;
    }
    public int getSpeed() {
        return speed;
    }
    public void setSpeed(int speed) {
        this.speed = speed;
    }
    @Override
    public String toString() {
        return "Car [name=" + name + ", price=" + price + ", speed=" + speed + "]";
    }

}

接下来在该包下创建静态工厂类staticFactory.java:

package com.csu.factory;

import java.util.HashMap;
import java.util.Map;


public class staticFactory {
    //此处访问控制符必须是static 因为静态方法需要访问
    static Map<String, Car> cars=new HashMap<>();
    //静态代码块完成初始化工作
    static{
        cars.put("dz", new Car("大众",200000,200));
        cars.put("ft", new Car("福特",200000,200));
        cars.put("bz", new Car("奔驰",200000,200));
        cars.put("bm", new Car("宝马",200000,200));
    }
    //根据name生产bean
    static Car buildCar(String name)
    {
        return cars.get(name);
    }
}

接下写xml:

<!--注意,这里配置的实际上是car 而不是staticFactory>
<bean id="car1" class="com.csu.factory.staticFactory" factory-method="buildCar">
<constructor-arg value="dz"></constructor-arg>  
</bean>

最后,在Main里写测试:

        ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml");
        Car car=(Car) context.getBean("car1");
        System.err.println(car);

后台可以打印出:Car [name=大众, price=200000.0, speed=200]

(2)实例工厂方法
观察上面这种工厂方法可得知,我们想获得car的实例,不用特地实例化一个staticFactory再调用buildCar方法,因为我们使用的是静态方法,可直接调用。实例化则需要先创建工厂本省,再调用工厂的方法。

package com.csu.factory;

import java.util.HashMap;
import java.util.Map;

public class instanceFactory {

    private Map<String, Car> cars=null;

    public instanceFactory()
    {
        cars=new HashMap<>();
        cars.put("dz", new Car("大众",200000,200));
        cars.put("ft", new Car("福特",200000,200));
        cars.put("bz", new Car("奔驰",200000,200));
        cars.put("bm", new Car("宝马",200000,200));
    }

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

    private int getCar(String name, int no) {
        //return new Car();
        return 0;
    }
}
<bean id="instance" class="com.csu.factory.instanceFactory"></bean>

<bean id="car2" factory-bean="instance" factory-method="getCar">
<constructor-arg value="dz"></constructor-arg>
</bean>

2.FactoryBean方式
这种方式,最大的特点是工厂类需要实现spring的FactoryBean接口,该接口定义了三个方法,如下:

package com.csu.factory;

import org.springframework.beans.factory.FactoryBean;

public class carFactoryBean implements FactoryBean<Car>{

    private String brand;

    public void setBrand(String brand) {
        this.brand=brand;
    }
    @Override
    public Car getObject() throws Exception {
        // TODO Auto-generated method stub
        return new Car(brand,20932,120);
    }

    @Override
    public Class<?> getObjectType() {
        // TODO Auto-generated method stub
        return Car.class;
    }

    @Override
    public boolean isSingleton() {
        // TODO Auto-generated method stub
        return false;
    }

}
<bean id="car3" class="com.csu.factory.carFactoryBean">
    <property name="brand" value="BMW"></property>
</bean>

这里虽然看起来实在配置carFactory,但实际返回的是carFactory 的getObject确定的类。

以上就是基于xml文件的配置,下面来说一说注解配置。
一说到注解,就是用一个@**加在一个字段或者方法上边就可以简单方便地完成很多事情。
工程结构:
这里写图片描述

beans-annotation.xml:
配置扫描包(可玩各种花样,比如只扫描哪里,不扫描哪里等等,具体可查手册)

<context:component-scan base-package="com.csu.annotation"></context:component-scan>

扫描annotation 以及 annotation下所有子包,只要发现带了
1 @Component 一般
2 @Repository 持久层
3 @Service 服务层
4 @ Controller 表现层
这四种注解的,IOC容器就把他们当作bean来配置,就不用自己在xml事无巨细的配置了。
比如:

package com.csu.annotation.repository;

import org.springframework.stereotype.Repository;

@Repository("userRepository")
public class UserRepositoryImpl implements UserRepository{
//UserRepository是一个自定义接口
    @Override
    public void save() {
        // TODO Auto-generated method stub
        System.out.println("save....");
    }

}
public class MainAnnot {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        ApplicationContext context=new ClassPathXmlApplicationContext("beans-annotation.xml");

        //TestObject testObject=(TestObject) context.getBean("test");
        //System.out.println(testObject);

        UserRepository repository=(UserRepository) context.getBean("userRepository");
        repository.save();

        //UserController controller=(UserController) context.getBean("userController");
        //controller.execute();

        //UserService service=(UserService) context.getBean("userService");
        //service.add();
    }

}

现在有一个问题就是,这只能配置单个独立的bean,如果bean里有bean呢?
比如Controller要用定义一个service是对象并实例化,service里定义repository对象并实例化,这种关系如何实现?
这里可用@Autowire来自动装配:

package com.csu.annotation.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.csu.annotation.repository.UserRepository;

@Service
public class UserService {
    @Autowired
    private UserRepository repository;
    public void add() {
        System.out.println("service add....");
        repository.save();      
    }
}

此处repository就可以自动装配。

最后一个问题,UserRepository 是一个接口类型,如果同时有多个类实现了该接口,这时到底该装配哪一个呢?
有两种解决办法:
(1)@Autowir下再标注一个 @Qualifier(“具体要装配的那个类名”)
(2)把字段名整得和bean名字一样。
我认为第一种更好,加一行上去标清楚,看得更清晰。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值