spring框架学习 Bean

自学spring真的需要自己多手动敲代码,了解弯弯绕绕的bean实例化的个中过程,去理解无参构造,静态工厂构造,实例工厂构造的区别,实现方法,理解bean的作用域,生命周期。


Bean对象的实例化需要spring帮我们实现,借助的中间媒介就是xml核心配置文件,其中的bean标签是bean对象实例化最重要的部分,来分析一下bean标签最基本的几个属性:


1、id:就是你随便规定的一个名称,在但是这个名称在你IOC容器实例化启用ApplicationContext接口定义客户端利用getBean(“id”)方法实例化bean的时候一定要注意里面的内容与你在xml文件里定义的对应bean标签id一致,我就出现过这样的错误导致报出未识别的错误。


2、class:顾名思义,class类,它的值是你需要借助它去实例化bean的一个java类的全限定名,个人理解就是目录里与xml文件对应的相对路径,这个java类可以是无参构造的原生类,也可以是作为中间商的静态或者实例工厂类。这个class的值可能有一些变化,有时候也可以不写这个属性,后面测试代码会给出来参考。


3、scope:作为比较受关注的属性,scope的两个值prototype与singleton的区别就很重要了,首先说当scope=“prototype”时实例化出来的对象的特点,定义这个值的时候每一次getBean之后(这里比较有特点,就是说scope等于prototype的时候,容器实例化之后对象并没有创建,而是在给出接收实例的接口,并运行getBea方法之后才能得到bean的实例化对象,属于半自动化了,我写多少条含接口含getBean代码就会产生多少个对象)得到的对象并不是同一个对象,也就是说它每次都会创建新对象,销毁的机制就有些像java一些自定义类的回收机制了,长时间不用会自动回收的。其次当scope=“singleton”的时候,实例化出来的对象都是同一个对象,无论你写多少行getBean代码,对象都是一个单例对象。有意思的是这种方式下创建对象的时间和spring容器实例化的时间一致,就是说我已经做好了橙汁,只需要你拿个接口杯子来装就行,全自动化。回收机制当然是与spring容器共存亡了。


4、还有其他的bean标签内部属性,会在代码里提到。


5、测试无参构造实例化bean以及bean标签内部属性scope取值不同的影响:

  • UserDao.java
  • package com.hlc.dao;
    //这里采用的无参构造去构造bean
    public class UserDao implements UserDaoImpl{
    //    这里的无参构造也可以尝试用来测试xml文件中bean属性scope等于不同值的作用,原理是容器构造一个对象时无参构造方法就会执行一次。
        public UserDao(){
            System.out.println("UserDao was created.....");
        }
    //    写一个初始化方法供xml文件帮助我使用,在bean里添加之后会在对象创建后初始化时调用它
        public void init(){
            System.out.println("init.....");
        }
    //    再加一个销毁的方法,会在bean销毁时使用到它,但可能销毁速度过快bean还没有反应过来调用它就会被销毁,所以这里需要注意在测试时用close();方法把app客户端关闭掉,当它关闭的时候bean会默认即将被销毁从而有时间调用它。
        public void destroy(){
            System.out.println("destroy.....");
        }
        @Override
        public void up() {
            System.out.println("up.......");
        }
    
        @Override
        public void shut() {
            System.out.println("shut down.....");
        }
    
        @Override
        public void inter() {
            System.out.println("inter.....");
        }
    }
    
  • UserDaoImpl
  • package com.hlc.dao;
    
    public interface UserDaoImpl {
        void up();
        void shut();
        void inter();
    }
  • config-application.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"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <!--利用bean去设定一个全限定名指向对应的类-->
    <!--    测试scope=“prototype”的作用-->
    <!--    <bean id="userdao" class="com.hlc.dao.UserDao" scope="prototype"></bean>-->
    <!--    通过classname.equals(class1name)套接if条件语句的方法测试到:scope等于singleton时创建的是同一实例对象,而prototype则创建的是不同对象
    关于这个测试,也可以回看UserDaoTest类里的无参构造测试。-->
    <!--    这里的init-method与destroy-method其实就是指定好bean能活多久的方法,指定的值应该在UserDao类里写好-->
        <bean id="userdao" class="com.hlc.dao.UserDao"  init-method="init" destroy-method="destroy"></bean>
    
    </beans>
  • UserDaoTest.java
  • import com.hlc.dao.UserDaoImpl;
    import org.junit.Test;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class UserDaoTest {
    //    测试注解,需要在pom文件导入java单元测试框架junit的依赖项。
        @Test
        public void test1() {
    
    //        这里的app相当于spring的一个容器访问客户端,用接口ApplicationContext定义,我们将会利用它去获取bean对象,当xml文件中的bean指定类的scope值为singleton时,一旦app被创建,也就是容器一实现,对象就已经被创建了,只是还没有利用getBean()方法让接口接收。由于我在UserDao类添加了无参构造方法,所以只执行这一步代码会输出单句UserDao was created....证明对象创建,同理当容器销毁时这个对象才会被销毁,它与容器共存亡。。但是当xml文件中的bean指定的类的scope值为prototype时,就算app创建,对象也只会在利用getBean()方法让接口接收时创建对象。这就导致了它创建多对象特性的形成。自然的这样模式下创建对象的生命会跟随bean一样,当长期不使用的时候就会被GC机制回收。一般spring项目会采用scope=“singleton”。
    //        ApplicationContext app = new ClassPathXmlApplicationContext("config-application.xml");
    
    
            ClassPathXmlApplicationContext app = new ClassPathXmlApplicationContext("config-application.xml");
    //       接口接收。
            UserDaoImpl user = (UserDaoImpl) app.getBean("userdao");
    //      UserDaoImpl user1 = (UserDaoImpl) app.getBean("userdao");
    
    //       这是测试方法调用,感觉没啥意义。
    //       user.up();
    //       user.inter();
    //       user.shut();
    
    //        下面是测试bean的scope值的作用代码,验证创建的是单例对象还是多例对象。下面要测试bean的生命周期所以把测试这个的先注掉啦!
    //       if (user.equals(user1)) {
    //            System.out.println("user = user1");
    //        } else System.out.println("user != user1");
    
    //        注意这行代码ApplicationContext app = new ClassPathXmlApplicationContext("config-application.xml");
    //        其中ApplicationContext是spring中最重要的两个接口中的一个,而后面的ClassApplicationContext是具体实现的上层应用类
    //        功能比它多,比如这个close()方法ApplicationContext接口就没有配备,所以要想使用close();方法需要用这个类去接收。
    //        需要将app的类型改动一下才能实现close()。改动后的代码如上述。
            app.close();
    //       补充: 结果显示bean销毁之前将UserDao类中的destroy()方法调用了。
        }
    }
    


