遨游Spring的世界(Spring之装配Bean三部曲)

2 篇文章 0 订阅
1 篇文章 0 订阅

如Spring名,对于一个java开发者来说,有了Spring就等于迎来了开发的春天一样。

一、spring简单介绍

正常来说每当我们学习了解一个新的技术之类的,都会去学习了解其背景,今天咱们就简单点吧。正式开始了啊:spring就是一个简化java开发的框架!(完)

二、spring装配bean的方案
	在Spring中将bean装配到容器有三种方案,去除混合搭配装备,?。
	```
	 1. XML显示配置
	 2. java代码中显示配置
	 3. 隐式配置和自动装配
	```
	下面分别来讲一下这三种装配方式。
三、XML装备Bean
  1. 创建我们的maven工程,此步骤就不用演示了吧。

  2. 添加我们的相关依赖包,你不要搞成Spring-boot的依赖了啊,现在讲的是最基础的spring,而SpringBoot是一个升级版本,使用我们的开发更加简洁,简洁到你或许用不到XML配置,?,我们还是先了解一下最简单的吧,先易后难嘛,在这里我才用的Spring版本是:

    
        <properties>
            <java.compiler.version>1.8</java.compiler.version>
            <spring.version>5.1.4.RELEASE</spring.version>
        </properties>
     <!-- Spring -->
                <dependency>
                    <groupId>org.springframework</groupId>
                    <artifactId>spring-core</artifactId>
                    <version>${spring.version}</version>
                </dependency>
                <dependency><!--这里用不到-->
                    <groupId>org.springframework</groupId>
                    <artifactId>spring-web</artifactId>
                    <version>${spring.version}</version>
                </dependency>
                <dependency>
                    <groupId>org.springframework</groupId>
                    <artifactId>spring-context</artifactId>
                    <version>${spring.version}</version>
                </dependency>
                <dependency>
                    <groupId>org.springframework</groupId>
                    <artifactId>spring-beans</artifactId>
                    <version>${spring.version}</version>
                </dependency>
                <dependency><!--这里用不到-->
                    <groupId>org.springframework</groupId>
                    <artifactId>spring-webmvc</artifactId>
                    <version>${spring.version}</version>
                </dependency>
                <dependency>
                    <groupId>org.springframework</groupId>
                    <artifactId>spring-jdbc</artifactId>
                    <version>${spring.version}</version>
                </dependency>
                <dependency>
                    <groupId>org.springframework</groupId>
                    <artifactId>spring-aspects</artifactId>
                    <version>${spring.version}</version>
                </dependency>
                <dependency>
                    <groupId>org.springframework</groupId>
                    <artifactId>spring-jms</artifactId>
                    <version>${spring.version}</version>
                </dependency>
                <dependency>
                    <groupId>org.springframework</groupId>
                    <artifactId>spring-context-support</artifactId>
                    <version>${spring.version}</version>
                </dependency>
    
  3. 我们项目简单的创建完毕后(包括依赖包名等),我们创建我们第一个简单Bean-User:

    public class User {
    
        private String name;
        private int age;
    
        public User() {
        }
    
        public User(String name, int age) {
            this.name = name;
            this.age = age;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    
        @Override
        public String toString() {
            return "User{" +
                    "name='" + name + '\'' +
                    ", age=" + age +
                    '}';
        }
    }
    
  4. 创建我们的配置文件applicaitonContext.xml,并在其中配置User

    <bean class="vip.zhuhailong.springother.pojo.User"/>
    

    这就是我们最简单的配置,这样我们的User就算是装配完毕了,但是问题又来了,我该这样在程序中从容器获取到这个bean呢,此时我们反转思考一下,假如是你编码了这个框架,你该如何来暴露出这个bean让消费者来调取呢,不错就是给个唯一的标示符Id,也就是说我们在配置bean时,需要配置bean的id,如果我们没有配置,那么spring将会默认将其全限定类名来做id,我们先来测试默认ID名:

        public static void main(String[] args) {
            ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");//创建spring应用上下文
            User user = applicationContext.getBean("vip.zhuhailong.springother.pojo.User", User.class);
            System.out.println(user);
        }
    

    运行结果为:User{name='null', age=0}
    从结果来看,获得的User中的属性都是默认的初始化值,并没有被我们初始化,下面我们来具体在XML配置初始化User,且不使用默认的ID,为其配置id,通常我们用其类名且第一个字母小些来作为id:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean class="vip.zhuhailong.springother.pojo.User" id="user">
        <constructor-arg name="name" value="User"/>
        <constructor-arg name="age" value="1"/>
    </bean>

    <!--<bean class="vip.zhuhailong.springother.pojo.User" id="user">-->
    <!--<property name="name" value="User"/>-->
    <!--<property name="age" value="1"/>-->
    <!--</bean>-->

    <!--<bean class="vip.zhuhailong.springother.pojo.User" id="user" init-method="init"/>-->

</beans>

上述的配置中,还添加了一些其他的xml初始化的配置方式,第一种是通过构造方法来配置属性值,第二种是通过直接配置属性值的方式来配置,第三种方式是指定初始化方法来初始化Bean,为此我们在User类中添加方法:

public void init() {
        setName("User");
        setAge(1);
    }

我们更改获取bean时的id为“user”:

public class OtherMain {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
        User user = applicationContext.getBean("user", User.class);
        System.out.println(user);
    }
}

测试结果为:User{name='User', age=1},这样我们的Bean就获取到相应的属性了。
有的童鞋肯定问了,在不同的服务场景中可能都会应用到User-bean,那么在不同场景中获取到的都是同一个Bean吗?我们注释掉User中重写的toString方法来测试一下:

public class OtherMain {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
        User user1 = applicationContext.getBean("user", User.class);
        User user2 = applicationContext.getBean("user", User.class);   
        System.out.println(user1);
        System.out.println(user2);
    }
}

