@Autowired自动注入实例 - yunshixin的专栏 - CSDN博客

1、网上有很多关于autowired的东西,然而看东西不如自己写点小东西。

2、虽然一直知道怎么用,但是并没有自己去了解过

3、上面两句基本都是废话

@Autowired实现自动注入分为以下几个步骤

1、写一个类

package com.hsb.dao; import org.springframework.stereotype.Repository; @Repositorypublic class DaoImpl implements IDao {     @Override    public void sayHello() {        System.out.println("Say Hello From DaoImpl");    }}

上面这个类中@Repository注解非常重要,它将类在web应用程序中的位置标识出来了,同时也让spring容器扫描的时候能将这个类找到并归入到可以使用自动注入的类中。同样的注解还有@Service和@Controller,当觉得不好归到Dao/Service/Controller中任意一类中的时候,也可以使用@Component

2、编辑applicationContext.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:aop="http://www.springframework.org/schema/aop"    xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context"    xsi:schemaLocation="http://www.springframework.org/schema/beans                           http://www.springframework.org/schema/beans/spring-beans-3.0.xsd                          http://www.springframework.org/schema/aop                           http://www.springframework.org/schema/aop/spring-aop-3.0.xsd                          http://www.springframework.org/schema/tx                           http://www.springframework.org/schema/tx/spring-tx-3.0.xsd                          http://www.springframework.org/schema/context                           http://www.springframework.org/schema/context/spring-context-3.0.xsd"    default-lazy-init="true">    <context:component-scan base-package="com.hsb.dao" /></beans>

注意其中的<context:component-scan base-package="com.hsb.dao" />这一句是用来告诉spring容器,在容器开启扫描的时候,去com.hsb.dao这个包下面去找可以自动注入的bean类。另外,如果Eclipse报错,说什么context can't be resolved 的话,多半是没添加最上面的那句

xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context"

3、编辑测试类

package com.hsb.dao; import org.junit.Test;import org.junit.runner.RunWith;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.test.context.ContextConfiguration;import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @RunWith(SpringJUnit4ClassRunner.class)@ContextConfiguration({"classpath*:**/applicationContext.xml","classpath*:**/springmvc-servlet.xml"})public class DaoImplTests {    @Autowired    private DaoImpl daoimpl;     @Test    public void test() {        daoimpl.sayHello();    }}

注意其中的

@RunWith(SpringJUnit4ClassRunner.class)@ContextConfiguration({"classpath*:**/applicationContext.xml","classpath*:**/springmvc-servlet.xml"})

@RunWith指定了测试运行在spring的测试环境下

@ContextConfiguration告诉spring容器去指定路径下寻找并加载applicationContext.xml文件

测试完成,Console的结果

九月 04, 2016 10:55:40 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions信息: Loading XML bean definitions from file [D:\PractiseForWork\WorkSpace\HelloMaven\target\classes\applicationContext.xml]九月 04, 2016 10:55:40 下午 org.springframework.context.support.AbstractApplicationContext prepareRefresh信息: Refreshing org.springframework.context.support.GenericApplicationContext@6ad5c04e: startup date [Sun Sep 04 22:55:40 CST 2016]; root of context hierarchySay Hello From DaoImpl九月 04, 2016 10:55:41 下午 org.springframework.context.support.AbstractApplicationContext doClose信息: Closing org.springframework.context.support.GenericApplicationContext@6ad5c04e: startup date [Sun Sep 04 22:55:40 CST 2016]; root of context hierarchy

可以看到,@Autowired成功的实现了自动注入

根据console中的打印结果,我们也可以重新理一遍思路

1、测试类跑起来的时候,Eclipse会根据@RunWith注解使用spring测试环境,然后根据@ContextConfiguration注解去加载applicationContext.xml.

2、Eclipse会记住applicationContext中的这句话 <context:component-scan base-package="com.hsb.dao" />

3、测试类跑起来,发现@Autowired注解的实例变量,会在com.hsb.dao包中去找DaoImpl类,找到后自动注入,相当于new了一次

4、调用daoimpl的方法,如果注入失败会报NullPointException,此处没有切打印出了信息,说明注入成功

4、根据控制台的打印结果我们能看到,Eclipse在实现自动注入的过程中,有一个start同时也有一个doClose过程,想必也是加载开始和运行结束时期做的事

