三种方法装配bean

1.自动化装配bean

1.1 bean之间没有依赖关系

配置类:

@Configuration      //表明这是一个配置类,配置Spring容器
@ComponentScan      //启动组件扫描,默认会扫描与配置类相同的包
public class LtConfig {
}

UserDaoImpl:

@Component          //表明该类会作为组件类,并告知Spring要为这个类创建bean
public class UserDaoImpl implements UserDao {
    public void getUser() {
        System.out.println("默认获取用户的数据");
    }
}

测试:

public class MyTest {       //测试类
    public static void main(String[] args) {
        ApplicationContext context = new AnnotationConfigApplicationContext(com.lt.LtConfig.class);
        UserDao dao = (UserDao) context.getBean("userDaoImpl");
        dao.getUser();
    }
}

1.2 bean之间存在依赖

配置类不变

CarDaoImpl:

@Component
public class CarDaoImpl implements CarDao{
    @Override
    public void getCarName() {
        System.out.println("AE86");
    }
}

UserDaoImpl:

@Component
public class UserDaoImpl implements UserDao {

    private CarDao carDao;

    @Autowired
    public UserDaoImpl(CarDaoImpl carDao){
        this.carDao = carDao;
    }

    @Override
    public void getUser() {
        System.out.println("获得用户");
        carDao.getCarName();
    }
}

UserDaoImpl对CarDaoImpl产生了依赖,并通过构造器注入。在这里,使用@Autowired由Spring容器来自动装配。在这里@Autowired用在了构造方法上。实际上,@Autowired注解可以用在类的任何方法上,甚至不需要声明用于装配的方法,直接用在声明的变量上也可以。如:

@Component
public class UserDaoImpl implements UserDao {
	@Autowired
    private CarDao carDao;

    @Override
    public void getUser() {
        System.out.println("获得用户");
        carDao.getCarName();
    }
}

运行结果:

如果没有匹配的bean,那么在应用上下文创建的时候,Spring会抛出一个异常。为了避免异常的出现,可以将@Autowired 的 required属性设置为 false:@Autowired(required=false),此时,Spring会尝试执行自动装配,但是如果没有匹配的bean的话,Spring将会让这个bean处于未装配的状态。

2.通过Java代码装配bean

2.1 bean之间没有依赖关系

配置类:

@Configuration
public class LtConfig {
    @Bean(name="userDao")
    public UserDaoImpl userDaoImpl(){
        return new UserDaoImpl();
    }
}

创建 JavaConfig 类的关键在于为其添加@Configuration 注解,@Configuration 注解表明这个类是一个配置类,该类应该包含在Spring应用上下文中如何创建bean的细节。

@Bean 注解会告诉Spring这个方法将会返回一个对象,该对象要注册为Spring应用上下文的 bean 。方法体中包含了最终产生 bean 实例的逻辑。默认情况下,bean 的 id 与带有 @bean 注解的方法名是一样的,也可以通过 name 属性指定一个名字。

UserDaoImpl:

public class UserDaoImpl implements UserDao{
    public void show(){
        System.out.println("调用show方法");
    }
}

测试:

public class MyTest {
    public static void main(String[] args) {
        ApplicationContext context = new AnnotationConfigApplicationContext(com.lt.LtConfig.class);
        UserDao userDao = (UserDao) context.getBean("userDao");
        userDao.show();
    }
}

2.2 bean之间存在依赖

方法一:

UserDaoImpl:

public class UserDaoImpl implements UserDao{
    private CarDao carDao;

    public UserDaoImpl(CarDaoImpl carDaoImpl){
        this.carDao = carDaoImpl;
    }

    public void show(){
        System.out.println("调用show方法");
        carDao.getCarName();
    }
}

CarDaoImpl:

public class CarDaoImpl implements CarDao {
    @Override
    public void getCarName() {
        System.out.println("AE86");
    }
}

配置类:

@Configuration
public class LtConfig {

    @Bean
    public CarDaoImpl carDaoImpl(){
        return new CarDaoImpl();
    }

    @Bean(name="userDao")
    public UserDaoImpl userDaoImpl(){
        return new UserDaoImpl(carDaoImpl());
    }
}

CarDaoImpl的配置方法与之前的相同,UserDaoImpl稍微有些变化,在这里没有用默认的无参构造器来构建实例,而是调用了需要传入依赖对象的构造器来创建实例。看起来依赖对象是通过调用 carDaoImpl() 方法得到的,事实并非完全如此,因为 carDaoImpl() 方法上添加了@bean 注解,Spring将会拦截所有对它的调用,并确保直接返回该方法所创建的 bean,而不是每次都对其进行实际的调用。
如果调用方法来引用bean的方式让你感到困惑,那么下面还有一种理解起来更为简单的方式:

