【Spring】分别基于XML、注解和配置类实现Spring的IOC(控制反转)

目录

1、理解loC是什么

2、基于XML实现Spring的IOC(这种方式已经不怎么使用了)

3、基于注解实现Spring的IOC

4、基于javaConfig实现Spring的IOC

5、总结

1、理解loC是什么

lOC:lnversion of Control 控制反转,简称就是 IOC

控制反转:控制(对象创建权利)被反转

        控制反转通过依赖注入(DI)方式实现对象之间的松耦合关系。程序运行时,依赖对象由辅助程序动态生成并注入到被依赖对象中,动态绑定两者的使用关系。Spring IoC 容器就是这样的辅助程序,它负责对象的生成和依赖的注入,然后再交由我们使用。

        依赖注入(DI)Dependency Injection,它是 spring 框架核心 ioc 的具体实现。其作用是去除Java类之间的依赖关系,实现松耦合,以便于开发测试。

假设我现在有两个java类,UserService 和 UserDao,然后 UserService 中有依赖 UserDao,这时候创建 UserService 有如下两种情况:

用IOC之前:由程序员控制创建对象

        自己创建对象:UserService(new UserDao())---->UserDao;这种方式具有强耦合,再小的代码变更都会引起BUG的可能性

        比如在UserService类中要用到UserDao类,就需要在UserService类中创建UserDao类的对象,这就会造成类之间的强耦合。写代码的耦合度越高,对后期的维护就越不利,比如说以后要把UserDao类给换掉的话,就必须来到UserService类中把UserDao类的对象代码给换掉,如果有几十处,就要改几十处,但是再小的代码变更都会引起BUG的可能性

用IOC之后:创建对象依赖Spring注入(DI)

        Spring(new UserService(); new UserDao();) 由Spring来创建UserService类和UserDao类的对象,如果UserService中要用到UserDao就让Spring把UserDao注入进来

        如果需要用到Spring管理的对象,需要依赖Spring注入(DI)

        loC/DI优点:解耦,管理好对象的创建和依赖,总的来说就是统一管理对象。某一个对象只会创建一次,可以节省内存的开支,这属于设计模式当中的一种,设计模式有23种,这种属于单例设计模式,Sprig的管理对象就用到了这个单例设计模式,但是我们自己也可以把他改成每一次用到都给他创建一次

 没有引入Spring降低耦合度的方式:

        这种方式就是,创建一个接口,通过把将来可能要换的类去实现这个接口,使用时都是用这个接口的实现类,当需要把这个实现类换掉的时候,就只需要再创建这个接口的实现类,然后把之前的那个实现类换成这个新创建的实现类就可以了

示例:

//定义接口
public interface IUserDao {
    //执行查询用户
    void getUser();
}

//实现IUserDao接口的类,这个类在UserService中需要用到
public class UserDao implements IUserDao{
    @Override
    //执行查询用户
    public void getUser() {
        System.out.println("Holle Spring");
    }
}

//UserService中需要用到UserDao,但是要降低和UserDao之间的耦合度
public class UserService {
    //用IUserDao来接收UserDao的实现类
    //这样当以后要把UserDao换成其他实现了IUserDao的类
    //就只需要把实现类(也就是现在UserDao的位置)改成要换的那个IUserDao实现类就可以了
    IUserDao userDao = new UserDao();
    //比如要换成User2Dao,只需要改成:IUserDao userDao = new User2Dao();就可以了
    public void getUser() {
        userDao.getUser();
    }
}

这种方式确实能够降低耦合度,但还是需要修改代码,而通过Spring的loC/Dl就可以实现不需要修改代码来降低耦合度

bean:在 Spring 中,构成应用程序主干并由 Spring IoC 容器管理的对象称为 bean。bean 是由Spring IoC 容器实例化、组装和管理的对象。 

2、基于XML实现Spring的IOC(这种方式已经不怎么使用了)

        通过在 xml 文件中用 <bean class=""> 这个标签的方式来进行显式的声明要配置成bean的类,生成 applicationContext.xml 文件步骤,但是要在pom.xml文件中引入spring-context依赖才会出现生成 applicationContext.xml 文件这一选项

bean 标签:在 Spring 的 XML 配置文件中配置一个 bean 标签,该标签最终会被加载为一个 BeanDefition 对象(描述对象信息),这个标签里面就用来描述要配置成bean的那个类的信息,这个标签里面像 ref、name 这些属性如果感兴趣的话可以去查阅一下,因为这种方式不怎么用了,所以这里就演示一下大概的流程

//pom.xml文件中需要引入的依赖
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>6.1.2</version>
</dependency>


//applicationContext.xml 文件配置
//在我的项目中,我把applicationContext.xml文件命名为spring.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">

    <!--让Spring帮我们去new对象,对象之间的依赖也让spring帮我们进行组织-->
    <bean class="com.lt.service.UserService">
        <!--进行注入-->
        <property name="userDao" ref="userDao"></property>
    </bean>

    <bean class="com.lt.dao.UserDao" name="userDao"></bean>
    <bean class="com.lt.dao.User2Dao" name="user2Dao"></bean>
