Spring系列(二)Bean详解

一.Spring—Bean概述

Spring框架性质是属于容器性质的,容器中装什么对象就有什么功能,能帮其他框架管理对象.
Spring容器中的对象统称为Bean.
Bean体现了Spring如下特性

IOC控制反转:把控制对象生命周期的权利交给第三方(spring)管理 
DI依赖注入:把Java程序中的对象创建的权利由第三方(spring)管理 

二.Bean的创建

直接上代码,具体解释见代码注释
这里写图片描述
User.java

public class User {
    @Override
    public String toString() {
         String  str=super.toString()+"#username="+getUsername()+"#password="+getPassword();
        return str;
    }
    private String username;
    private String password;

    public User() {
        System.out.println("空参构造方法创建User");
    }

    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
    public void init(){
        System.out.println("初始化方法");
    }
    public void destroy(){
        System.out.println("销毁方法");
    }
}

beancreate.xml

<?xml version="1.0" encoding="UTF-8"?>
<!-- 必须导入约束文件 -->
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd ">

<!-- 将User对象交给spring容器管理 -->
<!-- Bean元素:使用该元素描述需要spring容器管理的对象 
 class属性:被管理对象的完整类名. 
 name属性:给被管理的对象起个名字.获得对象时根据该名称获得对象. 可以重复.可以使用特殊字符.
 id属性: 与name属性一模一样. 名称不可重复.不能使用特殊字符. 
 结论: 尽量使用name属性. -->
 <!-- 创建方式1:空参构造创建 -->
<bean name="userone" class="cjx.beanCreate.User" scope="singleton"></bean>
 <!-- 创建方式2:静态工厂创建  调用UserFactory的createUser方法创建名为user2的对象.放入容器-->
<bean name="usertwo" class="cjx.beanCreate.BeanFactory" factory-method="createUser1"></bean>
 <!-- 创建方式3:实例工厂创建  调用UserFactory对象的createUser2方法创建名为user3的对象.放入容器-->
<bean name="userthree"  factory-bean="UserFactory" factory-method="createUser2"></bean>
<bean name="UserFactory" class="cjx.beanCreate.BeanFactory" ></bean>
</beans>

beancreateone.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd ">
<!-- 创建方式1:空参构造创建 -->
<bean name="userone" class="cjx.beanCreate.User" scope="singleton" 
init-method="init" destroy-method="destroy"></bean>
</beans>

beancreatetwo.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd ">
<!-- 创建方式2:静态工厂创建  调用UserFactory的createUser方法创建名为user2的对象.放入容器-->
<bean name="usertwo" class="cjx.beanCreate.BeanFactory" factory-method="createUser1"></bean>
</beans>

beancreatethree.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd ">
<!-- 创建方式3:实例工厂创建  调用UserFactory对象的createUser2方法创建名为user3的对象.放入容器-->
<bean name="userthree"  factory-bean="UserFactory" factory-method="createUser2"></bean>
<bean name="UserFactory" class="cjx.beanCreate.BeanFactory" ></bean>
<!-- 导入其他spring配置文件 -->
<import resource="beancreatetwo.xml"/>
</beans>

BeanCreate.java

public class BeanCreate {//bean的创建
    /*spring有BeanFactory接口和ApplicationContext
     * BeanFactory接口:原始接口,功能单一,每次获得对象时才创建对象
     * ApplicationContext:每次容器启动时就会创建容器中配置的所有对象.并提供更多功能
     * web开发中,使用applicationContext. 在资源匮乏的环境可以使用BeanFactory.
     */

