@Autowired自动注入实例

来源:互联网 发布:程序员面试题目 编辑:程序博客网 时间:2024/06/05 08:53

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

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

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


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

1、写一个类

package com.hsb.dao;import org.springframework.stereotype.Repository;@Repositorypublic class DaoImpl implements IDao {@Overridepublic 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 {@Autowiredprivate DaoImpl daoimpl;@Testpublic 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 */@Autowiredpublic 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中拿出一个最优项初始化给这个属性。



0 0
原创粉丝点击