写在前面

在spring4之后,要使用注解开发,必须要保证aop的包导入了

image-1659954770215

1. 环境搭建

1.1 applicationContext.xml

这里需要配置两个上下文属性:

  • component-scan 指定要扫描的包
  • annotation-config 开启注解
<?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">

    <!--指定要扫描的包,这个包下的注解就会生效-->
    <context:component-scan base-package="cc.leeleo.entity"/>
    <!--开启注解-->
    <context:annotation-config/>
</beans>

1.2 新建一个要扫描的包

这里创建cc.leeleo.entity 包作为要扫描的包,并创建User类,并添加@Component注解,此处的注解的作用相当于是在xml中配置<**bean id="user" class="cc.leeleo.entity.User"**/> ,说明当前类交由Spring管理了。

User.java

@Component
@Data
public class User {
    private String id;

    public User() {
        this.id = UUID.randomUUID().toString();
    }
}

1.3 测试

image-1659954902075

以上我们就完成了注解的最基本的使用,简直不要太简单~

2. 注解实现属性注入

Spring使用了@Value注解来实现属性的注入,从而替代了使用配置文件来繁琐的配置属性注入,下面我们来看下具体实现

很简单,这里我们给User类添加一个属性name,并使用@Value注解为其赋值

User.java

@Component
@Data
public class User {
    private String id;

    @Value("张三")
    private String name;

    public User() {
        this.id = UUID.randomUUID().toString();
    }
}

测试:

image-1659954913616

2.1 衍生注解

在日常的开发中经常会使用到MVC三层架构,针对这些分层,@Compnent提供了几个衍生注解

  • dao 【@Repository】
  • service 【@Service】
  • controller 【@Controller】

这四个注解功能都是一样的,都是将标识的类注册到Spring容器中进行装配

上代码:

  1. 修改要扫描的包名:

    <context:component-scan base-package="cc.leeleo"/>
    
  2. 新建四个包,同时新建四个MVC层的类

    • cc.leeleo.entity

      @Component
      @Data
      public class User {
          private String id;
      
          @Value("张三")
          private String name;
      
          public User() {
              this.id = UUID.randomUUID().toString();
          }
      }
      
    • cc.leeleo.controller

      @Controller
      public class UserController {
          @Autowired
          private UserService userService;
      
          public User getUser(){
              return userService.getUser();
          }
      }
      
    • cc.leeleo.service

      @Service
      public class UserService {
          @Autowired
          private UserDao userDao;
      
          public User getUser() {
              return userDao.getUser();
          }
      }
      
    • cc.leeleo.dao

      @Repository
      public class UserDao {
          @Autowired
          private User user;
      
          public User getUser() {
              return user;
          }
      }
      

测试:

@Test
    public void test(){
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserController userController = context.getBean("userController", UserController.class);
        User user = userController.getUser();
        System.out.println(user.toString());

    }

输出:

"D:\Program Files\Java\jdk1.8.0_261\bin\java.exe" -ea -Didea.test.cyclic.buffer.size=1048576 "-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2020.3\lib\idea_rt.jar=62334:C:\Program Files\JetBrains\IntelliJ IDEA 2020.3\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\JetBrains\IntelliJ IDEA 2020.3\lib\idea_rt.jar;C:\Program Files\JetBrains\IntelliJ IDEA 2020.3\plugins\junit\lib\junit5-rt.jar;C:\Program Files\JetBrains\IntelliJ IDEA 2020.3\plugins\junit\lib\junit-rt.jar;D:\Program Files\Java\jdk1.8.0_261\jre\lib\charsets.jar;D:\Program Files\Java\jdk1.8.0_261\jre\lib\deploy.jar;D:\Program Files\Java\jdk1.8.0_261\jre\lib\ext\access-bridge-64.jar;D:\Program Files\Java\jdk1.8.0_261\jre\lib\ext\cldrdata.jar;D:\Program Files\Java\jdk1.8.0_261\jre\lib\ext\dnsns.jar;D:\Program Files\Java\jdk1.8.0_261\jre\lib\ext\jaccess.jar;D:\Program Files\Java\jdk1.8.0_261\jre\lib\ext\jfxrt.jar;D:\Program Files\Java\jdk1.8.0_261\jre\lib\ext\localedata.jar;D:\Program Files\Java\jdk1.8.0_261\jre\lib\ext\nashorn.jar;D:\Program Files\Java\jdk1.8.0_261\jre\lib\ext\sunec.jar;D:\Program Files\Java\jdk1.8.0_261\jre\lib\ext\sunjce_provider.jar;D:\Program Files\Java\jdk1.8.0_261\jre\lib\ext\sunmscapi.jar;D:\Program Files\Java\jdk1.8.0_261\jre\lib\ext\sunpkcs11.jar;D:\Program Files\Java\jdk1.8.0_261\jre\lib\ext\zipfs.jar;D:\Program Files\Java\jdk1.8.0_261\jre\lib\javaws.jar;D:\Program Files\Java\jdk1.8.0_261\jre\lib\jce.jar;D:\Program Files\Java\jdk1.8.0_261\jre\lib\jfr.jar;D:\Program Files\Java\jdk1.8.0_261\jre\lib\jfxswt.jar;D:\Program Files\Java\jdk1.8.0_261\jre\lib\jsse.jar;D:\Program Files\Java\jdk1.8.0_261\jre\lib\management-agent.jar;D:\Program Files\Java\jdk1.8.0_261\jre\lib\plugin.jar;D:\Program Files\Java\jdk1.8.0_261\jre\lib\resources.jar;D:\Program Files\Java\jdk1.8.0_261\jre\lib\rt.jar;D:\项目\study\spring-01\spring-annotation\target\test-classes;D:\项目\study\spring-01\spring-annotation\target\classes;C:\Users\java-boy\.m2\repository\junit\junit\4.12\junit-4.12.jar;C:\Users\java-boy\.m2\repository\org\hamcrest\hamcrest-core\1.3\hamcrest-core-1.3.jar;C:\Users\java-boy\.m2\repository\org\springframework\spring-webmvc\5.3.9\spring-webmvc-5.3.9.jar;C:\Users\java-boy\.m2\repository\org\springframework\spring-aop\5.3.9\spring-aop-5.3.9.jar;C:\Users\java-boy\.m2\repository\org\springframework\spring-beans\5.3.9\spring-beans-5.3.9.jar;C:\Users\java-boy\.m2\repository\org\springframework\spring-context\5.3.9\spring-context-5.3.9.jar;C:\Users\java-boy\.m2\repository\org\springframework\spring-core\5.3.9\spring-core-5.3.9.jar;C:\Users\java-boy\.m2\repository\org\springframework\spring-jcl\5.3.9\spring-jcl-5.3.9.jar;C:\Users\java-boy\.m2\repository\org\springframework\spring-expression\5.3.9\spring-expression-5.3.9.jar;C:\Users\java-boy\.m2\repository\org\springframework\spring-web\5.3.9\spring-web-5.3.9.jar;C:\Users\java-boy\.m2\repository\org\projectlombok\lombok\1.18.22\lombok-1.18.22.jar" com.intellij.rt.junit.JUnitStarter -ideVersion5 -junit4 TestAnnotation,test
User(id=882471a5-d84f-4ead-95e0-301359c591d2, name=张三)