@Configuration
public class LtConfig {

    @Bean
    public CarDaoImpl carDaoImpl(){
        return new CarDaoImpl();
    }

    @Bean(name="userDao")
    public UserDaoImpl userDaoImpl(CarDaoImpl carDao){
        return new UserDaoImpl(carDao);
    }
}

这种方法把依赖的bean作为参数传递进来。当Spring调用userDaoImpl创建bean的时候,它会自动装配一个CarDaoImpl到配置方法之中。通过这种方式引用其他的bean通常是最佳的选择,因为它不会要求将CarDaoImpl和UserDaoImpl声明到同一个配置类中,甚至没有要求CarDaoImpl必须要在JavaConfig中声明。

我们可以进行测试:

UserDaoImpl:

public class UserDaoImpl implements UserDao{
    private CarDao carDao;

    public UserDaoImpl(CarDaoImpl carDaoImpl){
        this.carDao = carDaoImpl;
    }

    public void show(){
        System.out.println("调用show方法");
        carDao.getCarName();
    }

    public CarDao getCarDao(){		//获得carDao对象
        return carDao;
    }
}

配置类:

@Configuration
public class LtConfig {

    @Bean("carDao")
    public CarDaoImpl carDaoImpl(){
        return new CarDaoImpl();
    }

    @Bean(name="userDao")
    public UserDaoImpl UserDaoImpl(){
        return new UserDaoImpl(carDaoImpl());
    }

    @Bean(name="userDao2")
    public UserDaoImpl UserDaoImpl2(){
        return new UserDaoImpl(carDaoImpl());
    }
}

在配置类中,我们增加了一个方法用来创建 uerDao2,创建方法和创建 userDao 完全一样。下面看看结果。

测试:

public class MyTest {
    public static void main(String[] args) {
        ApplicationContext context = new AnnotationConfigApplicationContext(com.lt.LtConfig.class);
        UserDao userDao = (UserDao) context.getBean("userDao");
//        userDao.show();

        UserDao userDao2 = (UserDao) context.getBean("userDao2");
        CarDao carDao = (CarDao) context.getBean("carDao");
        System.out.println("三个carDao对象相同吗?"+(carDao==userDao.getCarDao()&&userDao.getCarDao()==userDao2.getCarDao()));
        System.out.println("两个userDao对象相同吗?"+(userDao==userDao2));
    }
}

测试结果:

结果表明:两个 userDao 中的 carDao 指向相同且都指向 carDao,但两个 userDao 指向不同。

3. 通过XML装配bean

这种装配bean的方法是最简单也是最好理解的,在此不过多阐述。

导入和混合配置

1. 在 JavaConfig 中引用 JavaConfig 配置

CarConfig.class

@Configuration
public class CarConfig {

    @Bean("carDao")
    public CarDaoImpl carDaoImpl(){
        return new CarDaoImpl();
    }
}

UserConfig.class

@Configuration
@Import(CarConfig.class)
public class UserConfig {
    
    @Bean(name="userDao")
    public UserDaoImpl UserDaoImpl(){
        return new UserDaoImpl(carDaoImpl());
    }
}

使用 @Import 注解可以导入 JavaConfig 类。

2. 在 JavaConfig 中引用 XML 配置

CarConfig.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 id="carDao" class="com.lt.dao.CarDaoImpl"/>
</beans>

UserConfig.class

@Configuration
@ImportResource("CarConfig.xml")
public class UserConfig {
    
    @Bean(name="userDao")
    public UserDaoImpl UserDaoImpl(CarDaoImpl carDao){
        return new UserDaoImpl(carDao);
    }
}

使用 @ImportResource 可以导入 XML 配置文件

3. 在 XML 配置中引用 XML 配置

CarConfig.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 id="carDao" class="com.lt.dao.CarDaoImpl"/>
</beans>

UserConfig.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">

    <import resource="CarConfig.xml"/>
    <bean id="userDao" class="com.lt.dao.UserDaoImpl">
        <constructor-arg ref="carDao"/>
    </bean>
</beans>

使用 import 标签可以导入 XML 配置文件

4. 在 XML 配置中引用 JavaConfig

CarConfig.class

@Configuration
public class CarConfig {

    @Bean("carDao")
    public CarDaoImpl carDaoImpl(){
        return new CarDaoImpl();
    }
}

UserConfig.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.lt.CarConfig" />
    <bean id="userDao" class="com.lt.dao.UserDaoImpl">
        <constructor-arg ref="carDao"/>
    </bean>
</beans>

可以通过 bean 元素将 JavaConfig 导入进来。

posted on 2020-01-30 17:36  噓つき  阅读(133)  评论(0)    收藏  举报