Spring注解开发——说说@Autowired

关于Autowired那点事

大家都知道,注解出来之前,向一个bean中注入另一个bean我们需要在配置文件里配置,像这样:

<?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 https://www.springframework.org/schema/context/spring-context.xsd">

    <bean id="car" class="com.example.demo.bean.Car" />
    <bean id="person" class="com.example.demo.bean.Person" >
        <!-- 第一种方式,通过setter方法注入 -->
        <property name="car" ref="car" />
        <!-- 第二种方式,通过构造函数注入 -->
        <constructor-arg ref="car" />
    </bean>
</beans>

我们看到,要在Person类中注入Car实例,首先要声明两个这两个bean,同时还要在Person类中提供带有Car参数的有参构造函数(如果选择通过构造器注入),或者提供setter方法(setter注入),像这样:

public class Person {
    private Car car;

    // 构造器注入时必须提供此构造函数
    public Person(Car car) {
        this.car = car;
        System.out.println("===>inject car by constructor. ");
    }

    // setter注入时必须提供此set方法
    public void setCar(Car car) {
        this.car = car;
    }
}

大家想想,如果我们Person类又需要注入一个其他bean NewCar,我们怎么做?首先,我们要在xml里面配置这个NewCar,,然后在person这个bean里面通过进行setter注入,或者构造器注入,最后我们还要对应的在Person类里面增加一个构造器或者set方法。。。

上面的过程,元芳你怎么看?

于是便有了注解。。。注解真是个好东西

有了注解以后,我们就省去了在xml里面配置so many bean的烦恼,麻麻再也不用担心我代码写的慢了。。

第一步,xml配置一个扫描器,扫描我们要放去bean容器的所有类(application-context.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"
       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 https://www.springframework.org/schema/context/spring-context.xsd">

    <context:component-scan base-package="com.example.demo.bean" />
</beans>

第二步,在我们需要spring帮我们管理的bean上面增加注解:@Controller、@Component、@Service、@Repository、@Resource其中的一种,这些注解就是告诉spring,你给我创建这些bean的实例,要用的时候我就直接去容器里拿了。我们想在person类里用car,直接一个@Autowired,car实例就来了,我们想来个NewCar,那就再@Autowired一下,多么简单。我们的世界再也没有了new。。。

@Component
public class Car {

    public Car() {
        System.out.println("得到了car实例");
    }
}

@Component
public class Person {
    @Autowired
    private Car car;
}

注解确实让我们的世界清静了很多,但是大家有没有想过,注解的本质是什么?

有句话收得好:万变不离其宗。其实注解本质上和xml是一样的,毕竟是先有xml配置,然后才有的注解。

细想一下我们就会发现,这个@Component不就等于我们在xml里面bean的声明么 ,在person里面注入car不就等于在xml里person bean里配置的car注入么。。。

等等,这里有人就有疑问了,person里面注入car有两种方式,那@Autowired到底是set注入还是构造器注入呢?good question。有问题就要动手去实践

测试类:

public class XmlConfigBeanTest {
    public static void main(String[] args) {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-context.xml");

        Person person = (Person) applicationContext.getBean("person");
        System.out.println(person);
    }
}

Person类:

@Component
public class Person {

    private String name;

    @Autowired
    private Car car;

    public Person(Car car) {
        this.car = car;
        System.out.println("===>inject car by constructor. ");
    }

    public void setCar(Car car) {
        this.car = car;
        System.out.println("===>inject by setter. ");
    }

    @Override
    public String toString() {
        return "Person{" +
                " car=" + car +
                '}';
    }
}

我们这里注解,set、构造器都提供,大家猜猜spring通过哪种方式注入car?看结果:

===>inject car by constructor. 
Person{ car=com.example.demo.bean.Car@1e8b7643}

意外吧,spring首选还是构造器注入,我们把构造器注释掉,结果:

Person{ car=com.example.demo.bean.Car@1115ec15}

此时选择的是@Autowired注解,大家可以在@Autowired接口里打上断点,debug一下,就会证实确实如此。

我们继续把@Autowired注释掉,结果:

Person{ car=null}

没注入进去。。。也就是有setter也不管用。

结论:@Autowired注解本质上等价于构造器注入。

猜你喜欢

转载自blog.csdn.net/chenshufeng115/article/details/100045138