当前位置: 首页 > news >正文

老区建设网站网络营销做得好的酒店

老区建设网站,网络营销做得好的酒店,网站被降权会发生什么,宁夏网站建设电话小伙伴们知道,当我们使用 Spring 容器的时候,如果遇到一些特殊的 Bean,一般来说可以通过如下三种方式进行配置: 静态工厂方法实例工厂方法FactoryBean 不过从 Spring5 开始,在 AbstractBeandefinition 类中多了一个属…

小伙伴们知道,当我们使用 Spring 容器的时候,如果遇到一些特殊的 Bean,一般来说可以通过如下三种方式进行配置:

  • 静态工厂方法
  • 实例工厂方法
  • FactoryBean

不过从 Spring5 开始,在 AbstractBeandefinition 类中多了一个属性,对于特殊的 Bean 我们有了更多的选择:

/*** Specify a callback for creating an instance of the bean,* as an alternative to a declaratively specified factory method.* <p>If such a callback is set, it will override any other constructor* or factory method metadata. However, bean property population and* potential annotation-driven injection will still apply as usual.* @since 5.0* @see #setConstructorArgumentValues(ConstructorArgumentValues)* @see #setPropertyValues(MutablePropertyValues)*/
public void setInstanceSupplier(@Nullable Supplier<?> instanceSupplier) {this.instanceSupplier = instanceSupplier;
}/*** Return a callback for creating an instance of the bean, if any.* @since 5.0*/
@Nullable
public Supplier<?> getInstanceSupplier() {return this.instanceSupplier;
}

接下来松哥就来和大家简单聊一聊这个话题。

1. 传统解决方案

1.1 问题

不知道各位小伙伴们有没有用过 OkHttp,这是一个专门做网络请求的工具,在微服务的 HTTP 调用组件中,我们可以配置底层使用 OkHttp 这个工具。

一般来说,如果我们想直接使用 OkHttp,代码如下:

OkHttpClient client = new OkHttpClient.Builder().connectTimeout(5, TimeUnit.SECONDS).readTimeout(5, TimeUnit.SECONDS).build();
Request getReq = new Request.Builder().get().url("http://www.javaboy.org").build();
Call call = client.newCall(getReq);
call.enqueue(new Callback() {@Overridepublic void onFailure(@NotNull Call call, @NotNull IOException e) {System.out.println("e.getMessage() = " + e.getMessage());}@Overridepublic void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {System.out.println("response.body().string() = " + response.body().string());}
});

先通过建造者模式创建出来一个 OkHttpClient 对象,然后还是建造者模式创建出来 Request 对象,接下来去发送请求就可以了。那么对于这样的代码,我们可以将 OkHttpClient 对象交由 Spring 容器统一管理,那么该如何将 OkHttpClient 注册到 Spring 容器中呢?

1.2 静态工厂方法

首先可以采用静态工厂方法,也就是工厂方法是一个静态方法,如下:

public class OkHttpStaticFactory {private static OkHttpClient okHttpClient;static {okHttpClient = new OkHttpClient.Builder().connectTimeout(5, TimeUnit.SECONDS).readTimeout(5, TimeUnit.SECONDS).build();}public static OkHttpClient getOkHttpClient() {return okHttpClient;}
}

然后在 Spring 配置文件中进行注入:

<bean class="org.javaboy.bean.OkHttpStaticFactory" factory-method="getOkHttpClient" id="httpClient"/>

静态工厂的特点是静态方法可以直接调用,并必须要获取到工厂类的实例,所以上面配置的时候只需要指定 factory-method 就可以了。

这就可以了,将来我们去 Spring 容器中查找一个名为 httpClient 的对象,拿到手的就是 OkHttpClient 了。

1.3 实例工厂方法

实例工厂方法意思就是说工厂方法是一个实例方法。如下:

