3. 基于注解方式管理Bean

1. 什么是注解

(1)注解是代码中的特殊标记,格式为:@注解名称(属性名称=属性值, 属性名称=属性值, …)

(2)注解可以作用在类、方法、属性上面

(3)使用注解的目的:简化xml配置

2. 使用注解管理Bean

2.1 基于注解方式创建对象

2.1.1 注解说明

  • @Component
  • @Service
  • @Controller
  • @Repository

上面四个注解功能是一样的,都可以用来创建bean实例,为了区分不同层级的功能,因此建议不同的层级用不同注解进行表示

2.1.2 代码实现

  1. 引入依赖

    需要引入apo依赖

    3. 基于注解方式管理Bean

  2. 开启组件扫描

    <?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 http://www.springframework.org/schema/context/spring-context.xsd">
    
    
        <!-- 开启组件扫描
                1. 如果扫描多个包,多个包之间使用逗号分隔
                2. 直接扫描上次目录
         -->
        <context:component-scan base-package="com.study.spring5.demo10"></context:component-scan>
    </beans>
    
  3. 创建UserService类,在类上面添加创建对象的注解

    import org.springframework.stereotype.Component;
    import org.springframework.stereotype.Service;
    
    //@Component(value = "userService")
    //@Component
    @Service
    // 等同于在配置文件中写 <bean id="userService" class="...">
    // 在注解里面value属性值可以省略不写,默认值就是类名称的首字母小写 UserService => userService
    public class UserService {
    
        public void add() {
            System.out.println("service add");
        }
    }
    
  4. 创建主方法

    public class Main {
    
        public static void main(String[] args) {
            ApplicationContext applicationContext =
                    new ClassPathXmlApplicationContext("bean10.xml");
            UserService userService = applicationContext.getBean("userService", UserService.class);
            userService.add();
        }
    }
    

2.2 组件扫描配置

UserService类

import org.springframework.stereotype.Component;
import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Service;


//@Component(value = "userService")
//@Component
//@Service
@Controller // 由于配置文件的配置,只能使用@Controller注解才会被扫描到
// 等同于在配置文件中写 <bean id="userService" class="...">
// 在注解里面value属性值可以省略不写,默认值就是类名称的首字母小写 UserService => userService
public class UserService {

    public void add() {
        System.out.println("service add");
    }
}

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


    <!-- 组件扫描配置 只扫描用Controller注解声明的类
            use-default-filters属性用来控制是否使用默认filter进行扫描
     -->
    <context:component-scan base-package="com.study.spring5.demo11" use-default-filters="false">
        <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>


    <!-- 组件扫描配置 不扫描用Component注解声明的类 不需要配置 use-default-filters属性 -->
    <context:component-scan base-package="com.study.spring5.demo11">
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Component"/>
    </context:component-scan>
</beans>

主方法

public class Main {

    public static void main(String[] args) {
        ApplicationContext applicationContext =
                new ClassPathXmlApplicationContext("bean11.xml");
        UserService userService = applicationContext.getBean("userService", UserService.class);
        userService.add();
    }
}

2.3 基于注解方式实现属性注入

2.3.1 注解说明

  • @Autowired

    根据属性类型进行自动注入

  • @Qualifier

    根据属性名称进行注入

  • @Resource

    可以根据类型注入,也可以根据名称注入

  • @Value

    注入普通类型属性

2.3.2 代码实现

  • @Autowired

    第一步:创建service和dao对象,在service和dao类添加创建对象的注解

    UserService类

    @Service
    public class UserService {
    
        public void add() {
            System.out.println("UserService::add");
        }
    }
    

    UserDao接口

    public interface UserDao {
    
        void add();
    }
    

    UserDao接口实现类UserDaoImpl

    @Repository
    public class UserDaoImpl implements UserDao {
    
        @Override
        public void add() {
            System.out.println("UserDaoImpl::add");
        }
    }
    

    第二步:在service注入dao对象,在UserServiceImpl类添加UserDao类型属性

    将UserService改为以下内容

    @Service
    public class UserService {
    
        // 定义dao类型属性,不需要添加set方法
        // 添加注入属性注解
        @Autowired
        private UserDao userDao;
    
        public void add() {
            System.out.println("UserService::add");
            userDao.add();
        }
    }
    

    主方法

    public class Main {
    
        public static void main(String[] args) {
            ApplicationContext applicationContext =
                    new ClassPathXmlApplicationContext("bean12.xml");
            UserService userService = applicationContext.getBean("userService", UserService.class);
            userService.add();
        }
    }
    
  • @Qualifier

    需要和@Autowired一起使用

    用于当一个接口有多个实现类时候,按照名称注入指定的实现类

    UserDaoImpl改为

    @Repository(value = "userDaoImpl")
    public class UserDaoImpl implements UserDao {
    
        @Override
        public void add() {
            System.out.println("UserDaoImpl::add");
        }
    }
    

    UserService改为

    @Service
    public class UserService {
    
        // 定义dao类型属性,不需要添加set方法
        // 添加注入属性注解
        @Autowired
        // 当有多个实现类时,按照指定的名称注入实现类,默认不写的话,则注入类名称首字母小写后的类 UserDao => userDao
        @Qualifier(value = "userDaoImpl")
        private UserDao userDao;
    
        public void add() {
            System.out.println("UserService::add");
            userDao.add();
        }
    }
    
  • @Resource(spring不建议使用)

    JDK11版本及以上需要引用javax.annotation-api才可使用@Resource注解

    3. 基于注解方式管理Bean

    将UserService改为

    @Service
    public class UserService {
    
    //    @Resource
        @Resource(name = "userDaoImpl") // 根据名称进行注入
        private UserDao userDao;
    
        public void add() {
            System.out.println("UserService::add");
            userDao.add();
        }
    }
    
  • @Value

    UserService改写为

    @Service
    public class UserService {
    
    //    @Resource
        @Resource(name = "userDaoImpl") // 根据名称进行注入
        private UserDao userDao;
    
        @Value(value = "注入的名称")
        private String name;
    
        public void add() {
            System.out.println("UserService::add");
            userDao.add();
            System.out.println("注入的name值:" + name);
        }
    }
    

2.4 完全注解开发

  1. 创建配置类,替代xml配置文件

    import org.springframework.context.annotation.ComponentScan;
    import org.springframework.context.annotation.Configuration;
    
    // 声明该类作为配置类
    @Configuration
    // @ComponentScan(basePackages = {"com.study.spring5.demo13"})
    // 等同于<context:component-scan base-package="com.study.spring5.demo13"/>
    @ComponentScan(basePackages = {"com.study.spring5.demo13"})
    public class SpringConfig {
        
    }
    
  2. 编写UserDao接口

    public interface UserDao {
    
        void add();
    }
    
  3. 编写UserDaoImpl实现类

    @Repository
    public class UserDaoImpl implements UserDao {
    
        @Override
        public void add() {
            System.out.println("UserDaoImpl::add");
        }
    }
    
  4. 编写主方法

    public class Main {
    
        public static void main(String[] args) {
            // 加载配置类,通过配置类加载配置,替代掉xml
            ApplicationContext applicationContext =
                    new AnnotationConfigApplicationContext(SpringConfig.class);
            UserService userService = applicationContext.getBean("userService", UserService.class);
            userService.add();
        }
    }
    
上一篇:Spring源码--debug分析循环依赖--构造器注入


下一篇:使用 Spring 实现 AOP.(代码实例)-- 使用 Spring 的 API 接口实现、使用自定义类实现、使用注解方式实现