关闭 x
IT技术网
    技 采 号
    ITJS.cn - 技术改变世界
    • 实用工具
    • 菜鸟教程
    IT采购网 中国存储网 科技号 CIO智库

    IT技术网

    IT采购网
    • 首页
    • 行业资讯
    • 系统运维
      • 操作系统
        • Windows
        • Linux
        • Mac OS
      • 数据库
        • MySQL
        • Oracle
        • SQL Server
      • 网站建设
    • 人工智能
    • 半导体芯片
    • 笔记本电脑
    • 智能手机
    • 智能汽车
    • 编程语言
    IT技术网 - ITJS.CN
    首页 » JAVA »Java Web系列:Spring依赖注入基础

    Java Web系列:Spring依赖注入基础

    2016-01-15 00:00:00 出处:soul_code
    分享

    一、Spring简介

    1.Spring简化Java开发

    Spring Framework是一个应用框架,框架一般是半成品,我们在框架的基础上可以不用每个项目自己实现架构、基础设施和常用功能性组件,而是可以专注业务逻辑。因此学习Spring Framework在架构和模式方面的结构和原理,对我们在架构和模块级别的理解帮助极大。Spring Framework(参考1)的宗旨是简化Java开发,主要的手段如下:

    (1)在架构上解耦:通过DI(依赖注入)管理类型依赖,通过AOP分离关注点,减少重复代码。

    (2)在设计上广泛采用DIP(依赖倒置)和ISP(接口隔离)等原则和Facade(外观)等模式:提供简化的调用接口并封装了众多出色的第三方组件。

    (3)在语言层面上采用注解:通过配置文件和Annotation(参考.NET Attribute)简化应用配置。

    2.Spring Framework的架构和模块:

    Spring Framework本身的架构是典型的松散分层,外层可以按需引用全部内层,内层不能引用外层。Spring的基础组件如下图所示:

    Java Web系列:Spring依赖注入基础

    从图中可以看出,开始的模块只有从core/beans/aop/context四个组件,后来添加了context-support【1.2】扩展模块、expression【3.0】扩展模块和beans-groovy【4.0】扩展模块。

    Spring上述模块的基础上,内建和封装了众多的实用的通用组件,主要的组件如图所示:

    Java Web系列:Spring依赖注入基础

    从图中可以看出,spring-oxm、spring-jdbc和spring-web是众多模块依赖的核心,spring-oxm提供了Object和XML的映射支持。

    二、基础知识

    1.DIP:DIP(依赖倒置原则)是DI(依赖注入)的核心(参考2)。

    (1)高层模块不应该依赖于低层模块。两者都应该依赖于抽象。

    (2)抽象不应该依赖于细节。细节应该依赖于抽象。

    说人话就是:将对具体类的引用转换成对其接口的引用,具体类只引用接口(引用==依赖,接口==接口或抽象类)。事实上我们调用具体类的时候在头脑里也是只关心其提供的API而非实现,DIP则通过在设计和重构阶段在技术手段上保证了解耦。

    2.DI:DI(依赖注入)让我们不必手写工厂代码来管理接口和实现类的映射、对象的创建和生命周期的管理。

    (1)接口注入:必须实现特定的接口才可以,侵入性太强,现在已经无人关心和使用。

    (2)构造函数注入:依赖体现在构造函数的参数上。

    (3)属性注入:依赖体现在属性上。

    由于在实现时,可以将类型注册为自己的兼容类型,这样依赖注入就可以直接替代new实例化对象,这样理解和使用依赖注入工具还不如不使用或手写工厂了。依赖注入工具在实现时肯定会实现成一个支持不同配置和不同生命周期的对象工厂,但即使没有提供一套添加依赖倒置原则限制的API,也不意味着我们把它当成new的替代品。如同映射工具虽然在实现时可以任意映射,但不是用来取代赋值的,而是用来处理领域实体和视图模型等有实际对应关系的对象之间的映射。

    (1)依赖配置:依赖配置是依赖注入实现的基础。依赖注入工具都至少支持代码配置和文件配置。Java中可以通过Annotation(.NET中通过Attribute)简化配置。

    (2)对象工厂:根据配置返回一个或多个对象。这是核心功能。

    (3)生命周期管理:一般提供至少4种级别的支持:作用域、单例、线程、HTTP请求范围。

    大多数依赖注入工具在支持依赖倒置原则的基础上,在技术手段上实现了更多的功能,如类型的兼容转换、对依赖命名、在配置时直接传入对象等。

    三、Spring依赖注入的要点

    Bean在Spring中就是POJO(.NET的POCO)。

    Spring依赖注入需要掌握的核心是3个类型BeanDefinition、BeanFactory和ApplicationContext。

    1.BeanFactory

    BeanFactory是spring中依赖注入的核心接口,其设计主要采用了ISP(接口隔离原则),通过多层次的接口继承即保证了单个接口的内聚又保证了整个体系的简洁。这里我们要关注的核心是DefaultListableBeanFactory。

    Java Web系列:Spring依赖注入基础

    如图所示,查看XmlBeanFactory代码,可以看到XmlBeanFactory只是通过XmlBeanDefinitionReader载入了BeanDefinition配置,XmlBeanDefinitionReader负责将配置解析到BeanDefinition。DefaultListableBeanFactory是真正的实现类,其中定义了类型为Map<String, BeanDefinition>的beanDefinitionMap列表用于存储依赖配置。

    2.BeanDefinition:

    BeanDefinition定义了配置元数据,无论使用java code、xml、Annotation还是Groovy脚本方式,不同的配置方式通过不同的BeanDefinitionReader解析为BeanDefinition。

    Java Web系列:Spring依赖注入基础

    3.ApplicationContext

    ApplicationContext的核心都是将对象工厂功能委托给BeanFactory的实现类DefaultListableBeanFactory。目前最常用的是基于注解的AnnotationConfigApplicationContext和AnnotationConfigWebApplicationContext。

    Java Web系列:Spring依赖注入基础

    四、Spring依赖注入快速上手

    1.使用Java配置代替xml配置

    Java配置的核心是@Configuration和@Bean。定义生命周期使用@Scope,需要引入其他配置文件时使用@Import。

    (1)@Configuration:应用了@Configuration注解的POCO成为了配置类。相当于xml配置文件。

    (2)@Bean:配置类中应用了@Bean注解的方法成为了配置项。相当于xml中的Bean节点。

    package me.test.spring_ioc;
    
    import org.springframework.context.annotation.AnnotationConfigApplicationContext;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    public class App {
        public static void main(String[] args) {
            AnnotationConfigApplicationContext container = new AnnotationConfigApplicationContext(AppConfig.class);
            String message = container.getBean(IAppService.class).Test();
            System.out.println(message);
            container.close();
        }
    }
    
    @Configuration
    class AppConfig {
        @Bean
        public IAppService IAppService() {
            return new AppService(new Repository<SimpleEntity>());
        }
    }
    
    class SimpleEntity {
        private String name;
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    }
    
    interface IAppService {
        String Test();
    }
    
    interface IRepository<T> {
        String Test();
    }
    
    class AppService implements IAppService {
    
        private IRepository<SimpleEntity> _repo;
    
        public AppService(IRepository<SimpleEntity> repo) {
            _repo = repo;
        }
    
        @Override
        public String Test() {
            return this._repo.Test();
        }
    
    }
    
    class Repository<T> implements IRepository<T> {
    
        @Override
        public String Test() {
            return this.getClass().getName();
        }
    
    }

    如果是Web应用程序,应该使用AnnotationConfigWebApplicationContext,在JSP中可通过WebApplicationContextUtils获取ApplicationContext对象。

    <%@page import="swp.IAppService"%>
    <%@page import="org.springframework.web.context.WebApplicationContext"%>
    <%@page
        import=" org.springframework.web.context.support.WebApplicationContextUtils"%>
    <html>
    <body>
        <%
            WebApplicationContext context = WebApplicationContextUtils
                    .getRequiredWebApplicationContext(this.getServletContext());
            String message = context.getBean(IAppService.class).print();
            out.print(message);
        %>
    </body>
    </html>

    2.基于Annotation的自动装配

    自动装配主要使用@ComponentScan、@Component和@Autowired。

    (1)@ComponentScan:作用在配置类上,启用组件扫描。扫描并注册标注了@Component(@Controller/@Service/@Repository)的类型。@Configuration已经应用了@Component注解。

    (2)@Autowired:按类型自动装配。@Autowired和使用@Inject(JSR-330)或@Resource(JSR-250)的效果是类似的。@Autowired和@Inject默认按类型注入,@Resource默认按名称注入。

    package me.test.spring_ioc;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.annotation.AnnotationConfigApplicationContext;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.ComponentScan;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.stereotype.Component;
    
    public class App {
        public static void main(String[] args) {
            AnnotationConfigApplicationContext container = new AnnotationConfigApplicationContext(AppConfig.class);
            String message = container.getBean(IAppService.class).Test();
            System.out.println(message);
            container.close();
        }
    }
    
    @Configuration
    @ComponentScan
    class AppConfig {
    
        /*@Bean
        public IAppService IAppService() {
            return new AppService(new Repository<SimpleEntity>());
        }*/
    
    }
    
    class SimpleEntity {
        private String name;
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    }
    
    interface IAppService {
        String Test();
    }
    
    interface IRepository<T> {
        String Test();
    }
    
    @Component
    class AppService implements IAppService {
    
        private IRepository<SimpleEntity> _repo;
    
        @Autowired
        public AppService(IRepository<SimpleEntity> repo) {
            _repo = repo;
        }
    
        @Override
        public String Test() {
            return this._repo.Test();
        }
    
    }
    
    @Component
    class Repository<T> implements IRepository<T> {
    
        @Override
        public String Test() {
            return this.getClass().getName();
        }
    
    }

    小结:

    你至少应该知道的:

    (1)BeanFactory和BeanDefinition

    (2)DefaultListableBeanFactory和ApplicationContext

    (3)AnnotationConfigApplicationContext和AnnotationConfigWebApplicationContext

    (4)@Configuraton和@Bean

    Spring的依赖注入在配置上是基于对象而不是类型,最先支持的是xml而不是注解,到现在也没有比较方便的代码配置机制。虽然现在已经从xml过渡到了注解方式,但基于对象的基础仍然是影响很多方面的缺点。

    参考

    1.http://docs.spring.io/spring-framework/docs/current/spring-framework-reference/html/overview.html

    2.https://en.wikipedia.org/wiki/Dependency_inversion_principle

    3.http://www.ibm.com/developerworks/cn/java/j-guice.html

    4.https://www.ibm.com/developerworks/cn/webservices/ws-springjava/

    5.http://www.ibm.com/developerworks/cn/opensource/os-cn-spring-iocannt/

    6.https://www.ibm.com/developerworks/cn/java/j-lo-spring25-ioc/

    7.http://www.ibm.com/developerworks/cn/java/j-lo-beanannotation/

    8.http://www.ibm.com/developerworks/cn/java/j-guice.html

    9.http://www.yiibai.com/spring/spring-dependency-checking-with-required-annotation.html

    随笔里的文章都是干货,都是解决实际问题的,这些问题我在网上找不到更好的解决方法,才会有你看到的这一篇篇随笔,因此如果这篇博客内容对您稍有帮助或略有借鉴,请您推荐它帮助更多的人。如果你有提供实际可行的更好方案,请推荐给我。
    上一篇返回首页 下一篇

    声明: 此文观点不代表本站立场;转载务必保留本文链接;版权疑问请联系我们。

    别人在看

    抖音安全与信任开放日:揭秘推荐算法,告别单一标签依赖

    ultraedit编辑器打开文件时,总是提示是否转换为DOS格式,如何关闭?

    Cornell大神Kleinberg的经典教材《算法设计》是最好入门的算法教材

    从 Microsoft 下载中心安装 Windows 7 SP1 和 Windows Server 2008 R2 SP1 之前要执行的步骤

    Llama 2基于UCloud UK8S的创新应用

    火山引擎DataTester:如何使用A/B测试优化全域营销效果

    腾讯云、移动云继阿里云降价后宣布大幅度降价

    字节跳动数据平台论文被ICDE2023国际顶会收录,将通过火山引擎开放相关成果

    这个话题被围观超10000次,火山引擎VeDI如此解答

    误删库怎么办?火山引擎DataLeap“3招”守护数据安全

    IT头条

    平替CUDA!摩尔线程发布MUSA 4性能分析工具

    00:43

    三起案件揭开侵犯个人信息犯罪的黑灰产业链

    13:59

    百度三年开放2.1万实习岗,全力培育AI领域未来领袖

    00:36

    工信部:一季度,电信业务总量同比增长7.7%,业务收入累计完成4469亿元

    23:42

    Gartner:2024年全球半导体营收6559亿美元,AI助力英伟达首登榜首

    18:04

    技术热点

    iOS 8 中如何集成 Touch ID 功能

    windows7系统中鼠标滑轮键(中键)的快捷应用

    MySQL数据库的23个特别注意的安全事项

    Kruskal 最小生成树算法

    Ubuntu 14.10上安装新的字体图文教程

    Ubuntu14更新后无法进入系统卡在光标界面解怎么办?

      友情链接:
    • IT采购网
    • 科技号
    • 中国存储网
    • 存储网
    • 半导体联盟
    • 医疗软件网
    • 软件中国
    • ITbrand
    • 采购中国
    • CIO智库
    • 考研题库
    • 法务网
    • AI工具网
    • 电子芯片网
    • 安全库
    • 隐私保护
    • 版权申明
    • 联系我们
    IT技术网 版权所有 © 2020-2025,京ICP备14047533号-20,Power by OK设计网

    在上方输入关键词后,回车键 开始搜索。Esc键 取消该搜索窗口。