    //演示spring创建对象容器的方式  :/spring/src/cjx/bean/User.java
    //spring在创建时会把配置文件里的对象全部创建
    @Test
    //创建方式1:空参构造创建
    public  void getbean1(){
        //1 创建容器对象
        //丛类路径下加载配置文件:ClassPathXmlApplicationContext("/cjx/bean/bean.xml")
        //从硬盘绝对路径下加载配置文件:FileSystemXmlApplicationContext("d:/xxx/yyy/xxx")
        ApplicationContext ac = new ClassPathXmlApplicationContext("cjx/beanCreate/beancreate.xml");
        //2 向容器"要"user对象
        User u = (User) ac.getBean("userone");
        //3 打印user对象
        System.out.println(u);
    }
    @Test
    //创建方式2:静态工厂创建
    public void getbean2(){
        ApplicationContext  ac = new ClassPathXmlApplicationContext("cjx/beanCreate/beancreate.xml");
        User u = (User) ac.getBean("usertwo");
        System.out.println(u);
    }
    @Test
    //创建方式2:动态工厂创建
    public void getbean3(){
        ApplicationContext  ac = new ClassPathXmlApplicationContext("cjx/beanCreate/beancreate.xml");
        User u = (User) ac.getBean("userthree");
        System.out.println(u);
    }
}
/*scope属性:
 * singleton(默认值):单例对象.被标识为单例的对象在spring容器中只会存在一个实例
 * prototype:多例对象.被标识为多例的对象,每次再获得才会创建.每次创建都是新的对象.
 * 整合struts2时,ActionBean必须配置为多例的.(struts2每次请求都会创建新的action)
 * request:web环境下.对象与request生命周期一致.(不常用)
 * session:web环境下,对象与session生命周期一致.(不常用)
 */

BeanCreateOne.java

public class BeanCreateOne {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("/cjx/beanCreate/beancreateone.xml");
        User u = (User) ac.getBean("userone");
        User u1 = (User) ac.getBean("userone");
        User u2 = (User) ac.getBean("userone");
        User u3 = (User) ac.getBean("userone");
        System.out.println(u);
        System.out.println(u1==u);
        System.out.println(u1==u2);
        System.out.println(u3==u2);
        //测试初始化和销毁方法(需要在文件里配置,和类中提供方法)
        ac.close();//用实现类(里面有close方法)
    }   
}

BeanCreateTwo.java

public class BeanCreateTwo {
    public static void main(String[] args) {
        @SuppressWarnings("resource")
        ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("/cjx/beanCreate/beancreatetwo.xml");
        User u = (User) ac.getBean("usertwo");
        System.out.println(u);
    }
}

BeanCreateThree.java

public class BeanCreateThree {
    public static void main(String[] args) {
        @SuppressWarnings("resource")
        ClassPathXmlApplicationContext  ac = new ClassPathXmlApplicationContext("/cjx/beanCreate/beancreatethree.xml");
        User u = (User) ac.getBean("userthree");
        System.out.println(u);

    }
}

BeanFactory.java

public class BeanFactory {
    @Test
    public static User createUser1(){//静态工厂
        System.out.println("静态工厂创建User");
        return new User();
    }   
    @Test
    public  User createUser2(){//实例(动态)工厂
        System.out.println("实例(动态)工厂创建User");
        return new User();
    }
}

三.Bean的注入

直接上代码,具体解释见代码注释
这里写图片描述
User.java

public class User {
    private String username;
    private String password;
    private Car car;    
    @Override
    public String toString() {
        return "User [username=" + username + ", password=" + password + ", car=" + car + "]";
    }

    public User() {
        System.out.println("无参构造!");
    }

    public User(String username, String password, Car car) {
        System.out.println("有参构造!(String username, String password, Car car)");
        this.username = username;
        this.password = password;
        this.car = car;
    }
    public User( Car car,String username, String password) {
        System.out.println("有参构造!( Car car,String username, String password) ");
        this.username = username;
        this.password = password;
        this.car = car;
    }
    public User(Integer username, String password, Car car) {
        System.out.println("有参构造!(Integer username, String password, Car car)");
        this.username = username+"";
        this.password = password;
        this.car = car;
    }
    public Car getCar() {
        return car;
    }
    public void setCar(Car car) {
        this.car = car;
    }
    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
}

Car.java

