个人看法:设计依赖查找的设计模式,是为了解耦.
  • 单一类型依赖查找

    • JNDI javax.naming.Context#lookup
    • JavaBeans java.beans.beancontext.BeanContext
  • 集合类型依赖查找

    • java.beans.beancontext.BeanContext#getCurrentServiceSelectors
  • 层析性依赖查找

Springboot中使用JNDI

JNDI即Java Naming and Directory Interface(JAVA命名和目录接口),那么java命名目的就是为了记录一些不方便记录的内容,就像人的名字或DNS中的域名与IP的关系。
两种模式
  1. Springboot Embedded Tomcat(嵌入Tomcat)使用JNDI
  2. Springboot WAR 使用JNDI

1. Springboot Embedded Tomcat(嵌入Tomcat)使用JNDI

  • 启用默认禁用的JNDI命名。
  • 构建一个ContextResource对象,然后添加到Context对象中

java:/comp/env/ 固定写法

JndiConfig.java

package com.rumenz;import org.apache.catalina.Context;import org.apache.catalina.startup.Tomcat;import org.apache.tomcat.util.descriptor.web.ContextResource;import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;import org.springframework.boot.web.embedded.tomcat.TomcatWebServer;import org.springframework.boot.web.servlet.server.ServletWebServerFactory;import org.springframework.context.annotation.Bean;import org.springframework.jndi.JndiObjectFactoryBean;import org.springframework.stereotype.Component;import javax.naming.NamingException;import javax.sql.DataSource;@Componentpublic class JndiConfig {    @Bean    public ServletWebServerFactory servletContainer() {        TomcatServletWebServerFactory tomcatServletWebServerFactory = new TomcatServletWebServerFactory() {            @Override            protected TomcatWebServer getTomcatWebServer(Tomcat tomcat) {                tomcat.enableNaming(); //启用默认禁用的JNDI命名                return super.getTomcatWebServer(tomcat);            }            //数据库配置信息可以配置在文件中,数据库发生变动,只需修改配置文件,而不用修改代码.            @Override            protected void postProcessContext(Context context) {                ContextResource resource = new ContextResource();                resource.setName("jdbcMydb");                resource.setType(DataSource.class.getName());                resource.setProperty("driverClassName", "com.mysql.jdbc.Driver");                resource.setProperty("url", "jdbc:mysql://127.0.0.1:3306/test");                resource.setProperty("username", "root");                resource.setProperty("password","root1234");                context.getNamingResources().addResource(resource);            }        };        return tomcatServletWebServerFactory;    }    @Bean    public DataSource jndiDataSource() throws IllegalArgumentException,            NamingException {        JndiObjectFactoryBean bean = new JndiObjectFactoryBean();           // create JNDI data source        bean.setJndiName("java:/comp/env/jdbcMydb");  // jndiDataSource is name of JNDI data source        bean.setProxyInterface(DataSource.class);        bean.setLookupOnStartup(true);        bean.afterPropertiesSet();        return (DataSource) bean.getObject();    }}

MysqlTest.java

package com.rumenz;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.boot.ApplicationArguments;import org.springframework.boot.ApplicationRunner;import org.springframework.boot.CommandLineRunner;import org.springframework.context.ApplicationContext;import org.springframework.stereotype.Component;import javax.naming.Context;import javax.naming.InitialContext;import javax.naming.NamingException;import javax.sql.DataSource;import java.sql.Connection;import java.sql.ResultSet;import java.sql.Statement;@Componentpublic class MysqlTest implements ApplicationRunner {    public static DataSource dataSource = null;   static {       Context context = null;       try {           context = new InitialContext();       } catch (NamingException e) {           e.printStackTrace();       }       //根据资源名称搜索       try {           dataSource = (DataSource)context.lookup("java:/comp/env/jdbcMydb");       } catch (NamingException e) {           e.printStackTrace();       }       System.out.println("static-----");   }    public void run(ApplicationArguments args) throws Exception {        System.out.println("run---------");        Statement stmt = null;        try {            Connection conn = dataSource.getConnection();            //查询            stmt = conn.createStatement();            String sql = "SELECT id,name FROM qq limit 1";            ResultSet rs = stmt.executeQuery(sql);            while(rs.next()){                int id  = rs.getInt("id");                String name = rs.getString("name");                System.out.print("id: " + id);                System.out.println(", name: " + name);            }            rs.close();            stmt.close();            conn.close();        } catch (Exception e) {          e.printStackTrace();        }    }}

源码:https://github.com/mifunc/spr...

2.Springboot WAR 使用JNDI

打包成war包放到tomcat,需要修改tomcat/conf/context.xml和tomcat/conf/server.xml

tomcat/conf/context.xml

<ResourceLink name="jdbcMydb"                global="jdbcMydb"                auth="Container"                type="javax.sql.DataSource" />

tomcat/conf/server.xml

<Resource name="jdbcMydb"          global="jdbcMydb"          auth="Container"           type="javax.sql.DataSource"           driverClassName="com.mysql.jdbc.Driver"           url="jdbc:mysql://localhost:3306/test"          username="root"          password="root1234"          maxActive="100"           maxIdle="20"           minIdle="5"           maxWait="10000"/>

业务代码

JNDIController.java

package com.rumenz.controller;import java.sql.Connection;import java.sql.ResultSet;import java.sql.SQLException;import java.sql.Statement;import javax.sql.DataSource;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RestController;@RestControllerpublic class JNDIController {    @Autowired    private DataSource dataSource;        @GetMapping("/test")    public String test() {        try {            Connection conn = dataSource.getConnection();            Statement stmt = conn.createStatement();            String sql = "SELECT id,name FROM qq limit 1";            ResultSet rs = stmt.executeQuery(sql);            while(rs.next()){                int id  = rs.getInt("id");                String name = rs.getString("name");                System.out.print("id: " + id);                System.out.println(", name: " + name);            }            rs.close();            stmt.close();            conn.close();        } catch (SQLException e) {            e.printStackTrace();        }        return null;    }}

源码:https://github.com/mifunc/Spr...

java.beans.beancontext.BeanContext(单一类型依赖查找/集合类型依赖查找)

  • 单一类型依赖查找

    • java.beans.beancontext.BeanContextServicesSupport#getService
  • 集合类型依赖查找

    • java.beans.beancontext.BeanContextServicesSupport#getCurrentServiceSelectors

层析性依赖查找

多个BeanContext相互为父子关系. 一个service的依赖有可能在多个BeanContext