装配Bean的三种方法

一.装配Bean的三种方法

1.在xml中显示配置(有些我们无法更改代码的类,可以通过xml方式配置使用)

2.在Java的接口和类中显示配置(第二考虑,避免xml泛滥,也更容易)

3.隐式Bean的发现机制和自动装配原则。(最优先,减少程序开发者的决定权,简单又不失灵活)

       当配置的类是你自身开发的工程,应该优先考虑java配置为主,Java配置又分自动装配和Bean名称配置,在没有歧义的基础上,优先使用自动装配,这样就能减少大量的xml配置,如果所需配置的类不是你自己开发的,建议使用xml方式。

二.装配详细方法

1.装配简易值

 <bean id="source" class="com.hly.spring.pojo.springIOC.Source">
    <property name="fruit" value="橙汁"/><!--property:构造方法的参数-->
    <property name="sugar" value="无糖"/>
    <property name="size" value="3"/>
</bean>
 <bean id="juiceMaker" class="com.hly.spring.pojo.springIOC.JuiceMaker" init-method="init" destroy-method="destroy">
        <property name="beverageShop" value="避风塘"/>
        <property name="source" ref="source"/><!--ref:引用之前定义的bean-->
    </bean>

1.1.id属性,spring能找到这个bean的编号

1.2.class属性,一个类的全限定名

1.3.property属性,定义类的属性,name是属性的名称,value是其值。

1.4.ref属性为应用对应的bean。

2.装配集合

public class ComplexAssemble {
    private Long id;
    private List<String> list;
    private Map<String,String> map;
    //主要用于读取Java的配置文件,各种语言都有自己所支持的配置文件,配置文件中很多变量是经常改变的,这样做也是为了方便用户,让用户能够脱离程序本身去修改相关的变量设置
    private Properties props;
    private Set<String> set;
    private String[]arrays;
    private List<User> listUser;

 <!--装配集合-->
    <bean id="complexAssemble" class="com.hly.spring.pojo.springBean.ComplexAssemble">
        <property name="id" value="1"/>
        <property name="list">
            <list>
                <!--多个value元素设置值-->
                <value>value-1ist-1</value>
                <value>value-1ist-2</value>
            </list>
        </property>
        <property name="map">
            <map>
                <!--entry元素设置值,包含一个键和一个值得设置-->
                <entry key="key1" value="value-key-1"/>
                <entry key="key2" value="value-key-2"/>
                <!--应用bean用的是key-ref,value-ref-->
            </map>
        </property>
        <property name="props">
            <props>
                <prop key="prop1">values-1</prop>
                <prop key="prop2">values-2</prop>
            </props>
        </property>
        <property name="set">
            <set>
                <value>values1</value>
                <value>values2</value>
            </set>
        </property>
        <property name="arrays">
            <array>
                <value>value-array-1</value>
                <value>value-array-2</value>
            </array>
        </property>
        <property name="listUser">
            <list>
                <!--引用之前定义的bean-->
                <ref bean="user2"/>
            </list>
        </property>
    </bean>

3.命名空间装配

暂略

4.通过注解装配Bean

4.1装配原则

1.更多的时候考虑注解装配Bean(annotation),减少xml的配置,注解功能更加强大,既能试下xml的功能,也提供了自动装配的功能,更加有利于程序开发。

2.两种方式让SpringIOC容器发现Bean

2.1组件扫描,通过定义资源方式,SpringIOC容器扫描对应的包,从而把Bean装配起来。

2.1自动装配,通过注解定义,使得一些依赖关系可以通过注解来完成。

3.目前最流行以注解为主,xml为辅

4.设么时候用xml

4.1系统存在公共的配置文件,properties,xml文件等,写在注解里,公共资源就分散了

4.2有时一些类来自第三方,xml来完成就会更加明确一些。

4.2.使用@Component装配Bean

ps

  • @Service用于标注业务层组件

  • @Controller用于标注控制层组件(如struts中的action)

  • @Repository用于标注数据访问组件,即DAO组件

  • @Component泛指组件,当组件不好归类的时候,我们可以使用这个注解进行标注

     作用:把普通pojo实例化到spring容器中,相当于配置文件中的<bean id="" class=""/>

     虽然有了@Autowired,但是我们还是要写一堆bean的配置文件,相当麻烦,而@Component就是告诉spring,我是pojo类,把我注册到容器中吧,spring会自动提取相关信息。

**
 * @author :hly
 * @date :2018/5/10
 */
@Component(value = "role")
public class Role {
    @Value("1")
    private int rolerId;
    @Value("hly")
    private String roleName;
    @Value("god")
    private String roleNote;

     1.@Component代表SpringIOC把这个类扫描成Bean的实例,Value可以简写成@Component("1");,不写的话,@SpringIOC就默认为类名,首写字母为小写为id。 

        2.id是int类型,注入时候,Spring会自动转化类型。

@ComponentScan
public class PojoConfig {

}

      上面这个类是告诉SpringIOC去哪里扫描它,包名要和上面的Role包名保持一致,这个类什么都没有。@ComponentScan默认是扫描当前包的路径的Java类。

       接下来就可以测试了。

import com.hly.spring.pojo.springBean.PojoConfig;
import com.hly.spring.pojo.springBean.Role;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

/**
 * @author :hly
 * @date :2018/5/10
 */
public class BeanTest {
    public static void main(String []y){
        ApplicationContext context = new AnnotationConfigApplicationContext(PojoConfig.class);
        Role role =  context.getBean(Role.class);
        System.err.print(role.getRolerId());
    }
}

