Spring使用Java Config和XML装配Bean总结

Spring使用Java Config和XML装配Bean总结_第1张图片
摘要

Bean的创建

配置Spring自动扫描组件

  • XML的配置方式

@Component
public class OneBean {
}
public static void main(String[] args) {
    ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
    OneBean bean = context.getBean("oneBean",OneBean.class);
    System.out.println(bean);
}
  • Java Config
@Configuration //标注了该注解的类是一个Spring的配置类,等价于原先的applicationContext.xml
@ComponentScan // 启动该注解,表明, 开启Spring的注解自动扫描 , 默认情况下,扫描当前类所在包及其子包
public class Config {
}
public static void main(String[] args) {
    ApplicationContext context = new AnnotationConfigApplicationContext(Config.class);
    OneBean oneBean = context.getBean(OneBean.class);
    System.out.println(oneBean);
}

构造器创建bean

  • XML

  • Java Config
@Configuration
public class Config {

    @Bean // 表明这是一个Spring 管理的bean
    public OneBean oneBean() {
        // 显然,这个Bean的CLass 是OneBean.class
        // 在spring 中,bean的 id 是不能重复的,而现在使用java config来代替xml配置
        // 在java config 方法名就是这个bean的id
        return new OneBean();
    }
}

静态工厂方法创建bean

示例代码:

public class OneBean {
}

public class OneBeanFactory {
    public static OneBean getOneBean() {
        return new OneBean();
    }
}
  • XML

  • Java Config
@Configuration
public class Config {

    @Bean
    public OneBean oneBean1() {
        return OneBeanFactory.getOneBean();
    }
}

实例工厂方法创建bean

代码示例:

public class OneBean {
}

public class OneBeanFactory {
    public OneBean getOneBean() {
        return new OneBean();
    }

  • XML


  • Java Config
@Configuration
public class Config {

    @Bean
    public OneBean oneBean2() {
        return new OneBeanFactory().getOneBean();
    }
}

通过FactoryBean创建Bean

代码示例:

public class OneBean {
}

public class OneBeanFactory implements FactoryBean {

    @Override
    public OneBean getObject() throws Exception {
        return new OneBean();
    }

    @Override
    public Class getObjectType() {
        return OneBean.class;
    }

    @Override
    public boolean isSingleton() {
        return true;
    }
}
  • XML

  • Java Config
@Configuration
public class Config {

    /**
     * OneBeanFactory 类实现了 Spring的 FactoryBean 接口,
     * Spring 知道这个类是用来创建 OneBean 对象的,
     * 方法虽然返回了 OneBeanFactory , 但是Spring 会帮我们用这个类来创建 OneBean
     */
    @Bean
    public OneBeanFactory oneBean() {
        return new OneBeanFactory();
    }

    public static void main(String[] args) {
        ApplicationContext context = new AnnotationConfigApplicationContext(Config.class);
        OneBean oneBean = context.getBean("oneBean", OneBean.class);
        System.out.println(oneBean);

        // 通过 "&"的方式获取对应的Factory
        OneBeanFactory oneBeanFactory = context.getBean("&oneBean", OneBeanFactory.class);
        System.out.println(oneBeanFactory);
    }
}

可以通过"&"的方式来获取对应Factory的原因

public interface BeanFactory {

    /**
     * Used to dereference a {@link FactoryBean} instance and distinguish it from
     * beans created by the FactoryBean. For example, if the bean named
     * {@code myJndiObject} is a FactoryBean, getting {@code &myJndiObject}
     * will return the factory, not the instance returned by the factory.
     */
    String FACTORY_BEAN_PREFIX = "&";

修改Bean的Scope

Scope选项:

  • singleton : 单例。默认情况下,Spring中的Bean都是单例的。
  • prototype : 多例。表示每次获得Bean都会生成一个新的对象。注意:scope为prototype的Bean,在Spring容器启动的时候不会初始化这些Bean
  • request : 表示在一次http请求中创建Bean(只适用于web应用)
  • session : 表示在一个用户会话内(HttpSession)有效(只适用于web应用)

配置

  • XML

  • Java Config
@Configuration
public class Config {

    @Bean
    @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
    public OneBean oneBean() {
        return new OneBean();
    }

    public static void main(String[] args) {
        ApplicationContext context = new AnnotationConfigApplicationContext(Config.class);
        OneBean oneBean1 = context.getBean("oneBean", OneBean.class);
        OneBean oneBean2 = context.getBean("oneBean", OneBean.class);
        System.out.println(oneBean1 == oneBean2); //false 
    }
}

Bean的注入

普通元素的注入

需求代码:

@Setter
@ToString
public class OneBean {
    private String name;
}
  • XML

    

  • Java Config
@Configuration
public class Config {