运行结果:

vip.zhuhailong.springother.pojo.User@335eadca
vip.zhuhailong.springother.pojo.User@335eadca

从结果来看,两个User是同一个,在Spring中在装配bean时,在未指定scop时,默认使用的是单例,所以无论在那里获取User-bean,都会是同一个,现在我们需求是不需要单例,如下:

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean class="vip.zhuhailong.springother.pojo.User" id="user" scope="prototype">
        <constructor-arg name="name" value="User"/>
        <constructor-arg name="age" value="1"/>
    </bean>
    <!--<bean class="vip.zhuhailong.springother.pojo.User" id="user">-->
    <!--<property name="name" value="User"/>-->
    <!--<property name="age" value="1"/>-->
    <!--</bean>-->
    <!--<bean class="vip.zhuhailong.springother.pojo.User" id="user" init-method="init"/>-->
</beans>

测试结果为:

vip.zhuhailong.springother.pojo.User@18eed359
vip.zhuhailong.springother.pojo.User@3e9b1010

在指定scope为prototype时,每当获取User-bean时,spring都会为我们生成一个新的User-bean。

当然还可以为其配置List 、set等集合,或者是引入其他的bean来初始化需要配置的bean,由于主要讲述配置方式,不再详细述说。

四、java代码装配bean
  1. 创建BeanConfig类,并加上注解@Configuration来标示此类为配置类
  2. 创建生成对应bean的方法,并加上注解@bean,通常默认将java代码配置类中方法名作为对应bean的id,也可以在@bean中指定bean的id;
    @Configuration
    public class BeanConfig {
        @Bean
        public User user() {
            User user = new User();
            user.setName("User");
            user.setAge(1);
            return user;
        }
    }
    
    我们先不指定固定id测试:
    public class OtherMain {
        public static void main(String[] args) {
            AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(BeanConfig.class);
            User user = applicationContext.getBean("user", User.class);
            System.out.println(user);
        }
    }
    
    测试结果:User{name='User', age=1};若指定Id,配置类为:
    @Configuration
    public class BeanConfig {
        @Bean("specialUser")
        public User user() {
            User user = new User();
            user.setName("User");
            user.setAge(1);
            return user;
        }
    }
    
    测试类:
    public class OtherMain {
        public static void main(String[] args) {
            AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(BeanConfig.class);
            User user = applicationContext.getBean("specialUser", User.class);
            System.out.println(user);
        }
    }
    
    测试结果为:User{name='User', age=1},同XML配置一样我们同样可以配置Bean的scope,在为指定Bean的scope情况下,默认为单例,若要指定scope,则增加注解:@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)这样每次注入依赖User时都会生成新的User。
五、自动化装配bean
  1. 同样创建UserConfig类,加上@Configuration注解告诉Spring这是一个配置类,再加上@ComponentScan注解,在未指定扫描包时,Spring会在当前配置类所在的包及其子包中的扫描装备带有@Component注解的类;若指定扫描包如:@ComponentScan(basePackages = "path"),Spring将会扫描path包中和其子目录下带有@Component注解的类;当然spring还提供另一种方式来配置扫描的类路径,即:@ComponentScan(basePackageClasses = 类.class),这样Spring将会扫描指定类的路径和其子包路径下的带有@Component, @Repository, @Service, @Controller或者已经声明过@Component自定义注解标记的组件,当前@ComponentScan或者@ComponentScans还有很多其他的功能这里不在叙述来,配置类如下:

    @Configuration
    @Configuration
    @ComponentScan
    或者@ComponentScan(basePackages = "vip.zhuhailong.springother.pojo")
    或者@ComponentScan(basePackageClasses = BeanConfig.class)
    public class BeanConfig {
    }
    
    
  2. 在我们User类上增添@Component注解;为了更清晰显示我们的装配结果,我们对User通过注解进行初始化,我们可以在注解@Component中指定固定的id如:@Component("AutoConfigUserId");若不指定id,则会使用类名的第一个字母小些作为id;当然在我们未指定Scope的情况此Component组件为单例,要想指定Scope,同java代码配置一样,通过注解@scope来指定模式,此处不在演示,User配置如下:

    @Component
    public class User {
        @Value("ComponentUserName")
        private String name;
        @Value("100000000")
        private int age;
        public User() {
        }
        public User(String name, int age) {
            this.name = name;
            this.age = age;
        }
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public int getAge() {
            return age;
        }
        public void setAge(int age) {
            this.age = age;
        }
        @Override
        public String toString() {
            return "User{" +
                    "name='" + name + '\'' +
                    ", age=" + age +
                    '}';
        }
        public void init() {
            setName("User");
            setAge(1);
        }
    }
    
  3. 测试我们的自动装配方式:

    public class OtherMain {
        public static void main(String[] args) {
            AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(BeanConfig.class);
            User user = applicationContext.getBean("user", User.class);
            System.out.println(user);
        }
    }
    

    测试结果:User{name='ComponentUserName', age=100000000}

  4. 补充:我们也可以不编码BeanConfig来扫描@Component组件,可以通过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.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
    
        <context:component-scan base-package="vip.zhuhailong.springother"/>
    </beans>
    

    测试类为:

    public class OtherMain {
        public static void main(String[] args) {
            ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:*applicationContext*.xml");
            User user = applicationContext.getBean("user", User.class);
            System.out.println(user);
        }
    }
    

    运行结果为:User{name='ComponentUserName', age=100000000}

本篇介绍Spring装配Bean的三种方式就到此为止,下一篇我们将进一步详细介绍Spring装备中的一些互相依赖注入及一下复杂的装配属性。谢谢大家,如有不对的地方还请大家指出必有重谢!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值