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
未标明原创文章均为采集,版权归作者所有,转载无需和我联系,请注明原出处,南摩阿彌陀佛,知识,不只知道,要得到
最新评论