DI入门案例&Bean入门

文章详细介绍了Spring中的依赖注入(DI)入门案例,包括Bean的基础配置,如别名和作用范围。讨论了Bean的实例化方法,如静态工厂和FactoryBean。此外,还讲解了Bean的生命周期,包括初始化方法、销毁方法以及如何配置和调用这些方法。文章最后提到了两种销毁Bean的方式和它们的区别。
摘要由CSDN通过智能技术生成

Spring学习记录:

DI入门案例:

  1. 基于IoC管理bean
  2. service中使用new创建的Dao对象是否可以保留(否)
  3. service中需要Dao对象该如何添加到service中(提供方法)
  4. Service与Dao之间的关系如何描述(配置文件)

applicationContext.xml:

<bean id="bookDao" class="org.wgq.dao.impl.BookDaoImpl"/>
<!--        Dao传入到Service 所以需要在Service中配置-->
        <bean id="bookService" class="org.wgq.service.impl.BookServiceImpl">
<!--                配置Serviece与Dao的关系-->
<!--                name中的bookDao是BookServiceImpl中的私有对象 ref中指的当前容器中为bookDao的bean-->
<!--                property标签表示配置属性-->
<!--                name属性表示配置哪一个的具体属性-->
<!--                ref属性表示参照哪一个bean-->
                <property name="bookDao" ref="bookDao"/>
        </bean>
public class BookServiceImpl implements BookService{

    //删除业务层中使用new创建的对象
	//    private BookDao bookDao=new BookDaoImpl();
    private BookDao bookDao;
    @Override
    public void Save() {
        System.out.println("BookService Save");
        bookDao.Save();//调用BookDao中的Save();
    }
    //提供对应的set方法
    public void setBookDao(BookDao bookDao) {
        this.bookDao = bookDao;
    }
}

最主要的目的降低耦合度

Bean配置:

bean基础配置:

image-20230207201637873

Bean别名:

image-20230207201724596

使用name 可以设置多个名称,使用别名的话那么在拿到bean对象时便可以使用别名。

image-20230207201937060

可以使用逗号(,)分号(;)空格( )分隔。

也可以使用别名定义reference:

image-20230207202159148

bean的作用范围:
public class AppForScope
{
    public static void main( String[] args )
    {
        ApplicationContext context=new ClassPathXmlApplicationContext("applicatinContext.xml");
        BookDao bookDao =(BookDao)context.getBean("bookDao");
        System.out.println(bookDao);
        BookDao bookDao1 =(BookDao)context.getBean("bookDao");
        System.out.println(bookDao1);
    }
}

image-20230207203331337

显然地址时一致的,所以可以得出Spring为我们创建bean时是单例模式。

若要创建非单例怎么做?(修改配置)

image-20230207203602594

使用Scope属性,prototype(非单例模式)singleton(单例模式)。

image-20230207203730522

为什么bean默认为单例模式?

**答:**Spring管理我们的对象时为了提高效率,同时为服务器减压采用单例(若需要调用Dao中的一次方法便创建一个Bean则Bean会无穷无尽)。

image-20230207204223488

那么Bean的控制范围实际上是Spring为了控制创建Bean的数量。

Bean的实例化:

什么是Bean,bean是如何创建出来的:

bean本质上就是对象,创建bean使用无参构造方法完成常用

<!--    方式1构造方法实例化bean-->
        <bean id="bookDao"  class="org.wgq.dao.impl.BookDaoImpl" scope="singleton"/>

image-20230207210243664

image-20230207210321408

Bean的三种实例化方式:

image-20230207210544374

通过静态工厂创建(早期常用方法):

造对象不要自己new,而是使用工厂,达到一定程度的解耦。

<!--        方式2 使用静态工厂创建bean-->
        <bean id="orderDao" class="org.wgq.factory.OrderDaoFactory" factory-method="getOrderDao"/>
<!-- factory-method 属性表示调用工厂中的某一实例化bean的方法-->
package org.wgq;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.wgq.factory.OrderDaoFactory;

public class AppForInstanceOrder {
    public static void main(String[] args) {
//        OrderDao   orderDao=OrderDaoFactory.getOrderDao();
//        orderDao.Save();
        ApplicationContext context=new ClassPathXmlApplicationContext("applicatinContext.xml");
        OrderDao orderDao = (OrderDao) context.getBean("orderDao");
        orderDao.Save();
    }
}

image-20230207213441469