以上结论都是根据实际操作猜测出来的,如有错误,欢迎指正。

后记一、在DaoImpl类中,重写无参构造方法,在其中随便写入一个输入语句,重新跑测试方法,会发现,这个输入语句被打印出来了。说明@autowired实现自动注入确实相当于new DaoImpl();

后记二、在比较大型的项目中,通常会有很多的dao/service/controller类, 不可能每个类都去添加一个注解,或者每写一个新的类就去添加一个@component或者其他注解来让spring容器明白这是一个bean。所以,我们可以在自动扫描中使用过滤组件(spring filter components in auto scanning)。在applicationContext.xml中的<context:component-scan base-package="com.hsb.dao"></context:component-scan>中添加这一句<context:include-filter type="regex"  expression="com.hsb.dao.*Dao*.*" /> 修改后完整的applicationContext.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"    xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"    xsi:schemaLocation="http://www.springframework.org/schema/beans            http://www.springframework.org/schema/beans/spring-beans-3.2.xsd        http://www.springframework.org/schema/tx        http://www.springframework.org/schema/tx/spring-tx-3.2.xsd           http://www.springframework.org/schema/context            http://www.springframework.org/schema/context/spring-context-3.2.xsd        http://www.springframework.org/schema/aop          http://www.springframework.org/schema/aop/spring-aop-3.2.xsd"    default-lazy-init="true">    <context:component-scan base-package="com.hsb.dao" >        <context:include-filter type="regex"                        expression="com.hsb.dao.*Dao*.*" />    </context:component-scan></beans>

<context:include-filter type="regex" expression="com.hsb.dao.*Dao*.java" />这句话大致可以解释为,自动扫描的时候使用过滤器,包含的过滤规则(include-filter)为正则类型(type="regex"),expression指定的包路径下,匹配正则表达式的文件,都将被作为bean存放到自动注入“候选库“中,当applicationContext被加载后,这些就会被解释,遇到autowired注解后,就会实现自动注入,此时,将DaoImpl类里面的@Repository注解去掉,同样可以实现自动注入。除了包含过滤(include-filter)之外,还有一种排除过滤(exclude-filter).

后记三、如果要自动注入的类中有参数怎么办?

例如:

public class SpitterDao {    private DataSource dataSource;    private JdbcTemplate jdbcTemplate;     /**     * @return the dataSource     */    public DataSource getDataSource() {        return dataSource;    }     /**     * @param dataSource     *            the dataSource to set     */    @Autowired    public void setDataSource(DataSource dataSource) {        this.dataSource = dataSource;        jdbcTemplate = new JdbcTemplate(dataSource);    }     /**     * @return the jdbcTemplate     */    public JdbcTemplate getJdbcTemplate() {        return jdbcTemplate;    }     /**     * @param jdbcTemplate     *            the jdbcTemplate to set     */    public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {        this.jdbcTemplate = jdbcTemplate;    }     public void getAllSpitter() {        String sql = "select * from spitter";        List<Spitter> spitters = jdbcTemplate.query(sql, new SpitterMapper());        for (Spitter spitter : spitters) {            System.out.println(spitter.toString());        }    }}

这个类中有两个参数,如果按照上面的方法进行自动注入,很明显参数是没有被初始化的。这个类最终进行操作的是通过参数的jdbcTemplate访问数据库,如果jdbcTemplate为null则肯定报NullPointException.这个时候,我们就可以使用@Autowired标注属性、构造器或者set方法,并在applicationContext.xml文件中注册一个beans。此例中我在applicationContext.xml中注册了一个dataSource如下:

<bean id="dataSource"        class="org.springframework.jdbc.datasource.DriverManagerDataSource">        <property name="driverClassName" value="com.mysql.jdbc.Driver" />        <property name="username" value="root" />        <property name="password" value="mysql" />        <property name="url" value="jdbc:mysql://localhost:3306/test" />    </bean>

这样当SpitterDao被自动注入的时候,容器会扫描到Autowired注解并通过类型匹配的方式从beansFactory中拿出一个最优项初始化给这个属性。


Original url: Access
Created at: 2019-04-04 11:19:11
Category: default
Tags: none

请先后发表评论
  • 最新评论
  • 总共0条评论