public class OkHttpInstanceFactory {private volatile static OkHttpClient okHttpClient;public OkHttpClient getInstance() {if (okHttpClient == null) {synchronized (OkHttpInstanceFactory.class) {if (okHttpClient == null) {okHttpClient = new OkHttpClient.Builder().connectTimeout(5, TimeUnit.SECONDS).readTimeout(5, TimeUnit.SECONDS).build();}}}return okHttpClient;}
}

这是一个简单的单例模式。但是这里的工厂方法是一个实例方法,实例方法的调用必须得先获取到对象然后才能调用实例方法,因此配置方式如下:

<bean class="org.javaboy.bean.OkHttpInstanceFactory" id="httpInstanceFactory"/>
<bean factory-bean="httpInstanceFactory" factory-method="getInstance" id="httpClient"/>

好啦,接下来我们就可以去 Spring 容器中获取一个名为 httpClient 的对象了,拿到手的就是 OkHttpClient 实例。

1.4 FactoryBean

当然,也可以通过 FactoryBean 来解决上述问题,FactoryBean 松哥在之前的文章中刚刚和大家介绍过,我们来看下:

public class OkHttpClientFactoryBean implements FactoryBean<OkHttpClient> {@Overridepublic OkHttpClient getObject() throws Exception {return new OkHttpClient.Builder().connectTimeout(5, TimeUnit.SECONDS).readTimeout(5, TimeUnit.SECONDS).build();}@Overridepublic Class<?> getObjectType() {return OkHttpClient.class;}@Overridepublic boolean isSingleton() {return true;}
}

最后在 Spring 中配置即可:

<bean class="org.javaboy.bean.OkHttpClientFactoryBean" id="httpClient"/>

这个就不做过多解释了,不熟悉的小伙伴可以翻看前面的文章。

上面这三种方案都是传统方案。

特别是前两种,其实我们用的比较少,前两种有一个缺陷,就是我们配置的的 factory-method 都是通过反射来调用的,通过反射调用的话,多多少少性能受点影响。

这种 factory-method 在 Spring 中处理的源码执行时序图如下:

所以最终反射是在 SimpleInstantiationStrategy#instantiate 方法中执行的,就是大家非常熟悉的反射代码了:

@Override
public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner,@Nullable Object factoryBean, final Method factoryMethod, Object... args) {ReflectionUtils.makeAccessible(factoryMethod);Method priorInvokedFactoryMethod = currentlyInvokedFactoryMethod.get();try {currentlyInvokedFactoryMethod.set(factoryMethod);Object result = factoryMethod.invoke(factoryBean, args);if (result == null) {result = new NullBean();}return result;}finally {if (priorInvokedFactoryMethod != null) {currentlyInvokedFactoryMethod.set(priorInvokedFactoryMethod);}else {currentlyInvokedFactoryMethod.remove();}}
}

好了,这是传统的解决方案。

2. Spring5 解决方案

Spring5 中开始提供了 Supplier,可以通过接口回调获取到一个 Bean 的实例,这种方式显然性能更好一些。

如下:

AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
GenericBeanDefinition definition = new GenericBeanDefinition();
definition.setBeanClass(Book.class);
definition.setInstanceSupplier((Supplier<Book>) () -> {Book book = new Book();book.setName("深入浅出 Spring Security");book.setAuthor("江南一点雨");return book;
});
ctx.registerBeanDefinition("b1", definition);
ctx.refresh();
Book b = ctx.getBean("b1", Book.class);
System.out.println("b = " + b);

关键就是通过调用 BeanDefinition 的 setInstanceSupplier 方法去设置回调。当然,上面这段代码还可以通过 Lambda 进一步简化:

public class BookSupplier {public Book getBook() {Book book = new Book();book.setName("深入浅出 Spring Security");book.setAuthor("江南一点雨");return book;}
}

然后调用这个方法即可:

AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
GenericBeanDefinition definition = new GenericBeanDefinition();
definition.setBeanClass(Book.class);
BookSupplier bookSupplier = new BookSupplier();
definition.setInstanceSupplier(bookSupplier::getBook);
ctx.registerBeanDefinition("b1", definition);
ctx.refresh();
Book b = ctx.getBean("b1", Book.class);
System.out.println("b = " + b);

这是不是更有一点 Lambda 的感觉了~

在 Spring 源码中,处理获取 Bean 实例的时候,有如下一个分支,就是处理 Supplier 这种情况的:

AbstractAutowireCapableBeanFactory#createBeanInstance

protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {// Make sure bean class is actually resolved at this point.Class<?> beanClass = resolveBeanClass(mbd, beanName);if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {throw new BeanCreationException(mbd.getResourceDescription(), beanName,"Bean class isn't public, and non-public access not allowed: " + beanClass.getName());}Supplier<?> instanceSupplier = mbd.getInstanceSupplier();if (instanceSupplier != null) {return obtainFromSupplier(instanceSupplier, beanName);}if (mbd.getFactoryMethodName() != null) {return instantiateUsingFactoryMethod(beanName, mbd, args);}//...return instantiateBean(beanName, mbd);
}@Nullable
private Object obtainInstanceFromSupplier(Supplier<?> supplier, String beanName) {String outerBean = this.currentlyCreatedBean.get();this.currentlyCreatedBean.set(beanName);try {if (supplier instanceof InstanceSupplier<?> instanceSupplier) {return instanceSupplier.get(RegisteredBean.of((ConfigurableListableBeanFactory) this, beanName));}if (supplier instanceof ThrowingSupplier<?> throwableSupplier) {return throwableSupplier.getWithException();}return supplier.get();}
}

上面 obtainFromSupplier 这个方法,最终会调用到第二个方法。第二个方法中的 supplier.get(); 其实最终就调用到我们自己写的 getBook 方法了。

好啦,这是从 Spring5 开始结合 Lamdba 的一种 Bean 注入方式,感兴趣的小伙伴可以试试哦~

http://www.hengruixuexiao.com/news/23179.html

相关文章:

  • 有什么网站做的比较高大上推广普通话内容100字
  • 基于iview的网站开发模板青岛seo网站排名优化
  • 厦门做网站公司哪家好上热门最火标题
  • 厦门市网站建设软件开发公司怎么样拓展客户资源
  • 手机网站和电脑网站的区别广州网络推广培训
  • 山东泰安泰山区疫情最新消息上海关键词排名优化价格
  • 怎么做游戏门户网站免费营销培训
  • 海口房产网站建设杭州网站seo优化
  • 国内网站开发平台哪家强三亚百度推广开户
  • 做视频找素材的网站有哪些宁波seo网络推广咨询价格
  • 梅州市住房和城乡建设局官方网站关键词网站排名查询
  • 丹东有做公司网站的吗推广普通话手抄报简单
  • 怎么制作自己的免费网站百度下载安装免费版
  • 图库网站源码下载seo百度快速排名
  • 自己做社交网站吗磁力多多
  • 如何找外包网站来做如何建立一个网站平台
  • 关于网站建设的电话销售话术网络推广项目计划书
  • 最简单的cms网站怎么做今日重大新闻事件
  • 武汉网站建设哪家好目前主流搜索引擎是哪种
  • 编辑目录中的字体wordpressseo网络推广课程
  • 网站建设南通谷歌seo网站推广怎么做
  • 北京建设银行招聘网站百度竞价课程
  • 网站专题页面用什么做seo关键词排名优
  • 做网站需要哪种工程师关键少数
  • 南京建筑人才招聘网360优化关键词
  • 太平洋网站开发北京网站建设公司优势
  • 建站公司生存难自媒体平台收益排行榜
  • wordpress如何导入模板数据库西安seo培训
  • 手机网站设计需要学什么企业管理软件
  • 分销商城小程序百色seo外包