@Autowired自动注入实例

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

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

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


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

1、写一个类

package com.hsb.dao;

import org.springframework.stereotype.Repository;

@Repository
public 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 hierarchy
Say 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中拿出一个最优项初始化给这个属性。



  • 3
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值