[笔记] @Produces 和 @Inject、@Bean 和 @Autowired

@Inject 注解的变量会自动调用构造函数初始化

如果希望不止是调用默认构造函数,可以使用 @Produces 动态生成

先定义一个 MyConnection 这是我们要用 @Inject 注解的变量的类型

package com.example.demo.entity;

import com.example.demo.utils.Logger;

public class MyConnection {
    private final String host;
    private final String port;

    public MyConnection(String host, String port) {
        this.host = host;
        this.port = port;
    }

    public void connect() {
        Logger.message("Connect to " + this.host + ":" + this.port);
    }

    public void query() {
        Logger.message("execute query");
    }

    public void disconnect() {
        Logger.message("Disconnect " + this.host + ":" + this.port);
    }
}

定义一个注解,用于 @Inject 的时候可以传参数

package com.example.demo.annotation;

import javax.inject.Qualifier;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

@Qualifier
@Target({TYPE, METHOD, FIELD, PARAMETER})
@Retention(RUNTIME)
public @interface MyProducedConnection {
    String host() default "";
    String port() default "";
}

定义一个 Factory,这里 @Produces 注解的函数会和 @Inject 配合,由 @Inject 注解的变量,如果变量类型是 MyConnection,就会找到这个由 @Produces 注解的,返回类型为 MyConnection 的函数

@RequestScoped 不是必须的,它表示这个函数产生的变量是 RequestScoped 的

@MyProducedConnection 也不是必须的,@Inject 再加这个注解,可用于传参数给 produces 函数

@Disposes 注解的函数,会在 @Inject 注解的变量失效的时候被调用

package com.example.demo.factory;

import com.example.demo.annotation.MyProducedConnection;
import com.example.demo.entity.MyConnection;

import javax.enterprise.context.Dependent;
import javax.enterprise.context.RequestScoped;
import javax.enterprise.inject.Disposes;
import javax.enterprise.inject.Produces;
import javax.enterprise.inject.spi.InjectionPoint;


@Dependent
public class MyConnectionFactory {

    @Produces
    @MyProducedConnection
    @RequestScoped
    public MyConnection produce(InjectionPoint injectionPoint) {
        MyProducedConnection annotation =
                injectionPoint.getAnnotated().getAnnotation(MyProducedConnection.class);
        String host = annotation.host();
        String port = annotation.port();

        MyConnection conn = new MyConnection(host, port);
        conn.connect();
        return conn;
    }

    public void closeConn(@Disposes @MyProducedConnection MyConnection conn) {
        conn.disconnect();
    }
}

应用,通过 @Inject + @MyProducedConnection 由 produce 函数创建了变量

每定义一个变量,会执行一次 produce 函数

@ApplicationScoped
@Named
public class DemoService {
    @Inject
    @MyProducedConnection(host = "192.168.1.1", port = "8192")
    private MyConnection myConnection;

    @PostConstruct
    public void init() {
        myConnection.query();
    }
}

SpringBoot 环境下没起作用


SpringBoot 环境下可以使用 @Bean 和 @Autowired
    @Bean
    @Scope(SCOPE_REQUEST)
    public MyConnection produce() {
        Logger.message("MyConnectionFactory produce conn");

        MyConnection conn = new MyConnection("192.168.1.1", "8912");
        conn.connect();
        return conn;
    }

@Bean 函数一定会被执行,不管有没有定义 @Autowired MyConnection

应用,@Autowired 注解的 MyConnection 变量,会直接使用 @Bean 创建的实例,不会重新调用 produce,如果定义多个 @Autowired MyConnection 变量,实际上都是指向同一个,并不会重新调用 produce

    @Autowired
    private MyConnection myConnection;

但可以通过 name 属性实现多个 @Bean 和多个变量

    @Bean(name = "test1")
    public MyConnection produce1() {
        Logger.message("MyConnectionFactory produce conn");

        MyConnection conn = new MyConnection("192.168.1.1", "8912");
        conn.connect();
        return conn;
    }

    @Bean(name = "test2")
    public MyConnection produce2() {
        Logger.message("MyConnectionFactory produce conn");

        MyConnection conn = new MyConnection("192.168.1.2", "8912");
        conn.connect();
        return conn;
    }

应用

    @Resource(name = "test1")
    private MyConnection myConnection1;

    @Resource(name = "test2")
    private MyConnection myConnection2;
posted @ 2022-01-14 22:57  moon~light  阅读(501)  评论(0编辑  收藏  举报