精华内容
下载资源
问答
  • java bean注入之静态注入

    千次阅读 2018-02-13 15:19:04
    Java bean之容器调用机制作为java程序控制层数据交互部分的缓存,java bean的加载方式如上图所示,Spring容器根据xml <bean>标签的写入、java中的@configuration、@bean、@autowrite注解等信息,将...

    Java bean之容器调用机制


    作为java程序控制层数据交互部分的缓存,java bean的加载方式如上图所示,Spring容器根据xml <bean>标签的写入、java中的@configuration、@bean、@autowrite注解等信息,将相关的java bean的信息注册在容器的注册表中。之后Spring容器会根据注册表的信息将注册表中的bean类进行实例化,并将实例化后的bean对象与java程序中的bean实例绑定放入容器中,形成一个bean的缓存池,当java应用程序需要调用bean实例时,Spring容器会直接根据索引在缓存池中调用相应的bean实例。

    1、bean的定义

    bean的配置有三种方式:1、在xml文件中配置,2、使用注解定义并自动装配,3、基于java类提供Bean定义信息

     基于xml文件的配置

     对于基于XML的配置,Spring 2.0以后使用Schema的格式,使得不同类型的配置拥有了自己的命名空间,是配置文件更具扩展性。

    ①默认命名空间:它没有空间名,用于Spring Bean的定义;

    ②xsi命名空间:这个命名空间用于为每个文档中命名空间指定相应的Schema样式文件,是标准组织定义的标准命名空间;

    ③aop命名空间:这个命名空间是Spring配置AOP的命名空间,是用户自定义的命名空间。

    命名空间的定义分为两个步骤:第一步指定命名空间的名称;第二步指定命名空间的Schema文档样式文件的位置,用空格或回车换行进行分分隔。

    在Spring容器的配置文件中定义一个简要Bean的配置片段如下所示:

    一般情况下,Spring IOC容器中的一个Bean即对应配置文件中的一个<bean>。其中id为这个Bean的标识,通过容器的getBean()即可获取对应的Bean,在容器中起到定位查找的作用,是外部程序和Spring IOC容器进行交互的桥梁。class属性指定了Bean对应的实现类。getBean的入参包括name、requiredType、args;其中name不可为空,对应的是xml文件中<bean>的id,requiredType可为空,对应的是<bean>标签的class,标明这个bean的类型,传入格式为类对象形式,即 类名.class形式。

    使用注解配置信息启动spring容器

    Spring提供了一个context的命名空间,它提供了通过扫描类包以应用注解定义Bean的方式:

    复制代码
    <?xml version="1.0" encoding="UTF-8" ?>
    <!--①声明context的命名空间-->
    <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"
        xsi:schemaLocation="http://www.springframework.org/schema/beans 
             http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
             http://www.springframework.org/schema/context
             http://www.springframework.org/schema/context/spring-context-3.0.xsd"
             >
        <!--②扫描类包以应用注解定义的Bean-->
       <context:component-scan base-package="com.baobaotao.anno"/>
       <bean class="com.baobaotao.anno.LogonService"></bean>
       <!-- context:component-scan base-package="com.baobaotao" resource-pattern="anno/*.class"/ -->
       <!-- context:component-scan base-package="com.baobaotao">
           <context:include-filter type="regex" expression="com\.baobaotao\.anno.*Dao"/>
           <context:include-filter type="regex" expression="com\.baobaotao\.anno.*Service"/>
           <context:exclude-filter type="aspectj" expression="com.baobaotao..*Controller+"/>
       </context:component-scan -->
    </beans>
    复制代码

    在①处声明context命名空间,在②处即可通过context命名空间的component-scan的base-package属性指定一个需要扫描的基类包,Spring容器将会扫描这个基类包里的所有类,并从类的注解信息中获取Bean的定义信息。

    如果仅希望扫描特定的类而非基包下的所有类,你们可以使用resource-pattern属性过滤特定的类,如下所示:

    < context:component-scan base-package="com.baobaotao" resource-pattern="anno/*.class"/ >

    这里我们将基类包设置为com.baobaotao,默认情况下resource-pattern属性的值为"**/*.class",即基类包里的所有类。这里我们设置为"anno/*.class",则Spring仅会扫描基包里anno子包中的类。

    Bean注入

    传统方式下是在XML中配置,此时分别有属性注入、构造函数注入和工厂方法注入

    属性注入

    属性注入即通过setXxx()方法注入Bean的属性值或依赖对象,由于属性注入方式具有可选择性和灵活性高的优点,因此属性注入是实际应用中最常采用的注入方式。

    属性注入要求Bean提供一个默认的构造函数,并为需要注入的属性提供对应的Setter方法。Spring先调用Bean的默认构造函数实例化Bean对象,然后通过反射的方式调用Setter方法注入属性值。

    复制代码
    package com.baobaotao.anno;
    
    import org.springframework.beans.factory.BeanNameAware;
    
    public class LogonService implements BeanNameAware{
    
        private LogDao logDao;
        private UserDao userDao;
        private String value; 
    public void setUserDao(UserDao userDao) { this.userDao = userDao; } public void setLogDao(LogDao logDao) { this.logDao = logDao; }
        public void setValue(String value) {
            this.value = value;
        }
    public LogDao getLogDao() { return logDao; } public UserDao getUserDao() { return userDao; }
        public String getValue() {
    
     
            return value;
    }
    
    }
    复制代码

    bean.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"
        xsi:schemaLocation="http://www.springframework.org/schema/beans 
             http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
             http://www.springframework.org/schema/context
             http://www.springframework.org/schema/context/spring-context-3.0.xsd"
           default-autowire="byName"
             >
        <bean id="logDao" class="com.baobaotao.anno.LogDao"/>
        <bean id="userDao" class="com.baobaotao.anno.UserDao"/>
       <bean  id="logonService" class="com.baobaotao.anno.LogonService">
           <property name="logDao" ref="logDao"></property>
           <property name="userDao" ref="userDao"></property>   
    
     
           <property name="value" value="60000"></property>
    </ bean > </ beans >
    复制代码

    上述xml文件中,Spring JVM读取到相关配置后,首先将UserDao和LogDao进行bean实例化存放在容器中,然后再实例化logonService的时候,会根据property ref中的内容在容器中寻找匹配名称的实例bean注入到logonService的实例中,而value变量为基本类型变量,因此直接根据property中value的值注入logonService实例的变量value中。(注意:Spring只会检查bean中是否有setter方法,而是否有对应的属性变量则不做具体要求,但按照约定俗成的规则我们最好为其设定相应的属性变量。个人理解中,属性注入的方式实际上是根据property中的name的值匹配bean类中的变量名从而进行值注入的

    构造方法注入

    使用构造函数注入的前提是Bean必须提供带参数的构造函数。例如

    复制代码
    package com.baobaotao.anno;
    
    import org.springframework.beans.factory.BeanNameAware;
    
    public class LogonService implements BeanNameAware{
    
        private LogDao logDao;
        private UserDao userDao;
        private String value; 
    public LogonService(){} public LogonService(LogDao logDao, UserDao userDao,Sting value) { this.logDao = logDao; this.userDao = userDao;
            this.value = Value;
    } public void setUserDao(UserDao userDao) { this.userDao = userDao; } public void setLogDao(LogDao logDao) { this.logDao = logDao; }
        public void setValue(String value) {
            this.value = value;
        }
    public LogDao getLogDao() { return logDao; } public UserDao getUserDao() { return userDao; }
     
        public String getValue() {
            return value;
    }}
    复制代码

    bean.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"
        xsi:schemaLocation="http://www.springframework.org/schema/beans 
             http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
             http://www.springframework.org/schema/context
             http://www.springframework.org/schema/context/spring-context-3.0.xsd"
           default-autowire="byName">
    
        <bean id="logDao" class="com.baobaotao.anno.LogDao"/>
        <bean id="userDao" class="com.baobaotao.anno.UserDao"/>
       <bean class="com.baobaotao.anno.LogonService">
          <constructor-arg  ref="logDao"></constructor-arg>
           <constructor-arg ref="userDao"></constructor-arg>
    
     
          <constructor-arg index="2" type="int"><value>200</value> </constructor-arg>
    </ bean > </ beans >

    利用构造器方式注入bean分类可以有四种方式,根据类型匹配入参、根据索引匹配入参、索引类型联合匹配、自身类型反射入参。

    上例中xml <constructor-arg ref="logDao"></constructor-arg>即是反射入参方式。如果bean构造函数入参的类型是可辨别的,由于java反射机制可以获取构造函数入参的类型,即使构造函数的注入不提供类型和索引的信息,Spring依旧可以完成构造函数信息的注入。因为之前实例化了logDao和userDao的bean,因此可以根据其id用ref指引到其在容器中匹配的实例。<constructor-arg index="2" type="String"><value>200</value> </constructor-arg>则是典型的联合匹配,其中index为变量在构造器中入参的索引位置,代表第index个入参(起始索引为0),type为入参的类型,value标签中为注入的bean的值。

    当然,在type的值唯一的情况下,可以单独使用type来进行匹配,如上例value变量中,因为入参只有一个String类型,所以可以直接用 < constructor-arg index= "2" type="String"> <value>200</value> < / constructor-arg >
    其外,也可以直接用index标签进行匹配, < constructor-arg index= "2" > <value>200</value> < / constructor-arg >

    工厂方法注入

    非静态工厂方法:

    有些工厂方法是非静态的,即必须实例化工厂类后才能调用工厂放。

    复制代码
    package com.baobaotao.ditype;
    
    public class CarFactory {
       public Car createHongQiCar(){
           Car car = new Car();
           car.setBrand("红旗CA72");
           return car;
       }
       
       public static Car createCar(){
           Car car = new Car();
           return car;
       }
    }
    复制代码

    工厂类负责创建一个或多个目标类实例,工厂类方法一般以接口或抽象类变量的形式返回目标类实例,工厂类对外屏蔽了目标类的实例化步骤,调用者甚至不用知道具体的目标类是什么。

    复制代码
    <?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:p="http://www.springframework.org/schema/p"
        xsi:schemaLocation="http://www.springframework.org/schema/beans 
             http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
    
        <!-- 工厂方法-->
        <bean id="carFactory" class="com.baobaotao.ditype.CarFactory" />
        <bean id="car5" factory-bean="carFactory" factory-method="createHongQiCar">
        </bean>
    
    
    </beans>
    复制代码

    由于createHongQiCar为非静态方法,因此在调用该方法的时候需要有一个其所在类的实例,上述xml中 <bean id="carFactory" class="com.baobaotao.ditype.CarFactory" />即为实例化该类,随后<bean id="car5" factory-bean="carFactory" factory-method="createHongQiCar">用factory-bean元素指定调用的实例,再用factory-method指定调用的方发,从而创建新的bean。

    静态工厂方法:

    很多工厂类都是静态的,这意味着用户在无须创建工厂类实例的情况下就可以调用工厂类方法,因此,静态工厂方法比非静态工厂方法的调用更加方便。

    复制代码
    <?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:p="http://www.springframework.org/schema/p"
        xsi:schemaLocation="http://www.springframework.org/schema/beans 
             http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
    
        <bean id="car6" class="com.baobaotao.ditype.CarFactory"
            factory-method="createCar"></bean>
    
    </beans>

    上述xml运作原理与非静态方法原理类似,只是调用的方法是静态方法createCar,因此只需要用class指定方法所在类,再用factory-bean指定调用的静态方法即可。

    2、使用注解的方式

    使用注解定义Bean

    我们知道,Spring容器成功启动的三大要件分别是:Bean定义信息、Bean实现类以及Spring本身。如果采用基于XML的配置,Bean定义信息和Bean实现类本身是分离的,而采用基于注解的配置方式时,Bean定义信息即通过在Bean实现类上标注注解实现。

    下面是使用注解定义一个DAO的Bean:

    复制代码
    package com.baobaotao.anno;
    
    import org.springframework.stereotype.Component;
    import org.springframework.stereotype.Repository;
    //①通过Repository定义一个DAO的Bean
    
    @Component("userDao")
    public class UserDao {
    
    }
    复制代码

    在①处,我们使用@Component注解在UserDao类声明处对类进行标注,它可以被Spring容器识别,Spring容器自动将POJO转换为容器管理的Bean。

    它和以下的XML配置是等效的:

    <bean id="userDao" class="com.baobaotao.anno.UserDao"/>

    除了@Component以外,Spring提供了3个功能基本和@Component等效的注解,它们分别用于对DAO、Service及Web层的Controller进行注解,所以也称这些注解为Bean的衍型注解:(类似于xml文件中定义Bean<bean id=" " class=" "/>

    • @Repository:用于对DAO实现类进行标注;
    • @Service:用于对Service实现类进行标注;
    • @Controller:用于对Controller实现类进行标注;

    之所以要在@Component之外提供这三个特殊的注解,是为了让注解类本身的用途清晰化,此外Spring将赋予它们一些特殊的功能。

    使用注解配置信息启动spring容器

    Spring提供了一个context的命名空间,它提供了通过扫描类包以应用注解定义Bean的方式:

    复制代码
    <?xml version="1.0" encoding="UTF-8" ?>
    <!--①声明context的命名空间-->
    <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"
        xsi:schemaLocation="http://www.springframework.org/schema/beans 
             http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
             http://www.springframework.org/schema/context
             http://www.springframework.org/schema/context/spring-context-3.0.xsd"
             >
        <!--②扫描类包以应用注解定义的Bean-->
       <context:component-scan base-package="com.baobaotao.anno"/>
       <bean class="com.baobaotao.anno.LogonService"></bean>
       <!-- context:component-scan base-package="com.baobaotao" resource-pattern="anno/*.class"/ -->
       <!-- context:component-scan base-package="com.baobaotao">
           <context:include-filter type="regex" expression="com\.baobaotao\.anno.*Dao"/>
           <context:include-filter type="regex" expression="com\.baobaotao\.anno.*Service"/>
           <context:exclude-filter type="aspectj" expression="com.baobaotao..*Controller+"/>
       </context:component-scan -->
    </beans>
    复制代码

    在①处声明context命名空间,在②处即可通过context命名空间的component-scan的base-package属性指定一个需要扫描的基类包,Spring容器将会扫描这个基类包里的所有类,并从类的注解信息中获取Bean的定义信息。

    如果仅希望扫描特定的类而非基包下的所有类,你们可以使用resource-pattern属性过滤特定的类,如下所示:

    < context:component-scan base-package="com.baobaotao" resource-pattern="anno/*.class"/ >

    这里我们将基类包设置为com.baobaotao,默认情况下resource-pattern属性的值为"**/*.class",即基类包里的所有类。这里我们设置为"anno/*.class",则Spring仅会扫描基包里anno子包中的类。

    基于java类提供Bean定义

    在普通的POJO类中只要标注@Configuration注解,就可以为spring容器提供Bean定义的信息了,每个标注了@Bean的类方法都相当于提供了一个Bean的定义信息。

    复制代码
    package com.baobaotao.conf;
    
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    //①将一个POJO标注为定义Bean的配置类
    @Configuration
    public class AppConf {
            //②以下两个方法定义了两个Bean,以提供了Bean的实例化逻辑
        @Bean
        public UserDao userDao(){
           return new UserDao();    
        }
        
        @Bean
        public LogDao logDao(){
            return new LogDao();
        }
        //③定义了logonService的Bean
        @Bean
        public LogonService logonService(){
            LogonService logonService = new LogonService();
                    //④将②和③处定义的Bean注入到LogonService Bean中
            logonService.setLogDao(logDao());
            logonService.setUserDao(userDao());
            return logonService;
        }
    }
    复制代码

    ①处在APPConf类的定义处标注了@Configuration注解,说明这个类可用于为Spring提供Bean的定义信息。类的方法处可以标注@Bean注解,Bean的类型由方法返回值类型决定,名称默认和方法名相同,也可以通过入参显示指定Bean名称,如@Bean(name="userDao").直接在@Bean所标注的方法中提供Bean的实例化逻辑。

    在②处userDao()和logDao()方法定义了一个UserDao和一个LogDao的Bean,它们的Bean名称分别是userDao和logDao。在③处,又定义了一个logonService Bean,并且在④处注入②处所定义的两个Bean。

    因此,以上的配置和以下XML配置时等效的:

    <bean id="userDao" class="com.baobaotao.anno.UserDao"/>
    <bean id="logDao" class="com.baobaotao.anno.LogDao"/>
    <bean id="logService" class="com.baobaotao.conf.LogonService"
        p:logDao-ref="logDao" p:userDao-ref="userDao"/>

    基于java类的配置方式和基于XML或基于注解的配置方式相比,前者通过代码的方式更加灵活地实现了Bean的实例化及Bean之间的装配,但后面两者都是通过配置声明的方式,在灵活性上要稍逊一些,但是配置上要更简单一些。

    Bean的注解方式注入

     使用@Autowired进行自动注入

    Spring通过@Autowired注解实现Bean的依赖注入,下面是一个例子:

    复制代码
    package com.baobaotao.anno;
    
    import org.springframework.beans.factory.BeanNameAware;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.annotation.Qualifier;
    import org.springframework.stereotype.Service;
    //① 定义一个Service的Bean(不需要在XML中定义Bean)
    @Service
    public class LogonService implements BeanNameAware{
            //② 分别注入LogDao及UserDao的Bean(不需要在XML中定义property属性注入)
        @Autowired(required=false)
        private LogDao logDao;
        @Autowired
        @Qualifier("userDao")
        private UserDao userDao;
        
        public LogDao getLogDao() {
            return logDao;
        }
        public UserDao getUserDao() {
            return userDao;
        }
        
        public void setBeanName(String beanName) {
            System.out.println("beanName:"+beanName);        
        }
        
        public void initMethod1(){
            System.out.println("initMethod1");
        }
        public void initMethod2(){
            System.out.println("initMethod2");
        }
        
    }
     
    复制代码

    在①处,我们使用@Service将LogonService标注为一个Bean,在②处,通过@Autowired注入LogDao及UserDao的Bean。@Autowired默认按类型匹配的方式,在容器查找匹配的Bean,当有且仅有一个匹配的Bean时,Spring将其注入到@Autowired标注的变量中。

    使用@Autowired的required属性

    如果容器中没有一个和标注变量类型匹配的Bean,Spring容器启动时将报NoSuchBeanDefinitionException的异常。如果希望Spring即使找不到匹配的Bean完成注入也不用抛出异常,那么可以使用@Autowired(required=false)进行标注:

    @Service
    public class LogonService implements BeanNameAware{
        @Autowired(required=false)
        private LogDao logDao;
            ...
    }

    默认情况下,@Autowired的required属性的值为true,即要求一定要找到匹配的Bean,否则将报异常。

    使用@Qualifier指定注入Bean的名称

    如果容器中有一个以上匹配的Bean时,则可以通过@Qualifier注解限定Bean的名称,如下所示:

    复制代码
    @Service
    public class LogonService implements BeanNameAware{
        @Autowired(required=false)
        private LogDao logDao;
    //①注入名为UserDao,类型为UserDao的Bean @Autowired @Qualifier(
    "userDao") private UserDao userDao; }
    复制代码

    这里假设容器有两个类型为UserDao的Bean,一个名为userDao,另一个名为otherUserDao,则①处会注入名为userDao的Bean。

     对类方法进行标注

    @Autowired可以对类成员变量及方法进行标注,下面我们在类的方法上使用@Autowired注解:

    复制代码
    package com.baobaotao.anno;
    
    import org.springframework.beans.factory.BeanNameAware;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.annotation.Qualifier;
    import org.springframework.stereotype.Service;
    
    @Service
    public class LogonService implements BeanNameAware{
        
        private LogDao logDao;
        private UserDao userDao;
        
        
        @Autowired
        public void setLogDao(LogDao logDao) {
            this.logDao = logDao;
        }
        
        @Autowired
        @Qualifier("userDao")
        public void setUserDao(UserDao userDao) {
            System.out.println("auto inject");
            this.userDao = userDao;
        }
        
    }
    复制代码

    上例中,当所有的bean被定义加载完毕存储在容器中后,实例化LongService的时候容器会调用@Autowired标注的方法在容器中寻找与入参类型匹配的bean注入到LongService的实例中。

    如果一个方法拥有多个入参,在默认情况下,Spring自动选择匹配入参类型的Bean进行注入。Spring允许对方法入参标注@Qualifier以指定注入Bean的名称,如下所示:

        @Autowired
        public void init(@Qualifier("userDao")UserDao userDao,LogDao logDao){
            System.out.println("multi param inject");
            this.userDao = userDao;
            this.logDao =logDao;
        }

    在以上例子中,UserDao的入参注入名为userDao的Bean,而LogDao的入参注入LogDao类型的Bean。

    一般情况下,在Spring容器中大部分的Bean都是单实例的,所以我们一般都无须通过@Repository、@Service等注解的value属性为Bean指定名称,也无须使用@Qualifier按名称进行注入。

     对标准注解的支持

    此外,Spring还支持@Resource和@Inject注解,这两个标准注解和@Autowired注解的功能类型,都是对类变量及方法入参提供自动注入的功能。@Resource要求提供一个Bean名称的属性,如果属性为空,则自动采用标注处的变量名或方法名作为Bean的名称。

    复制代码
    package com.baobaotao.anno;
    
    import javax.annotation.PostConstruct;
    import javax.annotation.PreDestroy;
    import javax.annotation.Resource;
    
    import org.springframework.stereotype.Component;
    
    @Component
    public class Boss {
        
        private Car car;
        
        public Boss(){
            System.out.println("construct...");
        }
        
        @Resource("car")
        private void setCar(Car car){
            System.out.println("execute in setCar");
            this.car = car;
        }
    }
    复制代码

    这时,如果@Resource未指定"car"属性,则也可以根据属性方法得到需要注入的Bean名称。可见@Autowired默认按类型匹配注入Bean,@Resource则按名称匹配注入Bean。而@Inject和@Autowired一样也是按类型匹配注入的Bean的,只不过它没有required属性。可见不管是@Resource还是@Inject注解,其功能都没有@Autowired丰富,因此除非必须,大可不必在乎这两个注解。(类似于Xml中使用<constructor-arg ref="logDao"></constructor-arg>或者<property name="logDao" ref="logDao"></property>进行注入,如果使用了@Autowired或者Resource等,这不需要在定义Bean时使用属性注入和构造方法注入了)

     关于Autowired和@Resource

    1.@Autowired注入是按照类型注入的,只要配置文件中的bean类型和需要的bean类型是一致的,这时候注入就没问题。但是如果相同类型的bean不止一个,此时注入就会出现问题,Spring容器无法启动。 
    2.@Resourced标签是按照bean的名字来进行注入的,如果我们没有在使用@Resource时指定bean的名字,同时Spring容器中又没有该名字的bean,这时候@Resource就会退化为@Autowired即按照类型注入,这样就有可能违背了使用@Resource的初衷。所以建议在使用@Resource时都显示指定一下bean的名字@Resource(name="xxx") 

     让@Resource和@Autowired生效的几种方式

    1.在xml配置文件中显式指定 

    <!-- 为了使用Autowired标签,我们必须在这里配置一个bean的后置处理器 -->  
        <bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor" />   
          
        <!-- 为了使用@Resource标签,这里必须配置一个后置处理器 -->  
        <bean class="org.springframework.context.annotation.CommonAnnotationBeanPostProcessor" />   

    2.在xml配置文件中使用context:annotation-config 它是对已注册Bean的进行操作的配置,也就是说,Bean需要首先通过某种方式(比如Xml配置,或者其他注解)被注册,然后使用这个配置,可以对已注册的Bean进行进一步操作(比如注入到某个类的内部),也就是说,这个配置是用于“激活”已注册的Bean的,让已注册的Bean开始工作。 

    <context:annotation-config />

    3.在xml配置文件中使用context:component-scan 首先有和<context:annotation-config/>一样的作用,此外,它还可以扫描指定包下的类,将拥有注解的它们注册到Spring中。 

    <context:component-scan base-package="com.baobaotao.anno"/>

    如果用<context:annotation-config/>,我们还需要配置Xml注册Bean,而使用<context:component-scan />的话,注册的步骤都免了,当然前提是我们对需要扫描的类使用的注解(比如@Componet,@Service),而如果同时使用两个配置的话,<context:annotation-config/>会被忽略掉。


    参考引入:spring中bean配置和bean注入

    展开全文
  • java项目】Service注入或Bean注入两种实现方法

    背景:controller及service上级路径均为"com.pcl.los"


    一、Service注入

    1.在进入项目执行applicationContext.xml时先扫描com.pcl.los

    <context:component-scan base-package="com.pcl.los" />

    2.在ServiceImpl实现类最上方写入:@Service("iDepartmentsSrv")

    @Service("iDepartmentsSrv")
    public class DepartmentsSrvImpl implements IDepartmentsSrv {

    //方法块

    }

    3.在Controller中使用

    @Autowired
     IDepartmentsSrv iDepartmentsSrv;


    二、Bean注入

    1.在进入项目执行applicationContext.xml时先扫描 配置文件beanConfig.xml

    <context:component-scan base-package="com.pcl.los.controller" />

    <import resource="beanConfig.xml"/>

    2.在beanConfig.xml中注入

     <bean id="iDepartmentsSrv" class="com.pcl.los.service.impl.DepartmentsSrvImpl"></bean>

    3.在Controller中使用

    @Autowired
     IDepartmentsSrv iDepartmentsSrv;


    或这样:

    2.在beanConfig.xml中注入

    <!-- 客户服务 -->
     <bean id="iDepend_09" class="esbSrv.depend.service.impl.Depend_09_impl"></bean>
     
     <!-- 账户服务依赖客户-->
     <bean id="iDeductionService" class="account.service.impl.DeductionServiceImpl">
      <property name="iDepend_09" ref="iDepend_09"></property>
     </bean>

    <!-- 其他服务依赖账户服务-->
     <bean id="srv09_001" class="esbSrv.provide.service.impl.EsbSrvImpl09_001">
      <property name="iDeductionService" ref="iDeductionService"></property>
     </bean>

    3.在ServiceImpl中使用

    //客户服务
     private IDepend_09 iDepend_09;

     public void setiDepend_09(IDepend_09 iDepend_09) {
      this.iDepend_09 = iDepend_09;
     }



    注意:不可同时存在Bean注入又Service注入,会导致注入失败。






    

    展开全文
  • 主要介绍了Java的Spring框架中bean的继承与内部bean注入,Spring框架是Java的SSH三大web开发框架之一,需要的朋友可以参考下
  • Spring bean注入之注解注入-- @Autowired原理 之前我们已经讲述过bean注入是什么了,也使用了xml的配置文件进行bean注入,这也是Spring的最原始的注入方式(xml注入)。 本节课就讲注解注入。 主要讲解的注解有以下...

    之前我们已经讲述过bean注入是什么了,也使用了xml的配置文件进行bean注入,这也是Spring的最原始的注入方式(xml注入)。

    本节课就讲注解注入。

    主要讲解的注解有以下几个:

    @Autowired、 @Service、@Repository、@Controller 、@Component、@Bean、@Configuration、@Resource

    一、@Autowired

    概念:

    @Autowired 注释,它可以对类成员变量、方法及构造函数进行标注,完成自动装配的工作。 通过 @Autowired的使用来消除 set ,get方法。

    在使用@Autowired之前,我们对一个bean配置起属性时,用的是

    <property name="属性名" value=" 属性值"/>    
    

    使用@Autowired之后,我们只需要在需要使用的地方使用一个@Autowired 就可以了。

    代码使用:

    public interface StudentService {
        public boolean login(String username,String password);
    }
    
    
    @Service
    public class StudentServiceImpl implements StudentService {
    
        @Override
        public boolean login(String username,String password) {
           if("crush".equals(username)&&"123456".equals(password)){
                System.out.println("登录成功");
                return true;
            }
            return false;
        }
    }
    
    @Controller
    public class StudentController {
        @Autowired
        private StudentService studentService;
            public void login(){
           boolean crush = studentService.login("crush", "123456");
           if(crush){
               System.out.println("crush"+"登录成功!!!!!");
           }else{
               System.out.println("登录失败");
           }
        }
    }
    

    测试:

        @Test
        public void login(){
            ApplicationContext applicationContext = new ClassPathXmlApplicationContext("application.xml");
            StudentController student = applicationContext.getBean("studentController", StudentController.class);
            student.login();
        }
    

    我们在使用@Autowired 之后不用再去xml文件中继续配置了。

    注意细节:

    1、使用@Autowired的当前类也必须由spring容器托管(打@Coponent、@Controller、@Service 、@repository)

    2、不管是public 和 private 修饰的字段都可以自动注入

    3、默认情况下,使用@Autowired注解的属性一定要被装配,如果在容器中找不到该类型的bean注入,就会报错。如果允许不被装配就可以将@Autowired的required属性为false

    4、@Autowired 是基于类型的注入,如果当前类型属性在容器中只有一个Bean, 那么属性名不限制,但一般建议遵循类名首字母小写的规则‘

    5、如果当前属性类型在容器中有个多个Bean,那么必须要通过属性名 或者 @Qualifier 指定Bean name

    6、@Autowired 可以打在XXX[] 、List上 ,此时会将容器中所有XXX类型的bean 都注入进去、且属性名没有约束,但是注意可以通过@Qualifier指定注入指定beanName的bean,属性名是没有约束作用的

    7、@Autowired可以打在Map<String,XXX>上,此时所有XXX类型的bean都会被注入 ,beanName 为key ,对象为value,但是注意可以通过@Qualifier指定注入指定beanName的bean,属性名是没有约束作用的

    2、@Service、@Repository、@Controller、@Component

    这几个注解的含义都是一样的,都是写在类上面或者接口上面,将自动注册到Spring容器。

    1、@Service用于标注业务层组件
    2、@Controller用于标注控制层组件(如struts中的action)
    3、@Repository用于标注数据访问组件,即DAO组件.
    4、@Component泛指组件,当组件不好归类的时候,我们可以使用这个注解进行标注。 注册到Spring 容器中。

    使用

    @Service
    public class StudentServiceImpl implements StudentService {
    }
    
    @Controller
    public class StudentController {
    }
    

    其作用就相当于在application.xml文件中 写以下代码

    <bean id="studentServiceImpl" class="com.crush.service.impl.StudentServiceImpl"/>
    <bean id="studentController" class="com.crush.controller.StudentController"/>
    

    当然如果要使注解生效,必不可少的要加上这样一行扫描包的代码

    <!--让com.crush包下类中使用 spring的注解生效-->
    <context:component-scan base-package="com.crush"/>
    

    3、@Bean

    @Bean明确地指示了一种方法,什么方法呢——产生一个bean的方法,并且交给Spring容器管理;从这我们就明白了为啥@Bean是放在方法的注释上了,因为它很明确地告诉被注释的方法,你给我产生一个Bean,然后交给Spring容器,剩下的你就别管了

    4、@Configuration

    @Configuration用于定义配置类 这里只简单说明。

    Spring 目前是有两种配置方式的,一种是xml文件配置加Java 代码,这种是从Spring出生的时候就有了,另一种是完全使用Java代码来进行配置及编写,这是在Spring 后面版本才出的。

    从Spring3.0,@Configuration用于定义配置类,可替换xml配置文件被注解的类内部包含有一个或多个被@Bean注解的方法,这些方法将会被AnnotationConfigApplicationContext或AnnotationConfigWebApplicationContext类进行扫描,并用于构建bean定义,初始化Spring容器。

    这种方式更加受java程序员的喜欢。

    @Configuration
    public class MyConfig {
    }
    

    并且这种方式在后续的学习中,在Spring源码中使用的非常多。

    5、@Resource

    @Resource的作用相当于@Autowired,只不过@Autowired按byType自动注入,而@Resource默认按 byName自动注入罢了。@Resource有两个属性是比较重要的,分是name和type,Spring将@Resource注解的name属性解析为bean的名字,而type属性则解析为bean的类型。所以如果使用name属性,则使用byName的自动注入策略,而使用type属性时则使用byType自动注入策略。如果既不指定name也不指定type属性,这时将通过反射机制使用byName自动注入策略。

    @Autowired 与@Resource的区别

    @Autowired原理

    自言自语

    难啊难啊。

    展开全文
  • Java多线程中Spring的Bean注入失败

    千次阅读 2018-05-30 14:51:02
    在spring框架进行项目开发,平时遇到了需要批量处理的数据的时候,会选择多线程进行数据批跑,但是会发现,启动多线程后,线程会出现service或者mapper文件注入失败的问题,导致线程启动失败,其中bean注入方式...

    问题说明 : 

    在spring框架进行项目开发,平时遇到了需要批量处理的数据的时候,会选择多线程进行数据批跑,但是会发现,启动多线程后,线程会出现service或者mapper文件注入失败的问题,导致线程启动失败,其中bean的注入方式选择的是spring常规的注解@Autowired进行注入

    原因分析 :

    web容器在启动应用时,spring容器是无法感知多线程的那些bean的,所以多线程的bean类无法获取spring容器的上下文,并不能通过@Autowired注入需要的bean

    解决方案 :

    线程中获取bean

    import org.springframework.context.ApplicationContext;
    public class ServiceFactory {
    	public static ApplicationContext context = null;
    	public static Object getInstance(String serviceName) {
    		if (null == context) {
    			context = ApplicationContextLoaderListener.getApplicationContext();
    		}
    		return context.getBean(serviceName);
    	}
    }
    public class CardThread extends Thread{
    	@Autowired
    	private FinanceCardDoMapper financeCardDoMapper;
    	
    	private Integer startIndex;
    	private Integer endIndex;
    	private List<FinanceCardDo> dataList;
    	public CardThread(Integer startIndex ,Integer endIndex ,List<FinanceCardDo> dataList) {
    		super();
    		this.startIndex = startIndex; 
    		this.endIndex = endIndex; 
    		this.dataList = dataList; 
    	}
    	public void run(){
    		financeCardDoMapper = (FinanceCardDoMapper)MyBatisConfig.getApplicationContext().getBean(FinanceCardDoMapper.class);
    		for (FinanceCardDo financeCardDo : dataList) {
    			if (financeCardDo.getIndex() > startIndex && financeCardDo.getIndex() <= endIndex) {
    				financeCardDo.setCardNo(DesUtil.encrypt("dfsghjkl",financeCardDo.getCardNo()));
    				financeCardDo.setBankMobile(DesUtil.encrypt("dfsghjkl",financeCardDo.getBankMobile()));
    				financeCardDoMapper.updateByPrimaryKeySelective(financeCardDo);
    				System.out.println("该用户银行卡更新完成:index:" + financeCardDo.getIndex());
    			}
    		}
    	}
    }

     

     

     

     

     

     

     

    展开全文
  • 总述:Spring 相互引用注入会报错 不要构建成bean1引用bean2,然后bean2直接引用bean1...如果使用构造器注入,Requested bean is currently in creation: Is there an unresolvable circular reference? 如果...
  • 主要介绍了详解Java的Spring框架中bean注入集合,Spring是Java的SSH三大web开发框架之一,需要的朋友可以参考下
  • 主要介绍了Java的Spring框架中bean的依赖注入,讲解了以构造函数为基础的依赖注入和基于setter方法的依赖注入的方式,需要的朋友可以参考下
  • Spring给bean注入日期属性的方法

    千次阅读 2017-11-24 17:06:55
    通常情况下,我们给Spring的bean注入属性可以通过setter方法和构造器方法给bean注入属性值,这两种方法都需要使用property标签给bean的属性赋值。 如下所示,使用setter方法给bean注入Date属性值 public ...
  • 【SpringBoot注解-3】Bean注入相关注解

    千次阅读 2019-10-22 16:00:45
    常见注解总结之Bean注入1 @Autowired1.1 @Autowired特点1.2 使用示例1.2 常见异常2 @Resource3 @Inject SpringBoot中要实现bean的注入,依赖三种注解: @Autowired @Inject @Resource 1 @Autowired 在Spring Boot...
  • 主要给大家介绍了关于Spring循环依赖的正确性,以及Bean注入的顺序关系的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧。
  • Java方式bean注入以及自动配置

    千次阅读 2019-04-17 15:21:46
    Java配置 Java配置的本质上,就是使用一个Java类去代替xml配置,这种配置方式在目前最主流的Spring Boot中得到了广泛的使用。 1、引入相关Spring相关依赖 2、创建Java配置类: /** * 这是一个Java配置类,它的作用...
  • Spring的bean注入方式

    千次阅读 2015-06-28 16:24:10
    Spring中依赖注入有三种注入方式: 一、构造器注入; 二、设值注入(setter方式注入);...三、Feild方式注入(注解方式注入)。...一、构造器注入 ... 构造器注入顾名思义...Java代码  package cn.glzaction
  • Spring如何为bean注入null值

    千次阅读 2017-04-10 22:30:17
    今天我们一起来学习下如何为bean注入null值,也就是说设置空值。有的同学可能会说,设置空值还需要学习么,不设置这个属性就好了。这样理解也是正确的,对于属性设置,可以这么做,但是如果对构造函数注入,不设置...
  • Spring BeanJavaConfig自动化装配bean

    千次阅读 2016-11-13 21:51:37
     Spring会自动发现应用上下文中所创建的bean  2、自动装配:  Spring会自动满足bean之间的依赖关系 比较有趣的是,Spring的自动化装配使用了零xml配置,而是使用全代码配置,其中代码的配置文件使用@...
  • 通过@Resource获取@Bean注入的bean

    千次阅读 2018-09-26 15:23:01
    首先了解一下@Resource注解和@Bean注解的作用 @Bean @Bean是一个方法级别上的注解,主要用在@Configuration注解的类里,也可以用在@Component注解的类里。作用为注册bean对象。 @Bean注解在返回实例的方法上,如果...
  • Java(多)线程中注入Spring的Bean

    千次阅读 2016-10-28 19:53:41
    问题说明 : 今天在web应用中用到了Java多线程的技术来并发处理一些... 原因分析 :web容器在启动应用时,并没有提前将线程中的bean注入(在线程启动前,web容易也是无法感知的) 解决方案 :线程中获取bean import org
  • Springboot bean注入 ---- Jedis注入

    千次阅读 2017-06-05 13:56:04
    @Configuration public class RedisDao{ ... } @Bean public RedisDao redisFactory(){ ... return new RedisDao(); }
  • JAVA简单AOP切面编程;依赖注入;代码配置Bean源码 JAVA简单AOP切面编程;依赖注入;代码配置Bean源码
  • javabean注入方式

    2019-09-06 17:17:19
    @Resource是java自己定义的,如果name和type都没有指定,默认按照name匹配,如果匹配到则注入。没有则按照type去匹配,匹配到一个则装配,如果是匹配到多个则又根据名字注入,如果有多个类型匹配,但是名称不匹配则抛...
  • String Bean 注入方式

    千次阅读 2018-04-27 17:33:27
    注解注入: 属性注入的注解(说明:使用注解注入的方式,可以不用提供set方法) 如果是注入的普通类型,可以使用value注解 @Value -- 用于注入普通类型(基本数据类型和字符串) *如果注入的是对象类型,使用如下注解...
  • 1) IOC依赖注入工作流程(1)Spring 容器高层视图:三种配置bean的方式 (2)完整Bean的作业流程:通过配置文件,最后生成bean实例 2) 三种配置注入bean方式—示例:三种方式、区别和使用场景(1)基于XML的配置...
  • Spring单例Bean注入非单例Bean

    千次阅读 2014-05-22 17:07:50
     如果一个singleton bean要引用另外一个singleton bean,或者一个非singleton bean要引用另外一个非singleton bean时,通常情况下将一个bean定义为另一个bean的property值就可以了。不过对于具有不同生命周期
  • Spring三种bean注入方式

    万次阅读 2019-04-10 10:13:04
    Spring中依赖注入有三种注入方式: 一、构造器注入; 二、设值注入(setter方式注入); 三、Feild方式注入(注解方式注入)。 一、构造器注入 构造器注入顾名思义就是在程序组件...import java.util.List; impo...
  • bean注入情况下的Junit单元测试

    千次阅读 2016-04-06 17:25:25
    一般对于有bean注入的类进行方法单元测试时,会发现bean对象并没有注入进来,对象是null。这种情况可以使用如下方式解决: @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = { "/META...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 214,594
精华内容 85,837
关键字:

bean注入java

java 订阅