image-20230207212039415

  1. package org.wgq.dao.impl;
    
    import org.wgq.OrderDao;
    
    public class OrderDaoImpl implements OrderDao {
    
        @Override
        public void Save() {
            System.out.println("OrderDao Save() Is Running!!!");
        }
    }
    
  2. package org.wgq.factory;
    
    import org.wgq.OrderDao;
    import org.wgq.dao.impl.OrderDaoImpl;
    
    public class OrderDaoFactory {
       public static OrderDao getOrderDao(){
            return new OrderDaoImpl();
       }
    }
    
  3. package org.wgq;
    
    public interface OrderDao {
        void Save();
    }
    
    

    实例工厂实例化Bean:

    image-20230207214408927

与静态的区别在于工厂的get方法没有static。

package org.wgq.factory;

import org.wgq.UserDao;
import org.wgq.dao.impl.UserDaoImpl;

public class UserDaoFactory {
    public UserDao getUserDao(){
        return new UserDaoImpl();
    }
}
package org.wgq;

import org.wgq.factory.UserDaoFactory;

public class AppForInstanceUser {
    public static void main(String[] args) {
        //需要先通过工厂的实例对象调用get方法,返回给userDao
        //不可以直接通过工厂完成实例化
        UserDaoFactory  userDaoFactory =new UserDaoFactory();
        UserDao userDao=userDaoFactory.getUserDao();
        //工厂返回后,再调用user实现类中的方法
        userDao.Save();
    }
}
<!--    1. 先造工厂Bean-->
            <bean id="userFactory" class="org.wgq.factory.UserDaoFactory"/>
<!--    2. 使用工厂Bean对象创建user-->
            <bean id="userDao" factory-method="getUserDao" factory-bean="userFactory"/>
package org.wgq;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.wgq.factory.UserDaoFactory;

public class AppForInstanceUser {
    public static void main(String[] args) {
//        UserDaoFactory  userDaoFactory =new UserDaoFactory();
//        UserDao userDao=userDaoFactory.getUserDao();
//        userDao.Save();
        ApplicationContext ctx =new ClassPathXmlApplicationContext("applicationContext.xml");
        UserDao userDao = (UserDao) ctx.getBean("userDao");
        userDao.Save();
    }
}

image-20230207220245798

image-20230207220333672

FactoryBean(掌握):

image-20230207221843086

image-20230207221911342

image-20230207221939113

class定义对象的具体属性。通过FactoryBean完成对象实例化。

image-20230207222828590

在FactoryBean中添加方法,返回为true则为单例(默认不加方法也为单例)

false为非单例。

Bean的生命周期:

主调用方法:

package org.wgq;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class AppforLifecycle {
    public static void main(String[] args) {
        ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml");
        BookDao bookDao = (BookDao) ctx.getBean("bookDao");
        bookDao.Save();
    }
}

BookDao实现类:

package org.wgq.dao.impl;

import org.wgq.BookDao;

public class BookDaoImpl implements BookDao {
//    public BookDaoImpl() {
//        System.out.println("BookDao constructor is running===");
//    }

    public void Save(){
        System.out.println("BookDao Save");

    }
    //初始化Bean
    public void init(){
        System.out.println("init bean...");
    }
    //销毁bean
    public void destroy(){
        System.out.println("destroy bean...");
    }
}

运行结果:

image-20230209130746443

初始化方法即销毁方法均未调用。为什么呢?是因为我们并未在配置文件中进行配置。

配置:

<bean id="bookDao"  class="org.wgq.dao.impl.BookDaoImpl" scope="singleton" init-method="init" destroy-method="destroy"/>
<!-- init-method 初始化方法 destrot-method 销毁方法-->

运行结果:

image-20230209131342017

我们发现初始化方法已经调用了,那销毁方法呢?

解答:是因为我们的程序目前跑在java虚拟机中,Vm拿到IoC容器后并初始化bean,然后获取对象,再调用Save()方法,那么程序结束,虚拟机直接退并没有给机会使其销毁Bean。

所以需要以下方法销毁

两种方式销毁Bean:

调用Close()方法:

image-20230209132416510

我们会发现它并没有close的方法可以调用。我们需要换一个接口。

image-20230209132654381

image-20230209132722149

这样close方法就有了。

运行结果:

image-20230209132758164

关闭注册钩子:

意思是在虚拟机关闭前,先关闭我的容器

image-20230209133110958

任何位置都可,即也可以放在Save()前后都行。

运行结果:

image-20230209133135499

两者的区别:

Close相比之下更加暴力,且close的执行时间必须在容器执行完需要做的事情后才能关闭容器。

若Close在获取对象之前等,如下:

image-20230209133707982

image-20230209133719413

则会报错!

使用Spring接口关闭:
继承接口:

image-20230209134617937

生成方法:

image-20230209134646146

配置文件:

image-20230209134713522

去掉我们自己实现的方法。

运行结果:

image-20230209134756754

afterPeopertiesSet()表示在属性设置完后再初始化。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值