进程已结束,退出代码为 0

2.2 作用域

我们在之前讲到依赖注入的时候,提到过作用域的概念,之前学到的prototype和singleton这俩作用域都是以配置文件给标签增加scope属性来完成的,其实也可以通过注解的形式实现。

这里我们直接给需要更改作用域的bean增加@Scope注解就可以了

上代码:

这里我们修改User类增加@Scope注解,使其为多例模式

@Component
@Data
@Scope("prototype")
public class User {
    private String id;

    @Value("张三")
    private String name;

    public User() {
        this.id = UUID.randomUUID().toString();
    }
}

测试:

image-1659954937478

我们发现新get的bean和现有的bean内存地址不一样,已经变成多例模式了

3、使用java实现xml配置

完全不使用Spring的xml配置,全部使用java代码实现,

先来初始化一个Spring容器,并获取一个bean

  • 使用xml实现
    以前初始化一个Spring的ApplicationContext,我们需要指定一个配置文件,并且需要在配置文件中通过标签来配置一个bean

  • 使用java实现

    1. 新建User类

      @Data
      public class User {
          private String id;
      
          @Value("张三")
          private String name;
      
          public User() {
              this.id = UUID.randomUUID().toString();
          }
      }
      
    2. 新建配置类,增加@Configuration注解,并新增一个get方法使用@Bean注解,配置一个bean

      @Configuration
      public class SpringConfig {
      
          @Bean
          public User getUser(){
              return new User();
          }
      }
      

      需要注意:

      1. 如果有多个返回值相同的方法,那么会报如下错误:
        org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'cc.leeleo.entity.User' available: expected single matching bean but found 2: getUser,getUser2
      2. @Bean注解只能作用于方法上面

    测试:这里需要注意,以前使用

    ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
    

    现在需要改为使用配置类来替代原先的xml路径了

    ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
    

image-1659954951273

知识点:
方法的名称就相当于的id属性
方法的返回值就相当于的class属性
所以我们想通过bean的id获取它的话,应该是像下面这样:
User user = context.getBean(**"getUser"**,User.**class**);

至此,我们就实现一个0xml配置的Spring容器了,使用@Configuration注解,其实就等同于使用xml中的标签,在使用注解的类中,使用@Bean注解,就等同于在标签中使用标签。

3.1 @ComponentScan

该注解的作用相当于配置文件的如下配置:

<!--指定要扫描的包,这个包下的注解就会生效-->
<context:component-scan base-package="cc.leeleo"/>

我们只需要在添加了@Configuration注解的类上追加@ComponentScan即可

@Configuration
@ComponentScan("cc.leeleo")
public class SpringConfig {

    @Bean
    public User getUser(){
        return new User();
    }

}

于此同时,只需要在指定的包下,新建的类中添加@Component、@Controller、@Repository、@Service、任一注解,均可将当前类交由Spring容器进行管理。

3.2 @Import导入配置类

我们在之前使用配置文件的时候讲过,可以通过标签即可导入其他的配置文件

<import resource="beans2.xml"/>

以下使用java的方式,此处导入的就不是xml的配置文件了,而是加了@Configuration注解的配置类了

  1. 新建个实体类Company

    public class Company {
        @Value("leeleo")
        public String name;
    
    }
    
  2. 新建配置类SpringConfig2

    @Configuration
    public class SpringConfig2 {
    
        @Bean
        public Company company(){
            return new Company();
        }
    }
    
  3. 导入配置类

    @Configuration
    @Import(SpringConfig2.class)
    public class SpringConfig {
    
        @Bean
        public User getUser(){
            return new User();
        }
    
    }
    

测试:

image-1659954965662