public class Car {
    private String name;
    private Integer age;    
    @Override
    public String toString() {
        return "Car [name=" + name + ", age=" + age + "]";
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Integer getAge() {
        return age;
    }
    public void setAge(Integer age) {
        this.age = age;
    }
}

Collection.java

public class Collection {
    private Object[] arr;//数组类型注入
    private List list;//List/set类型注入
    private Map map;//map类型注入
    private Properties prop;//Properties类型注入    
    @Override
    public String toString() {
        return "Collection [arr=" + Arrays.toString(arr) + ", list=" + list + ", map=" + map + ", prop=" + prop + "]";
    }
    public Object[] getArr() {
        return arr;
    }
    public void setArr(Object[] arr) {
        this.arr = arr;
    }
    public List getList() {
        return list;
    }
    public void setList(List list) {
        this.list = list;
    }
    public Map getMap() {
        return map;
    }
    public void setMap(Map map) {
        this.map = map;
    }
    public Properties getProp() {
        return prop;
    }
    public void setProp(Properties prop) {
        this.prop = prop;
    }
}

beaninjection.xml

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

    <!-- set方式注入: -->
    <bean name="user1" class="cjx.beanInjection.User">
        <!-- 值类型注入:为User对象注入值 -->
        <property name="username" value="tom"></property>
        <property name="password" value="123"></property>
        <!-- 引用类型注入:为User对象注入下方的car对象 -->
        <property name="car" ref="car"></property>
    </bean>
    <!-- 将car对象配置到容器中 -->
    <bean name="car" class="cjx.beanInjection.Car">
        <property name="name" value="兰博基尼"></property>
        <property name="age" value="11"></property>
    </bean>


    <!-- 构造函数注入:name="username" index="0" -->
    <bean name="user2" class="cjx.beanInjection.User">
        <constructor-arg name="username" value="jerry" index="0"></constructor-arg>
        <constructor-arg name="password" value="456"></constructor-arg>
        <constructor-arg name="car" ref="car"></constructor-arg>
    </bean>
    <!-- 构造函数注入:name="username" index="1" -->
    <bean name="user3" class="cjx.beanInjection.User">
        <constructor-arg name="username" value="jerry" index="1"></constructor-arg>
        <constructor-arg name="password" value="789"></constructor-arg>
        <constructor-arg name="car" ref="car"></constructor-arg>
    </bean>
    <!-- 构造函数注入:name="username" index="0" type="java.lang.Integer" -->
    <!-- 构造函数注入 name:构造函数的参数名 index:构造函数的参数索引 type:构造函数的参数类型 -->
    <bean name="user4" class="cjx.beanInjection.User">
        <constructor-arg name="username" value="123456789"
            index="0" type="java.lang.Integer"></constructor-arg>
        <constructor-arg name="password" value="789"></constructor-arg>
        <constructor-arg name="car" ref="car"></constructor-arg>
    </bean>


    <!-- p名称空间注入 首先要导入约束xmlns:p="http://www.springframework.org/schema/p" -->
    <bean name="user5" class="cjx.beanInjection.User" p:username="jack"
        p:password="963" p:car-ref="car"></bean>


    <!-- spel注入:spring expression language :spring表达式语言 不支持引用类型,只用于值类型。取其他对象的值。 -->
    <bean name="user6" class="cjx.beanInjection.User">
        <property name="username" value="#{user5.username}"></property>
        <property name="password" value="#{user4.password}"></property>
        <property name="car" ref="car"></property>
    </bean>