    @Bean
    public OneBean oneBean() {
        OneBean oneBean = new OneBean();
        oneBean.setName("xxx");
        return oneBean;
    }
}

Java Config 实现对象注入

示例代码:

@Setter
@Getter
public class SomeBean {
    private OtherBean otherBean;
}

public class OtherBean {
}

@Configuration
public class Config {

    @Bean
    public OtherBean otherBean() {
        return new OtherBean();
    }

    @Bean
    public OtherBean otherBean2() {
        return new OtherBean();
    }

    @Bean
    public SomeBean someBean() {
        SomeBean someBean = new SomeBean();
        //因为在otherBean()方法上有@Bean注解
        //Spring会拦截所有对该方法的调用.并确保直接返回该方法创建的Bean
        someBean.setOtherBean(otherBean());
        return someBean;
    }

    /**
     * 也可以通过方法的参数来注入所需要的对象
     * 通过这种方式来引用其他的Bean通常是最佳的选择.
     * 因为他不会要求被注入的Bean和当前Bean声明到同一个配置类中
     * 

* 如果Spring的容器中存在 相同类型 的Bean , * 1> 可以使用 @Qualifier("name") 来指定Bean的name * 2> 也可以使用 方法参数名 来 指定对应的Bean */ // @Bean // public SomeBean someBean2(@Qualifier("otherBean2") OtherBean bean) { // SomeBean someBean = new SomeBean(); // someBean.setOtherBean(bean); // return someBean; // } @Bean public SomeBean someBean2(OtherBean otherBean) { SomeBean someBean = new SomeBean(); someBean.setOtherBean(otherBean); return someBean; } public static void main(String[] args) { ApplicationContext context = new AnnotationConfigApplicationContext(Config.class); SomeBean someBean = context.getBean("someBean2", SomeBean.class); OtherBean otherBean = context.getBean("otherBean", OtherBean.class); OtherBean otherBean2 = context.getBean("otherBean2", OtherBean.class); System.out.println(someBean.getOtherBean() == otherBean); //true System.out.println(someBean.getOtherBean() == otherBean2); //false } }

使用Java Config @Bean 注解的方式可以采用任何必要的Java 功能来构建Bean。

@Autowired 和 @Resource

@Autowired

  • spring提供的注解.作用于字段或者setter方法,根据依赖对象类型去找.
  • 默认情况下必须要求依赖对象必须存在;如果要允许null 值,可以设置它的required属性为false @Autowired(required=false)
  • 可以通过使用 @Qualifier来指定bean的name

@Resource

  • J2EE规范的注解, @Resource 也可以作用于字段或者setter方法
  • @Resource必须要求有匹配的对象
  • 首先按照名字去找;如果按照名字找不到,再按照类型去找,但如果找到多个匹配类型,报错
  • 可以直接使用name属性指定bean的名称
@Resource(name="mybean1")
private Mybean mybean;

等价于

@Autowired
@Qualifier("mybean1")
private Mybean mybean;

Bean的初始化和销毁方法

需求:

  • 某些bean需要在spring实例化完成之后,去调用bean上面的一个初始化方法来完成bean的初始化工作。
  • 某些bean需要在spring正常销毁之前,调用一个结束方法(销毁方法)去完成一些清理工作。

示例代码:

public class OneBean {

    public void init() {
        System.out.println("init...");
    }

    public void close() {
        System.out.println("close...");
    }

}
  • XML

  • Java Config
@Configuration
public class Config {

    @Bean(initMethod = "init", destroyMethod = "close")
    public OneBean oneBean() {
        return new OneBean();
    }

    public static void main(String[] args) {
        //ClassPathXmlApplicationContext  和 AnnotationConfigApplicationContext 都 实现了 AutoCloseable 接口
        // 只有正常关闭Spring容器,才会调用Bean 的destroyMethod
        try (AnnotationConfigApplicationContext context =
                     new AnnotationConfigApplicationContext(Config.class)) {
            OneBean oneBean = context.getBean("oneBean", OneBean.class);
        }


    }
}
  • 实现Spring的 InitializingBean 和 DisposableBean 接口
@Component
public class SomeBean implements InitializingBean, DisposableBean {
    @Override
    public void destroy() throws Exception {
        System.out.println("close...");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("inti..");
    }
}
  • 使用J2EE规范注解 @PostConstruct 和 @PreDestroy
@Component
public class OtherBean {

    @PostConstruct
    public void close() throws Exception {
        System.out.println("close...");
    }

    @PreDestroy
    public void init() throws Exception {
        System.out.println("inti..");
    }
}

注意

  • 如果手动启动容器,必须要正常关闭spring容器,才能调用到destory-method。
  • 如果bean的scope是prototype,spring不会调用destory-method。

你可能感兴趣的:(Spring使用Java Config和XML装配Bean总结)