6、测试静态工厂实例化bean

  • staticFactory.java
  • package com.hlc.factory;
    
    import com.hlc.dao.UserDao;
    import com.hlc.dao.UserDaoImpl;
    
    //主要测试静态工厂构造bean
    public class staticFactory {
        public static UserDaoImpl getUserDaoImpl(){
    //        返回时new一个新的UserDao对象实现静态工厂的构造。
            return new UserDao();
        }
    }
  • staticFactorytest.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"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <!--      为了区别于无参构造的测试,我违背了常理的测试结构,又建立了一个xml文件,在测试时更改ClassPathXmlApplicationContext("")中的xml文件名即可
    这里我们利用静态工厂类去制造bean实例对象,factory-method的值是写好的静态方法,返回的是new出的一个新对象UserDao-->
            <bean id="userdao" class="com.hlc.factory.staticFactory" factory-method="getUserDaoImpl"></bean>
    </beans>
  • staticFactoryTest.java
  • import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class staticFactoryTest {
        @Test
        public void Test(){
    //        此例子主要在测试静态工厂构造,个人理解原理就是将工厂作为UserDao与Xml之间的中间商,工厂提取UserDaoImpl中的类特性,
    //        接到app客户端口getBean()生产对象userdao的指令之后会按照类UserDao给出的图纸去制造,感觉这样子的商业模式
    //        会起到一定的解耦作用。
            ApplicationContext app = new ClassPathXmlApplicationContext("staticFactorytest.xml");
            UserDaoImpl user = (UserDaoImpl) app.getBean("userdao");
            System.out.println(user);
        }
    }

7、测试实例工厂实例化bean

  • DynamicFactory.java
  • package com.hlc.factory;
    
    import com.hlc.dao.UserDao;
    import com.hlc.dao.UserDaoImpl;
    
    //此例采用实例工厂去实现bean的实例化
    public class DynamicFactory {
        public  UserDaoImpl getUserDaoImpl(){
    //        返回时new一个新的UserDao对象实现静态工厂的构造。
            return new UserDao();
        }
    }
  • DynamicFactory.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"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <!--这里需要注意这个是静态工厂与实例工厂的使用区别,实例工厂需要先将工厂实例化,再去访问工厂的bean实例调用方法去制造UserDao的bean实例-->
        <bean id="factory" class="com.hlc.factory.DynamicFactory"></bean>
        <bean id="userdao" factory-bean="factory" factory-method="getUserDaoImpl"></bean>
    </beans>
  • DynamicFactoryTest.java
  • import com.hlc.dao.UserDaoImpl;
    import org.junit.Test;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class DynamicFactoryTest {
        @Test
        public  void Test(){
    //        测试结果的代码真的就一样。
            ApplicationContext app = new ClassPathXmlApplicationContext("DynamicFactory.xml");
            UserDaoImpl user = (UserDaoImpl) app.getBean("userdao");
            System.out.println(user);
        }
    }

8、基于5去建立service层实现假web页面的功能

  • UserService
  • package com.hlc.service;
    
    public interface UserService {
        void shut();
    }
    
  • UserServiceImpl.java
  • import com.hlc.dao.UserDaoImpl;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    //测试搭建service层帮我们去完成业务,这里采用spring帮我们完成,其实这个service作用就相当于相当于一个假的web页面。
    public class UserServiceImpl implements UserService{
        @Override
        public void shut() {
            ApplicationContext app = new ClassPathXmlApplicationContext("DynamicFactory.xml");
            UserDaoImpl user = (UserDaoImpl) app.getBean("userdao");
            user.shut();
        }
    }
  • UserServiceTest.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"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean id="service" class="com.hlc.service.UserServiceImpl"></bean>
    </beans>
  • UserServiceTest.java
  • import com.hlc.service.UserService;
    import org.junit.Test;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class UserServiceTest {
        @Test
        public void Test(){
            ApplicationContext a = new ClassPathXmlApplicationContext("UserServiceTest.xml");
            UserService service = (UserService) a.getBean("service");
            service.shut();
        }
    }
    

9、总的pom.xml文件如下:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>Spring</artifactId>
    <version>1.0-SNAPSHOT</version>
    <dependencies>
<!--        这里导入spring坐标-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.3.15</version>
        </dependency>
<!--        这里导入的java单元测试框架的依赖-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13.2</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

10、测试练习的项目目录如下:

 

11、其实真的很水,卡了三天的进度,坚持日更吧只能.......

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ForestSpringH

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值