Spring-IOC-注解开发

目录

注解开发前的准备

@Component、@Scope、@PostConstruct、@PreDestroy注解

@Value注解

 @Autowired

@Qualifier

@Primary

@Resource

全注解开发

依赖加载


注解开发前的准备

要想使用注解进行开发,必须要启动注解扫描,加载类配置中的注解项

<context:component-scan base-package="packageName"></context:component-scan>

说明:

  • 在进行包所扫描时,会对配置的包及其子包中所有文件进行扫描
  • 扫描过程是以文件夹递归迭代的形式进行的
  • 扫描过程仅读取合法的java文件
  • 扫描时仅读取spring可识别的注解
  • 扫描结束后会将可识别的有效注解转化为spring对应的资源加入IoC容器

注意:

  • 无论是注解格式还是XML配置格式,最终都是将资源加载到IoC容器中,差别仅仅是数据读取方式不同
  • 从加载效率上来说注解优于XML配置文件

@Component、@Scope、@PostConstruct、@PreDestroy注解

先通过一个类介绍@Component、@Scope、@PostConstruct、@PreDestroy注解的使用        

package com.jjs.dao;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
@Component(value = "useDao")//声明这个类有spring管理,加入spring容器
@Scope(value = "singleton")//指定单例或者非单例
public class UserDaoImpl implements UserDao {



    public void save() {
    System.out.println("已保存");

    }

    @PostConstruct //初始化方法
    public void init(){
    System.out.println("初始化完成");
    }
    @PreDestroy //销毁方法
    public void destroy (){
        System.out.println("销毁");
    }
}

@Component与@Controller、@Dao、@Service的功能其实完全相同,只是spring用在不同场景给的一个名称区别,用于表示是干啥用的,并且后续可能会针对性的实现某些功能,但是现在还没有实现

@Value注解

说明:

  • value值仅支持非引用类型数据,赋值时对方法的所有参数全部赋值

  • value值支持读取properties文件中的属性值,通过类属性将properties中数据传入类中

  • value值支持SpEL

  • @value注解可以定义在方法上或者属性上,如果添加在属性上方,可以省略set方法(set方法的目的是为属性赋值)

使用案例:

准备阶段:

先在resources目录下创建一个application.properties文件 里面写入两条数据

username=zangsan
password=3.14159265

然后通过注解载入配置文件@PropertySource("classpath:application.properties")

最后通过@Value配个el表达式获取值

package com.jjs.dao;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;
@Component(value = "userDao")
@PropertySource("classpath:application.properties")  //加载properties配置文件
public class UserDaoImpl implements UserDao {
    @Value("${username}")
    private String username;
    @Value("${password}")
    private String password;

    public void save() {
    System.out.println("username:"+username);
    System.out.println("password:"+password);

    }
}

 @Autowired

说明:通过Autowired可以实现引用类型的注入,注入是先通过类型进行匹配,如果有同样类型存在的话,就会根据id进行匹配,下面通过代码进行解释

首先是一个接口userDao

package com.jjs.dao;
public interface UserDao {
    void save();
}

创建一个UserDao实现类UserDaoImpl1

package com.jjs.dao;
import org.springframework.stereotype.Component;
@Component(value = "userDao1")
public class UserDaoImpl implements UserDao {
    public void save() {
    System.out.println("userDao1起作用");
    }
}

这时候将UserDao注入UserService中

package com.jjs.service;
import com.jjs.dao.UserDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class UserServiceImpl implements UserService {
    @Autowired
   private UserDao useDao;
    
    public void save() {
        useDao1.save();
    }
}

结果:

这个时候就会根据UserDao这个类型识别到这个类,因为有唯一的实现类,所以成功注入

这个时候再创建一个UserDao实现类UserDaoImpl2

package com.jjs.dao;
import org.springframework.stereotype.Component;
@Component(value = "userDao2")
public class UserDaoImpl2 implements UserDao {
    public void save() {
        System.out.println("userDao2起作用");
    }
}

这时候再运行一次就会报以下错误,意思是根据类型查找,有重复的两个实现类都实现了UserDao接口,这时候根据bean的ID进行匹配,但是没有找到匹配的ID,由此已经可以看出,它是先根据类型进行匹配,当类型匹配冲突的时候,就进行ID匹配。

根据ID匹配是以bean的ID和声明注入类型的变量进行匹配。

 

 

 这个时候修改以下变量名字与其中一个ID相同就可以匹配上了

package com.jjs.service;
import com.jjs.dao.UserDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class UserServiceImpl implements UserService {
    @Autowired
   private UserDao userDao1;

    public void save() {
        useDao.save();
    }
}

@Qualifier

继续上面的例子,如果说变量名就想取为userDao,或者换个说法,当类型相同,变量名还相同的时候就可以@Qualifier这个注解进行区分,在@Qualifier表名bean的id

package com.jjs.service;
import com.jjs.dao.UserDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
@Component
public class UserServiceImpl implements UserService {
    @Autowired
    @Qualifier("userDao1")
   private UserDao userDao;

    public void save() {
        userDao.save();
    }
}

@Primary

继续上面的例子,在正常的企业开发中,很少会对一个接口做出两套实现类,所以在大多数的情况下,基本上都不会@Component或者@Service、@Dao中加上id名字。但是如果有的时候某个同事突然给了第二套实现方案,这时候可以使用Primary来标明优先级。就指定每次加载的时候都加载被@Primary注解标记的类

package com.jjs.dao;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Component;
@Component
@Primary
public class UserDaoImpl implements UserDao {
    public void save() {
    System.out.println("userDao1起作用");
    }
}

@Resource

@Resource是@Autowired和@Quelifier的组合,通过name设置注入的bean的id

package com.jjs.service;
import com.jjs.dao.UserDao;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
@Component
public class UserServiceImpl implements UserService {
    @Resource(name = "userDao")
   private UserDao userDao;
    public void save() {
        userDao.save();
    }
}

全注解开发

既然说是全注解开发,那么就是要想办法替换掉spring的配置文件

这时候就要引入一个配置类,用来代替spring的配置文件

package com.jjs.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan("com")
public class SpringConfig {
}

上述代码中,@Configuration就可以替代Spring的配置文件,而@ComponentScan则代替包扫描

接下来就是要加载配置类

import com.jjs.config.SpringConfig;
import com.jjs.service.UserServiceImpl;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class UserAPP {
  public static void main(String[] args) {
    // 加载配置文件
    ApplicationContext applicationContext =
        new AnnotationConfigApplicationContext(SpringConfig.class);
    // 获取资源
    UserServiceImpl userDao = (UserServiceImpl) applicationContext.getBean("userServiceImpl");
    userDao.save();
  }
}

依赖加载

@DependsOn

  • 名称:@DependsOn

  • 类型:类注解、方法注解

  • 位置:bean定义的位置(类上或方法上)

  • 作用:控制bean的加载顺序,使其在指定bean加载完毕后再加载

范例:

@DependsOn("beanId")
public class ClassName {
}

@Order

  • 名称:@Order
  • 类型:配置类注解
  • 位置:配置类定义的位置(类上)
  • 作用:控制配置类的加载顺序

范例:

@Order(1) //数字越小优先级越高

public class SpringConfigClassName {

}

猜你喜欢

转载自blog.csdn.net/Promise_J_Z/article/details/121680987