</beans>


//创建接口IUserDao
public interface IUserDao {
    //执行查询用户
    void getUser();
}


//接口IUserDao的实现类UserDao
public class UserDao implements IUserDao{
    @Override
    //执行查询用户
    public void getUser() {
        System.out.println("Holle Spring");
    }
}


//接口IUserDao的实现类User2Dao
public class User2Dao implements IUserDao{
    @Override
    //执行查询用户
    public void getUser() {
        System.out.println("Holle Spring 222");
    }
}


//创建接口IUserService
public interface IUserService {
    void getUser();
}


//接口IUserService的实现类UserService
//因为这种方式是基于get和set属性来进行注入的,所以要把UserService类的get和set方法声明一下
public class UserService implements IUserService{
    //耦合度过高 依赖spring注入(DI)
    IUserDao userDao;

    public IUserDao getUserDao() {
        return userDao;
    }

    public void setUserDao(IUserDao userDao) {
        this.userDao = userDao;
    }

    @Override
    public void getUser() {
        userDao.getUser();
    }
}

//测试类
public class Test01 {
    @Test
    public void test(){
        //UserService userService = new UserService();
        //如果是自己new一个UserService,Spring是不会为这个自己new的UserService注入userDao的
        //要依赖spring注入,就需要从spring容器中获取UserService
        ClassPathXmlApplicationContext ico = new ClassPathXmlApplicationContext("spring.xml");
        IUserService service = ico.getBean(IUserService.class);
        service.getUser();
    }
}

注入UserDao时的运行结果 

注入User2Dao时的运行结果

 

3、基于注解实现Spring的IOC

通过 @component注解也可以将一个类声明为 Bean通过这种方式就不需要再在applicationContext.xml文件来进行复杂的添加每一个需要被配置成bean的类了

//applicationContext.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 https://www.springframework.org/schema/context/spring-context.xsd">

<!--告诉spring注解所在的包在哪,在com.lt包下面的包-->
<context:component-scan base-package="com.lt"></context:component-scan>

</beans>



//IUserDao是一个接口
public interface IUserDao {
    //执行查询用户
    void getUser();
}



@Component  //标识当前类交给spring去new(实例化),交给spring进行管理,spring组件-bean
public class UserDao implements IUserDao{
    @Override
    //执行查询用户
    public void getUser() {
        System.out.println("Holle Spring");
    }
}



//@Component  //标识当前类交给spring去new(实例化),交给spring进行管理,spring组件-bean
public class User2Dao implements IUserDao{
    @Override
    //执行查询用户
    public void getUser() {
        System.out.println("Holle Spring 222");
    }
}


public interface IUserService {
    void getUser();
}


@Component
public class UserService implements IUserService{
    @Autowired  //让spring自动注入进来
    IUserDao userDao;

    @Override
    public void getUser() {
        userDao.getUser();
    }
}


public class Test01 {
    @Test
    public void test(){
        //UserService userService = new UserService();
        //如果是自己new一个UserService,Spring是不会为这个自己new的UserService注入userDao的
        //要依赖spring注入,就需要从spring容器中获取UserService
        ClassPathXmlApplicationContext ico = new ClassPathXmlApplicationContext("spring.xml");
        IUserService service = ico.getBean(IUserService.class);
        service.getUser();
    }
}

想要注入哪一个类就在那一个类上添加@Component注解

运行结果

 运行结果

4、基于javaConfig实现Spring的IOC

通过javaConfig(配置类)这种方式就不需要再在applicationContext.xml文件来配置要扫描的包是哪一个了,我们可以新建一个java类(javaConfig类)来代替这个xml文件,创建这个JavaConfig类,这里我把命名为SpringCopnfig,放在config文件下

ClassPathXmlApplicationContext 是基于xml配置的容器,这种方式不用xml文件了,所以用来获取对象的Spring容器也需要更改,这里需要用 AnnotationConfigApplicationContext 这个容器

然后就运行test02这个方法

相关代码:除了javaconfig(配置类)和测试方法的代码,其他代码没改动,和上面基于注解实现Spring的IOC中的代码一样

/*这个配置类就用来代替xml*/
@Configuration // = xml的配置文件
@ComponentScan("com.lt") //这个注解告诉spring要扫描的包在哪里,等于在xml文件中配置的 <context:component-scan 标签
public class SpringConfig {

}


public class Test01 {
    
    @Test  //测试基于 XML 实现Spring的IOC的方法
    public void test(){
        //如果是自己new一个UserService,Spring是不会为这个自己new的UserService注入userDao的
        //要依赖spring注入,就需要从spring容器中获取UserService
        //(我这里把获得的容器命名为 ioc)
        ClassPathXmlApplicationContext ico = new ClassPathXmlApplicationContext("spring.xml");
        IUserService service = ico.getBean(IUserService.class);
        service.getUser();
    }

