SpringBoot中Utils中无法读取application.yml与无法注入Bean

SpringBoot中Utils中无法注入Bean

问题:

​ 使用springboot的JavaMailSender 发送邮件时一直注入不了。

@Autowired
private JavaMailSender javaMailSender;

原始代码:

@Autowired
private JavaMailSender javaMailSender;

 public static void sendMail(String receiveEmail, String emailSubject, String emailText){
        SimpleMailMessage message = new SimpleMailMessage();
        message.setFrom("website@aamazedata.com");
        message.setTo(receiveEmail);
        message.setText(emailText);
        message.setSubject(emailSubject);
        javaMailSender.send(message);
    }

上面的这样测试时一直在报空指针异常,提示无法注入JavaMailSender。

有两种解决方法:

一、 使用applicationContext的getBean方法即可实现。
public static void sendMail(String receiveEmail, String emailSubject, String emailText){
    JavaMailSender javaMailSender = ApplicationContextUtil.get(JavaMailSender.class);
    SimpleMailMessage message = new SimpleMailMessage();
    message.setFrom("website@aamazedata.com");
    message.setTo(receiveEmail);
    message.setText(emailText);
    message.setSubject(emailSubject);
    javaMailSender.send(message);
}

ApplicationContextUtill:

@Configuration
public class ApplicationContextUtil implements ApplicationContextAware {

    // 定义静态的ApplicationContext成员对象
    private static ApplicationContext applicationContext;

    // 重写setApplicationContext方法,把参数中的ApplicationContext对象赋值给类静态成员
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        ApplicationContextUtil.applicationContext = applicationContext;
    }

    // 定义get方法,参数为Class,调用上下文的getBean方法获取容器中的指定对象
    public static <T> T get(Class<T> clazz){
        return applicationContext.getBean(clazz);
    }

    // 同上,参数为对象名
    public static Object get(String name) {
        return applicationContext.getBean(name);
    }
}

个人感觉上面这个类其实的核心还是ApplicationContext,直接调用ApplicationContext。getBean()应该就可以。

上面是使用自己定义的ApplicationContextUtil来获取Spring配置文件中的实例方法。

当然还有许多现成的工具类: SpringUtils.getBean() 、 SpringContextUtil.getBean()都可以。

二、 使用@PostConstruct注解,专门可以解决在静态方法中调用依赖注入的Bean中的方法。

@PostConstruct注解好多人以为是Spring提供的。其实是java自己的注解。

java中该注解的说明:@PostConstruct该注解被用来修饰一个非静态的void()方法。该@PostConstruct修饰的方法会在服务器加载Servlet的时候运行,并且服务器只会被服务器执行一次。PostConstruct在构造函数之后执行,init()方法之前执行。

通常我们会是在Spring框架中使用@PostConstruct注解。该注解在整个Bean初始化中的执行顺序是: Constructor(构造方法) -> @Autowired(依赖注入) -> @PostConstruct(注释的方法)。

解决方法

1、首先在MailUtis上添加@Component声明其为bean组件

2、使用Autowired注入要注入的那个类(JavaMailSender)

3、在MailUtils中声明一个静态的私有变量private static MailUtils mailUtils;

4、添加共有的init方法,并使用@PostConstruct声明在项目启动的时候进行执行该方法,也可以理解为在Spring容器初始化的时候执行该方法。

代码变为:

@Component
public class MailUtils {
    @Autowired
    private JavaMailSender javaMailSender;

    private static MailUtils mailUtils;

     @PostConstruct
     public void init(){
     mailUtils = this;
     mailUtils.javaMailSender = this.javaMailSender;
     }

      public static void sendMail(String receiveEmail, String emailSubject, String emailText){
            SimpleMailMessage message = new SimpleMailMessage();
            message.setFrom("website@aamazedata.com");
            message.setTo(receiveEmail);
            message.setText(emailText);
            message.setSubject(emailSubject);
            mailUtils.javaMailSender.send(message);
        }
}

上面的办法亲测可用。

上面的办法也可以解决下面的问题:

当我们自己创建了配置类:

@Configuration
public class MailAccountConfig implements ApplicationContextAware {
    @Value("${email.host}")
    private String host;
    @Value("${email.port}")
    private Integer port;
    @Value("${email.from}")
    private String from;
    @Value("${email.user}")
    private String user;
    @Value("${email.pass}")
    private String pass;
    @Value("${email.ssLEnable}")
    private Boolean ssLEnable;
    
    
     @Bean
    public MailAccount mailAccount(){
        MailAccount mailAccount = new MailAccount();
        mailAccount.setHost(host);
        mailAccount.setPort(port);
        mailAccount.setAuth(true);
        mailAccount.setFrom(from);
        mailAccount.setUser(user);
        mailAccount.setPass(pass);
        mailAccount.setSslEnable(ssLEnable);
        return mailAccount;
    }

当想自己使用这个Bean时,你会发现在Utils中还是不能注入,这时还是借鉴上面的PostConstruct注解解决。

SpringBoot的Utils中还不能读取Application.yml中配置的属性

遇到这种情况时,首先考虑Spring接口类Environment:

  1. Spring 为运行环境提供了的高度的抽象接口,项目运行中的所有配置都是基于此接口,用来表示整个应用运行时的环境。

  2. 该接口继承自PropertyResolver, 而PropertyResolver规范了解析底层任意property资源,也就意味着application.yml是由ProprttyResolver管理。

  3. PropertyResolver提供了方法getProperty(String key) ,该方法通过传入properties文件中定义的key,返回与给定键关联的属性值。

    因此使用下面的代码即可实现在Utils中自由读取配置文件中自定义的所有属性。

    public static String getProperty(){
        Environment environment = ApplicationContextUtil.get(Environment.class);
        String host = environment.getProperty("spring.mail.host");
        logger.info(host);
        String port = environment.getProperty("spring.mail.port");
        logger.info(port);
        String username = environment.getProperty("spring.mail.username");
        logger.info(username);
        String password = environment.getProperty("spring.mail.password");
        logger.info(password);
        String protocol = environment.getProperty("spring.mail.protocol");
        logger.info(protocol);
        return null;
    }
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值