    <!-- 复杂类型注入 -->
    <bean name="collection" class="cjx.beanInjection.Collection">
        <!-- array注入 -->
        <!-- 如果数组中只注入一个值,直接使用value或ref <property name="arr" value="tomcat"></property> -->
        <!-- array注入:多元素 -->
        <property name="arr">
            <array>
                <value>tom</value>
                <value>jake</value>
                <ref bean="user6" />
            </array>
        </property>
        <!-- list注入:如果只注入一个值,直接使用value或ref -->
        <property name="list">
            <list>
                <value>rose</value>
                <value>taomcat</value>
                <ref bean="user3" />
            </list>
        </property>
        <!-- map注入 -->
        <property name="map">
            <map>
                <entry key="url" value="www.baidu.com"></entry>
                <entry key="car" value-ref="car"></entry>
                <entry key-ref="user1" value-ref="user2"></entry>
            </map>
        </property>
        <!-- Properties注入 -->
        <property name="prop">
            <props>
                <prop key="driverclass">com.jdbc.mysql.driver</prop>
                <prop key="username">cjx</prop>
                <prop key="password">123</prop>
            </props>
        </property>
    </bean>
</beans>

BeanInjection.java

public class BeanInjection {//bean的注入   
    @Test
    public  void getbean1(){
        ApplicationContext ac = new ClassPathXmlApplicationContext("cjx/beanInjection/beaninjection.xml");
        User u = (User) ac.getBean("user6");
        System.out.println(u);
    }   
    @Test
    public  void getbean2(){
        ApplicationContext ac = new ClassPathXmlApplicationContext("cjx/beanInjection/beaninjection.xml");
        Collection c =  (Collection) ac.getBean("collection");
        System.out.println(c);
        }
}

四.Bean的注解

直接上代码,具体解释见代码注释
这里写图片描述
User.java

//import org.springframework.stereotype.Controller;
//import org.springframework.stereotype.Repository;
//import org.springframework.stereotype.Service;

@Component("user")// 标记为组件,并设置名称为user,放在类前
//          @Service("user")// Service层注解
//          @Controller("user")//Web层注解
//          @Repository("user")//Dao层注解
//上面四个注解的功能相同,为了区分不同层的对象,提供了下面三个注解
@Scope(scopeName="singleton")//指定对象的作用域,默认是单例(singleton),可以设置为多例(prototype)
public class User {// 使用注解代替xml配置
    @Value("tom")// 赋值,放在属性前,通过反射赋值,不走set方法,破坏了对象的封装性。
    private String username;
    private String password;
//  @Autowired//根据类型自动装配,对象属性赋值,但如果匹配到多个类型一致的对象,将无法选择
//  @Qualifier("car")//根据名称自动装配,对象属性赋值
//上面两个注解要一起使用,或只用第一个
    @Resource(name="car")//手动注入,指定对象名称
    private Car car;

    @Value("123456789")// 赋值,放在set方法前,通过set方法赋值,推荐使用
    public void setPassword(String password) {
        System.out.println("setPassword");
        this.password = password;
    }

    @PostConstruct//在对象创建后被调用,相当于init-method
    public void init(){
        System.out.println("初始化方法!");
    }
    @PreDestroy//在对象销毁之前被调用,相当于destory-method
    public void destory(){
        System.out.println("销毁方法!");
    }

    @Override
    public String toString() {
        return "User [username=" + username + ", password=" + password + ", car=" + car + "]";
    }

    public String getPassword() {
        return password;
    }

    public Car getCar() {
        return car;
    }
    public void setCar(Car car) {
        this.car = car;
    }
    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        System.out.println("setUsername");
        this.username = username;
    }
}

Car.java

@Component("car")
public class Car {
    @Value("兰博基尼")
    private String name;
    @Value("66")
    private Integer age;    
    @Override
    public String toString() {
        return "Car [name=" + name + ", age=" + age + "]";
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Integer getAge() {
        return age;
    }
    public void setAge(Integer age) {
        this.age = age;
    }
}

beanAnnotate.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd ">
<!-- 使用注解代替xml配置
在/spring/src/cjx/beanCreate/beancreate.xml基础上
导入约束
···\spring-framework-4.2.4.RELEASE\schema\context\spring-context-4.2.xsd
 -->
 <!-- 导包:spring-aop-4.2.4.RELEASE.jar -->
<!-- 组件自动扫描:指定扫描指定包下所有类的注解,包括子包。 -->
<context:component-scan base-package="cjx.beanAnnotate"></context:component-scan>
</beans>

BeanAnnotateTest.java

//spring整合Junit的测试功能
//导包spring-test-4.2.4.RELEASE.jar
//创建容器
@RunWith(SpringJUnit4ClassRunner.class)
//指定配置文件,路径前面要加classpath:
@ContextConfiguration("classpath:cjx/beanAnnotate/beanAnnotate.xml")
public class BeanAnnotateTest {
    //将user对象注入到u变量
    @Resource(name="user")
    private User u; 
    @Test
    public void getbean(){
    System.out.println(u);
    }

}

BeanAnnotate.java

public class BeanAnnotate {
    @Test
    public  void getbean() {
        ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("cjx/beanAnnotate/beanAnnotate.xml");
        User u = (User) ac.getBean("user");
        System.out.println(u);
        ac.close();
    }
}

猜你喜欢

转载自blog.csdn.net/bestmy/article/details/81069446
今日推荐