    @Test  //测试基于 javaconfig 实现Spring的IOC的方法
    public void test02(){
        //如果是自己new一个UserService,Spring是不会为这个自己new的UserService注入userDao的
        //要依赖spring注入,就需要从spring容器中获取UserService
        //从spring容器中获取UserService(我这里把获得的容器命名为 ioc)
        AnnotationConfigApplicationContext ico = new AnnotationConfigApplicationContext(SpringConfig.class);
        IUserService service = ico.getBean(IUserService.class);
        service.getUser();
    }
}

5、总结

1.、spring1版本 纯xml文件的方式:这种方式中,如果要把某个类交给Spring帮我们管理,帮我们去 new 这个对象,那就需要把这个类在 xml 文件中配置成相应的 bean,如果要配置的 bean 非常的多的话,那这个 xml 文件的信息就会非常的多,也不利于我们后期的一个维护,开发的效率也非常的低(因为单单去编写这个 xml 文件都要花费许多时间)

 2、spring2版本 xml文件 + @(注解)的方式:在这种方式中,我们只需要在 xml 中配置一个扫描包,然后告诉他扫描的包路径,然后他就会通过这个包路径去扫描这个包下面所有的类,一旦发现类里面有个 @component 的注解,那他就会把当前这个类交给 spring 去管理,也就是把当前这个类配置成一个 bean (就是帮我们去 new 这个类的对象)。这中方式下就不需要像 纯xml 的方式那样去编写大量配置 bean 的信息了

3、spring3版本 javaconfig(配置类) + @(注解)的方式:这种方式中,只需要一个 javaconfig(配置类)就可以代替掉之前的 xml 配置文件

【java多线程】通过等待唤醒机制、局部变量、原子变量实现线程同步-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/m0_65277261/article/details/137122461?spm=1001.2014.3001.5501

【java多线程】线程同步问题:用同步代码块、同步方法和重入锁实现线程同步-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/m0_65277261/article/details/137022053?spm=1001.2014.3001.5501【Java多线程】多线程的三种实现方式和多线程常用方法-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/m0_65277261/article/details/136961604?spm=1001.2014.3001.5501

  • 26
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
1、Spring配置文件 Spring配置文件是Spring框架中非常重要的一部分,它通常以XML格式编写,用于配置Spring应用程序中的各种组件,例如Bean、AOP、数据源、事务等。 在Spring配置文件中,最常用的标签是<bean>标签,用于定义和配置Spring IoC容器中的Bean对象。除此之外,还有<import>标签,用于引入其他配置文件;<aop:config>标签,用于配置AOP相关的切面和通知等;<tx:advice>标签,用于配置事务管理相关的通知等。 Spring配置文件的编写需要遵守一定的规范和约束条件,例如必须指定命名空间、必须定义命名空间的schema等。同时,Spring还提供了多种加载配置文件的方式,例如ClassPathXmlApplicationContext、FileSystemXmlApplicationContext等。 2、Spring IoC基于注解的操作和案例 除了使用XML配置文件之外,Spring IoC容器还支持基于注解的Bean定义和注入操作。在Spring中,使用注解可以大大简化配置文件的编写,提高开发效率和可读性。 常用的Spring注解包括: - @Component:用于标识一个组件,通常与@Autowired等注解一起使用。 - @Autowired:用于自动注入一个Bean对象。 - @Qualifier:用于指定一个Bean对象的名称。 - @Value:用于注入一个基本类型或String类型的属性值。 - @Configuration:用于标识一个配置类,通常与@Bean等注解一起使用。 - @Bean:用于定义一个Bean对象,通常用于@Configuration类中。 - @Profile:用于指定一个Bean对象的环境依赖。 下面是一个基于注解Spring IoC配置案例: ``` @Configuration public class AppConfig { @Bean public UserService userService() { return new UserServiceImpl(); } } ``` 在这个案例中,使用@Configuration注解表示这是一个配置类,使用@Bean注解表示定义了一个名为“userService”的Bean对象。该Bean对象的类型是UserServiceImpl。 另外,还可以使用@Autowired和@Qualifier注解实现Bean的自动注入。例如: ``` @Service public class UserServiceImpl implements UserService { @Autowired @Qualifier("userRepository") private UserRepository userRepository; // ... } ``` 在这个案例中,使用@Service注解表示这是一个服务类,使用@Autowired注解表示自动注入一个名为“userRepository”的Bean对象。其中,@Qualifier注解用于指定Bean对象的名称。 总之,Spring配置文件和基于注解的操作是Spring框架中非常重要和常用的组件,它们为Java开发人员提供了一种高效、灵活和可维护的方式来管理对象和依赖关系。通过基于注解的方式,可以大大简化配置文件的编写工作,提高开发效率和可读性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值