zoukankan      html  css  js  c++  java
  • Spring05_基于注解的IOC和DI

    本教程源码请访问:tutorial_demo

    在学习基于注解的IOC和DI之前,大家要有一个基本的认识,即注解配置和之前学习的XML配置要实现的功能是一样的,都是为了降低程序间的耦合,只是配置的形式不一样

    一、使用注解实现IOC

    1.1、创建项目

    1. 在Idea中新建Maven工程;
    2. 工程创建完成后添加相应的坐标。
    <?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.codeaction</groupId>
        <artifactId>anno</artifactId>
        <version>1.0-SNAPSHOT</version>
        <packaging>jar</packaging>
    
        <dependencies>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-context</artifactId>
                <version>5.2.6.RELEASE</version>
            </dependency>
        </dependencies>
    </project>
    

    1.2、添加相关类

    1.2.1、创建持久层接口

    package org.codeaction.dao;
    
    public interface IAccountDao {
        void saveAccount();
    }
    

    1.2.2、创建持久层接口实现类

    package org.codeaction.dao.impl;
    
    import org.codeaction.dao.IAccountDao;
    
    //@Component
    @Repository("accountDao")
    public class AccountDaoImpl implements IAccountDao {
        @Override
        public void saveAccount() {
            System.out.println("账户保存成功");
        }
    }
    

    @Component和@Repository注解下面会讲。

    1.2.3、创建业务层接口

    package org.codeaction.service;
    
    public interface IAccountService {
        void saveAccount();
    }
    

    1.2.4、创建业务层接口实现类

    package org.codeaction.service.impl;
    
    import org.codeaction.dao.IAccountDao;
    import org.codeaction.dao.impl.AccountDaoImpl;
    import org.codeaction.service.IAccountService;
    
    //@Component
    @Service("accountService")
    public class AccountServiceImpl implements IAccountService {
        private IAccountDao accountDao;
        @Override
        public void saveAccount() {
            accountDao.saveAccount();
        }
    }
    

    @Component

    作用:把资源让Spring来管理,相当于在XML中配置了一个bean;

    属性:只有一个value属性,用来指定id。如果不指定value属性,默认bean的id是当前类的类名,首字母小写。

    @Controller、@Service、@Repository

    作用和属性与@Component完全一样,但是它们提供了更加明确的语义。

    @Controller:用于视图层的注解

    @Service:用于业务层的注解

    @Repository:用于持久层的注解

    1.3、添加XML配置文件

    XML文件在resource目录下。这个文件也可以不写,但是不写如何配置,后面的教程会讲

    <?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
            https://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/context
            https://www.springframework.org/schema/context/spring-context.xsd">
        <!-- 告知spring创建容器时要扫描的包 -->
        <context:component-scan base-package="org.codeaction"></context:component-scan>
    </beans>
    

    1.4、添加测试类

    创建带有main方法的类,用来进行测试

    package org.codeaction.ui;
    
    import org.codeaction.dao.IAccountDao;
    import org.codeaction.service.IAccountService;
    import org.codeaction.service.impl.AccountServiceImpl;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.annotation.AnnotationConfigApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class AccountUI {
        public static void main(String[] args) {
            ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
            IAccountService accountService = (IAccountService) context.getBean("accountService");
            IAccountDao accountDao = (IAccountDao) context.getBean("accountDao");
    
            System.out.println(accountService);
            System.out.println(accountDao);
        }
    }
    

    运行main方法,控制台输出如下:

    org.codeaction.service.impl.AccountServiceImpl@5f71c76a
    org.codeaction.dao.impl.AccountDaoImpl@1d7acb34
    

    通过上面的内容,我们学习了如何通过注解配置bean,在AccountServiceImpl中,accountDao属性没有被注入值,接下来我们学习一下如何注入值,也就是使用注解实现DI。

    二、使用注解实现DI

    2.1、修改业务层接口实现类

    package org.codeaction.service.impl;
    
    import org.codeaction.dao.IAccountDao;
    import org.codeaction.service.IAccountService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.annotation.Qualifier;
    import org.springframework.stereotype.Service;
    
    import javax.annotation.Resource;
    
    @Service("accountService")
    public class AccountServiceImpl implements IAccountService {
        @Autowired
        private IAccountDao accountDao;
        @Override
        public void saveAccount() {
            accountDao.saveAccount();
        }
    }
    

    @Autowired

    作用

    1. 自动按照类型注入;
    2. 当使用此注解注入属性时,set方法可以省略,它只能注入bean类型;
    3. 当有多个类型匹配时(2.3会讲这种情况),使用要注入的对象变量名称作为bean的id,在Spring容器中查找,找到了可以注入成功,找不到就报错。

    2.2、修改测试类

    package org.codeaction.ui;
    
    import org.codeaction.dao.IAccountDao;
    import org.codeaction.service.IAccountService;
    import org.codeaction.service.impl.AccountServiceImpl;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.annotation.AnnotationConfigApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class AccountUI {
        public static void main(String[] args) {
            ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
            IAccountService accountService = (IAccountService) context.getBean("accountService");
            IAccountDao accountDao = (IAccountDao) context.getBean("accountDao");
    
            System.out.println(accountService);
            System.out.println(accountDao);
            
            accountService.saveAccount();
        }
    }
    

    运行main方法,控制台输出如下:

    org.codeaction.service.impl.AccountServiceImpl@1188e820
    org.codeaction.dao.impl.AccountDaoImpl@2f490758
    11111111111111111111111111111
    

    2.3、自动类型注入多个类型匹配的情况

    2.3.1、新增业务层接口实现类

    package org.codeaction.dao.impl;
    
    import org.codeaction.dao.IAccountDao;
    import org.springframework.stereotype.Repository;
    
    @Repository("accountDao1")
    public class AccountDaoImpl1 implements IAwccountDao {
        @Override
        public void saveAccount() {
            System.out.println("222222222222222222222222");//注意这个打印输出
        }
    }
    
    

    运行2.2中的main方法,控制台输出如下:

    org.codeaction.service.impl.AccountServiceImpl@33b37288
    org.codeaction.dao.impl.AccountDaoImpl@77a57272
    11111111111111111111111111111
    

    大家注意,这里输出了“11111111111111111111111111111”,证明@Autowired自动注入在有多个类型匹配时,使用要注入的对象变量名称作为bean的id,如果存在,依然可以注入成功。如果此时我希望注入AccountDaoImpl1的对象应该如何做呢?

    2.3.2、注入特定id的bean对象(方式1)

    修改业务层接口实现类,代码如下:

    package org.codeaction.service.impl;
    
    import org.codeaction.dao.IAccountDao;
    import org.codeaction.service.IAccountService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.annotation.Qualifier;
    import org.springframework.stereotype.Service;
    
    import javax.annotation.Resource;
    
    @Service("accountService")
    public class AccountServiceImpl implements IAccountService {
        @Autowired
        @Qualifier("accountDao1")
        private IAccountDao accountDao;
        @Override
        public void saveAccount() {
            accountDao.saveAccount();
        }
    }
    

    运行2.2中的main方法,控制台输出如下:

    org.codeaction.service.impl.AccountServiceImpl@77a57272
    org.codeaction.dao.impl.AccountDaoImpl@7181ae3f
    222222222222222222222222
    

    这里输出了“222222222222222222222222”,证明我们使用@Autowired结合 @Qualifier实现了特定id的bean对象的注入。

    @Qualifier

    作用

    1. 在自动按照类型注入的基础之上,再按照bean的id注入;
    2. 给方法注入参数;
    3. 在给属性注入时,不能独立使用,必须和@Autowired一起使用(我们目前案例讲的就是这种情况),给方法注入参数时,可以独立使用。

    属性:只有一个value,指定bean的id。

    上面的案例要使用两个注解,能不能一个注解就搞定?

    2.3.3、注入特定id的bean对象(方式2)

    修改业务层接口实现类,代码如下:

    package org.codeaction.service.impl;
    
    import org.codeaction.dao.IAccountDao;
    import org.codeaction.service.IAccountService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.annotation.Qualifier;
    import org.springframework.stereotype.Service;
    
    import javax.annotation.Resource;
    
    @Service("accountService")
    public class AccountServiceImpl implements IAccountService {
        //@Autowired
        //@Qualifier("accountDao1")
        @Resource(name = "accountDao1")
        private IAccountDao accountDao;
        @Override
        public void saveAccount() {
            accountDao.saveAccount();
        }
    }
    

    运行2.2中的main方法,控制台输出如下:

    org.codeaction.service.impl.AccountServiceImpl@77a57272
    org.codeaction.dao.impl.AccountDaoImpl@7181ae3f
    222222222222222222222222
    

    这里输出了“222222222222222222222222”,证明我们使用@Resource实现了特定id的bean对象的注入。

    @Resource

    作用:直接按照bean的id注入,只能注入bean类型。

    属性:name,指定bean的id。

    2.3.4、注入基本数据类型和String类型

    package org.codeaction.service.impl;
    
    import org.codeaction.dao.IAccountDao;
    import org.codeaction.service.IAccountService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.annotation.Qualifier;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.stereotype.Service;
    
    import javax.annotation.Resource;
    
    @Service("accountService")
    public class AccountServiceImpl implements IAccountService {
        @Value("hello world")
        private String test;
    
        //@Autowired
        //@Qualifier("accountDao1")
        @Resource(name = "accountDao1")
        private IAccountDao accountDao;
        @Override
        public void saveAccount() {
            System.out.println(this.test);
            accountDao.saveAccount();
        }
    }
    

    运行2.2中的main方法,控制台输出如下:

    org.codeaction.service.impl.AccountServiceImpl@3e77a1ed
    org.codeaction.dao.impl.AccountDaoImpl@3ffcd140
    hello world
    100
    222222222222222222222222
    

    这里输出了“hello world”和“100”,证明我们使用@Value能够注入基本数据类型和String类型。

    @Value

    作用:注入基本数据类型和 String 类型数据的。
    属性:只有一个value,用于指定值 。

    三、其他注解

    3.1、@Scope

    作用:指定bean的作用范围。

    属性:value,用来指定范围,可以取的值包括,singleton、prototype、request、session、globalsession。

    3.2、@PostConstruct

    作用:用于指定初始化方法。

    3.3、@PreDestroy

    作用:用于指定销毁方法。

  • 相关阅读:
    常见保护方式简介
    各种保护机制绕过手法
    ShellCode框架(Win32ASM编写)
    单例模式
    HTTP1.0、HTTP1.1、HTTP2.0的关系和区别
    java集合提供的排序算法
    Dubbox以及微服务
    进程栈帧
    java线程池
    Java多态的实现
  • 原文地址:https://www.cnblogs.com/codeaction/p/12976135.html
Copyright © 2011-2022 走看看