zoukankan      html  css  js  c++  java
  • spring 自动装配与注解注入

    基于xml的自动装配

    除了上述手动注入的情况,Spring还非常智能地为我们提供自动向Bean注入依赖的功能,这个过程一般被称为自动装配(autowiring)

    Spring的自动装配有三种模式:byTpye(根据类型),byName(根据名称)、constructor(根据构造函数)。

    在byTpye模式中,Spring容器会基于反射查看bean定义的类,然后找到与依赖类型相同的bean注入到另外的bean中,这个过程需要借助setter注入来完成,因此必须存在set方法,否则注入失败。

    //dao层
    public class UserDaoImpl implements UserDao{
        //.......
        @Override
        public void done(){
            System.out.println("UserDaoImpl.invoke......");
        }
    }
    //service层
    public class UserServiceImpl implements UserService {
        //需要注入的依赖
        private UserDao userDao;
    
        /**
         * set方法
         * @param userDao
         */
        public void setUserDao(UserDao userDao) {
            this.userDao = userDao;
        }
        @Override
        public void done(){
            userDao.done();
        }
    }
    
    基于xml的配置如下,通过使用<bean>的autowire属性启动名称为userService的自动装配功能
    
    <bean id="userDao"  class="com.zejian.spring.springIoc.dao.impl.UserDaoImpl" />
    <!-- byType 根据类型自动装配userDao-->
    <bean id="userService" autowire="byType" class="com.zejian.spring.springIoc.service.impl.UserServiceImpl" />
    byType模式可能存一种注入失败的情况,由于是基于类型的注入,因此当xml文件中存在多个相同类型名称不同的实例Bean时,Spring容器依赖注入仍然会失败,因为存在多种适合的选项,Spring容器无法知道该注入那种,此时我们需要为Spring容器提供帮助,指定注入那个Bean实例。可以通过<bean>标签的autowire-candidate设置为false来过滤那些不需要注入的实例Bean
    bean id="userDao"  class="com.zejian.spring.springIoc.dao.impl.UserDaoImpl" />
    
    <!-- autowire-candidate="false" 过滤该类型 -->
    <bean id="userDao2" autowire-candidate="false" class="com.zejian.spring.springIoc.dao.impl.UserDaoImpl" />
    
    <!-- byType 根据类型自动装配userDao-->
    <bean id="userService" autowire="byType" class="com.zejian.spring.springIoc.service.impl.UserServiceImpl" />
    
    除了上述的解决方案外,还可采用byName模式的自动装配,此时Spring只会尝试将属性名与bean名称进行匹配,如果找到则注入依赖bean。
    <bean id="userDao"  class="com.zejian.spring.springIoc.dao.impl.UserDaoImpl" />
    <bean id="userDao2" class="com.zejian.spring.springIoc.dao.impl.UserDaoImpl" />
    
    <!-- byName 根据名称自动装配,找到UserServiceImpl名为 userDao属性并注入-->
    <bean id="userService" autowire="byName" class="com.zejian.spring.springIoc.service.impl.UserServiceImpl" />

    构造器自动装配

    public class UserServiceImpl implements UserService {
    
        private UserDao userDao;
        //constructor模式
        public UserServiceImpl(UserDao userDao){
            this.userDao=userDao;
        }
    
    //    /**
    //     * set方法
    //     * @param userDao
    //     */
    //    public void setUserDao(UserDao userDao) {
    //        this.userDao = userDao;
    //    }
    
        @Override
        public void done(){
            userDao.done();
        }
    }
    
    基于xml配置:
    
    <bean id="userDao"  class="com.zejian.spring.springIoc.dao.impl.UserDaoImpl" />
    <!-- constructor自动装配userDao-->
    <bean id="userService" autowire="constructor" class="com.zejian.spring.springIoc.service.impl.UserServiceImpl" />
    在constructor模式下,存在单个实例则优先按类型进行参数匹配(无论名称是否匹配),当存在多个类型相同实例时,按名称优先匹配,如果没有找到对应名称,则注入失败,此时可以使用autowire-candidate=”false” 过滤来解决。

    基于注解的自动装配(@Autowired&@Resource&@Value)

    基于@Autowired注解的自动装配

    在Spring 2.5 中引入了 @Autowired 注释,它可以对类成员变量、方法及构造函数进行标注,完成自动装配的工作。 通过 @Autowired的使用标注到成员变量时不需要有set方法,请注意@Autowired 默认按类型匹配的

    <!-- 使用注解时必须启动注解驱动 -->
    <context:annotation-config />
    public class UserServiceImpl implements UserService {
        //标注成员变量
        @Autowired
        private UserDao userDao;
        //标注构造方法
        @Autowired
        public UserServiceImpl(UserDao userDao){
            this.userDao=userDao;
        }
        //标注set方法
        @Autowired
        public void setUserDao(UserDao userDao) {
            this.userDao = userDao;
        }
    
        @Override
        public void done(){
            userDao.done();
        }
    }
    
    显然上述代码我们通过3种方式注入userDao实例,xml配置文件只需声明bean的实例即可,在实际开发中,我们只需选择其中一种进行注入操作即可,建议使用成员变量注入,这样可以省略set方法和构造方法,相当简洁。
    
    
    @service
    public class UserServiceImpl implements UserService {
        //标注成员变量
        @Autowired
        private UserDao userDao;   
     }
    
    在@Autowired中还传递了一个required=false的属性,false指明当userDao实例存在就注入不存就忽略,如果为true,就必须注入,若userDao实例不存在,就抛出异常。由于默认情况下@Autowired是按类型匹配的(byType),如果需要按名称(byName)匹配的话,可以使用@Qualifier注解与@Autowired结合,请注意必须在xml配置中启动注解驱动
    public class UserServiceImpl implements UserService {
        //标注成员变量
        @Autowired
        @Qualifier("userDao1")
        private UserDao userDao;   
     }
    使用byName模式,xml配置如下:
    
    <!-- 根据@Qualifier("userDao1")自动识别 -->
    <bean id="userDao1" class="com.zejian.spring.springIoc.dao.impl.UserDaoImpl" />
    <bean id="userDao2" class="com.zejian.spring.springIoc.dao.impl.UserDaoImpl" />
    
    <bean id="userService" class="com.zejian.spring.springIoc.service.impl.UserServiceImpl" />

    基于@Resource注解的自动装配

    与@Autowried具备相同功效的还有@Resource,默认按 byName模式 自动注入,由J2EE提供,需导入Package: javax.annotation.Resource,可以标注在成员变量和set方法上,但无法标注构造函数。@Resource有两个中重要的属性:name和type。Spring容器对于@Resource注解的name属性解析为bean的名字,type属性则解析为bean的类型。因此使用name属性,则按byName模式的自动注入策略,如果使用type属性则按 byType模式自动注入策略。倘若既不指定name也不指定type属性,Spring容器将通过反射技术默认按byName模式注入。

    //@Autowired标注成员变量
    @Autowired
    @Qualifier("userDao")
    private UserDao userDao;  
    //上述代码等价于@Resource
    @Resource(name=“userDao”)
    private UserDao  userDao;//用于成员变量
    
    //也可以用于set方法标注
    @Resource(name=“userDao”)
    public void setUserDao(UserDao userDao) {
       this.userDao= userDao;
    }

    基于@Value注解的自动装配以及properties文件读取

    关于@Autowired和@Resource都分析完了,但这里存在一个问题,上述两种自动装配的依赖注入并不适合简单值类型,如int、boolean、long、String以及Enum等,对于这些类型,Spring容器也提供了@Value注入的方式,这是非常具备人性化的,可以解决很多硬编码问题。@Value接收一个String的值,该值指定了将要被注入到内置的java类型属性值,放心,不必关系类型转换,大多数情况下Spring容器都会自动处理好的。一般情况下@Value会与properties文件结合使用,也分两种情况一种是SpEL(有点类似于jsp的EL),另外一种是占位符方式,看一个简单例子jdbc.properties文件如下:

    jdbc.driver=com.mysql.jdbc.Driver
    jdbc.url=jdbc:mysql://127.0.0.1:3306/test?characterEncoding=UTF-8&allowMultiQueries=true
    jdbc.username=root
    jdbc.password=root

    利用注解@Value获取jdbc.url和jdbc.username的值,实现如下:

    /**
     * Created by zejian on 2017/1/18.
     * Blog : http://blog.csdn.net/javazejian [原文地址,请尊重原创]
     */
    public class UserServiceImpl implements UserService {
        //标注成员变量
        @Autowired
        @Qualifier("userDao")
        private UserDao userDao;
        //占位符方式
        @Value("${jdbc.url}")
        private String url;
        //SpEL表达方式,其中代表xml配置文件中的id值configProperties
        @Value("#{configProperties['jdbc.username']}")
        private String userName;
    
        @Override
        public void done(){
            System.out.println("url:"+url);
            System.out.println("username:"+userName);
            userDao.done();
        }
    }
    

     基于xml的配置如下:

    <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:util="http://www.springframework.org/schema/util"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
    
        <!--基于占位符方式 配置单个properties -->
        <!--<context:property-placeholder location="conf/jdbc.properties"/>-->
        <!--基于占位符方式 配置多个properties -->
        <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PreferencesPlaceholderConfigurer">
            <property name="location" value="conf/jdbc.properties"/>
        </bean>
    
        <!--基于SpEL表达式 配置多个properties id值为configProperties 提供java代码中使用 -->
        <bean id="configProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
            <property name="locations">
                <list>
                    <value>classpath:/conf/jdbc.properties</value>
                </list>
            </property>
        </bean>
    
        <!--基于SpEL表达式 配置单个properties -->
        <!--<util:properties id="configProperties" location="classpath:conf/jdbc.properties"/>-->
    
        <!--注解驱动 -->
        <context:annotation-config/>
    
         
     
    
        <bean id="userService" class="com.zejian.spring.springIoc.service.impl.UserServiceImpl"/>
    </beans>
     
  • 相关阅读:
    onLoad和DomContentLoad的区别
    懒加载和预加载区别
    各大浏览器特点
    移动端适配
    清除浮动的方法
    rem的计算
    粗结MySql数据库基础知识点之一
    单例模式(饿汉式单例模式与懒汉式单例模式)
    关于ajax技术
    浅谈EL与JSTL
  • 原文地址:https://www.cnblogs.com/hellohero55/p/12643443.html
Copyright © 2011-2022 走看看