       3.上面扫描的弊端在于只能扫描当前的包,接下来介绍怎么扫描别的包和多个包。

//@ComponentScan(basePackageClasses = {Role.class, RoleServiceImpl.class})
@ComponentScan(basePackages = {"com.hly,spring.pojo.springBean","com.hly,spring,service"})
public class ApplicationConfig {
}
       basePackages的可读性会更好一些,在项目中优先选择他,但在需要大量重构的项目中不要选择,选择另一个IDE会提示包被改动的报错,如果在项目中重复定义多个包,会造成对一个Bean进行多次扫描,重复创建对
@ComponentScan(basePackageClasses = {Role.class, RoleServiceImpl.class},basePackages = {"com.hly,spring.pojo.springBean","com.hly,spring,service"})

       上面这个类代替PojoConfig这个类,另外再定义两个类

package com.hly.spring.service;

import com.hly.spring.pojo.springBean.Role;

/**
 * @author :hly
 * @date :2018/5/10
 */
public interface RoleService {
    public void printRoleInfo(Role role);
}
package com.hly.spring.ServiceImpl;

import com.hly.spring.pojo.springBean.Role;
import com.hly.spring.service.RoleService;
import org.springframework.stereotype.Component;

/**
 * @author :hly
 * @date :2018/5/10
 */
//@Component表明他是Spring所需要的Bean
@Component
public class RoleServiceImpl implements RoleService {
    @Override
    public void printRoleInfo(Role role) {
        System.out.print(role.getRoleName());
    }
}
测试类
public class BeanTest {
    public static void main(String []y){
       // ApplicationContext context = new AnnotationConfigApplicationContext(PojoConfig.class);
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ApplicationConfig.class);
        Role role =  context.getBean(Role.class);
        RoleService roleService = context.getBean(RoleService.class);
        roleService.printRoleInfo(role);

    }
}
4.3自动注入@Autowired

(@Component是装配,@Autowired是注入装配的@Component)

1.@Autowired表示被修饰的类需要注入对象,spring会扫描所有被@Autowired标注的类,然后根据 类型 在ioc容器中找到匹配的类注入。

@Autowired自动装配(按类注入),通常情况,Spring是先完成Bean的定义和生成,然后寻找要注入的资源,如果发现@Autowire的这个注解,就会在Bean中进行查找,然后找到对应的类型,将其注入进来。

代码中使用@Autowired或@Resource注解方式进行装配,这两个注解的区别是:@Autowired 默认按类型装配,@Resource默认按名称装配,当找不到与名称匹配的bean才会按类型装配。 

package com.hly.spring.service;

import com.hly.spring.pojo.springBean.Role;

/**
 * @author :hly
 * @date :2018/5/10
 */
public interface RoleService { 
  public void printRoleInfo();
}
package com.hly.spring.ServiceImpl;

import com.hly.spring.pojo.springBean.Role;
import com.hly.spring.service.RoleService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * @author :hly
 * @date :2018/5/10
 */
public class RoleServiceImpl implements RoleService {
    //SpringIOC定位所有的Bean后,这个字段需要按类型注入,IOC就会寻找资源,然后将其注入。
    //requiredIOC找不到对应的资源,没有异常抛出
    @Autowired(required = false)
    private Role role = null;
    //@Autowired自动注入
    @Override
    public void printRoleInfo() {
        System.out.print(role.getRoleName());
    }
    //@Autowired也可以方法配置
    @Autowired
    public void setRole(Role role){
        this.role=role;
    }
   
}

按类注入role后,printRoleInfo没有参数。

2.@Primary优先注入,RoleService有两个实现类,IOC容器无法判断把哪个对象注入进来

public interface RoleService {
    //public void printRoleInfo();
}
@Component
public class RoleServiceImpl implements RoleService {
    @Override
    public void printRoleInfo(Role role) {
        System.out.print(role.getRoleName());
    }
}
/**
 * @author :hly
 * @date :2018/5/10
 */
@Component("roleService3")
@Primary
public class RoleServiceImpl2 implements RoleService {
    @Override
    public void printRoleInfo(Role role) {
        System.out.print(role.getRoleNote());
    }

}
public class BeanTest {
    public static void main(String []y){
       // ApplicationContext context = new AnnotationConfigApplicationContext(PojoConfig.class);
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ApplicationConfig.class);
        Role role =  context.getBean(Role.class);
        RoleService roleService = context.getBean(RoleService.class);
        roleService.printRoleInfo(role);

    }
}

输出的是RoleServiceImpl2的方法。

3.@Qualifier("")按名称注入

4.4使用@Bean转配Bean

1.@Componet只能注解在类上,不能注解在方法上

import com.hly.spring.pojo.springIOC.JuiceMaker;
import com.hly.spring.pojo.springIOC.Source;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * @author :hly
 * @date :2018/5/9
 */
@Configuration
public class Juice {

    @Bean(name = "juiceMaker2",initMethod = "init",destroyMethod = "myDestroy")
    public JuiceMaker juiceMaker(){
        JuiceMaker juiceMaker2 = new JuiceMaker();
        juiceMaker2.setBeverageShop("茶");
        Source source = new Source();
        source.setFruit("芒果");
        source.setSize(1);
        source.setSugar("无糖");
        juiceMaker2.setSource(source);
        return juiceMaker2;

    }
    public static void main(String []hly){
        //ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("spring-cfg.xml");
        //AnnotationConfigApplicationContext这个容器是为注解方式设计的
        ApplicationContext ctx = new AnnotationConfigApplicationContext(Juice.class);
        JuiceMaker juiceMaker = (JuiceMaker)ctx.getBean("juiceMaker2");
        System.out.println(juiceMaker.makeJuice());
        //ctx.close();


    }
}

ps

@Configuration:https://www.cnblogs.com/duanxz/p/7493276.html

@Configuration可理解为用spring的时候xml里面的<beans>标签

猜你喜欢

转载自blog.csdn.net/sirius_hly/article/details/80260287
今日推荐