您的位置:首页 > 编程语言 > Java开发

@Autowired自动注入实例

2016-09-04 23:04 369 查看
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-f
4000
ilter).

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

例如:

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中拿出一个最优项初始化给这个属性。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  spring autowired