001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.juneau.commons.function; 018/** 019 * A universal factory interface used with <ja>@Marshalled</ja><c>(factory=X.class)</c> for any bean type the 020 * framework needs to instantiate. 021 * 022 * <p> 023 * This interface provides a single DI hook for all framework-managed classes including 024 * {@link BeanConsumer}, {@link BeanSupplier}, {@link BeanChannel}, {@code ObjectSwap} subclasses, 025 * and any ordinary bean class parsed from JSON/XML/etc. 026 * 027 * <p> 028 * When a class annotated with <ja>@Marshalled</ja><c>(factory=MyFactory.class)</c> needs to be instantiated, 029 * the framework resolves the factory as follows: 030 * <ol> 031 * <li>Look up the factory class in the {@code BeanStore} (e.g. Spring {@code ApplicationContext}) 032 * <li>If not found in the store, attempt to instantiate the factory directly via no-arg constructor 033 * or {@code getInstance()} static method 034 * <li>If both fail, throw {@link IllegalArgumentException} 035 * </ol> 036 * 037 * <h5 class='section'>Example (Spring integration):</h5> 038 * <p class='bjava'> 039 * <jc>// Spring singleton factory that creates per-request ItemChannel instances</jc> 040 * <ja>@Component</ja> 041 * <jk>public class</jk> ItemChannelFactory <jk>implements</jk> BeanFactory<ItemChannel> { 042 * <ja>@Autowired</ja> DataSource <jv>ds</jv>; 043 * 044 * <ja>@Override</ja> 045 * <jk>public</jk> ItemChannel create() { 046 * <jk>return new</jk> ItemChannel(<jv>ds</jv>); 047 * } 048 * } 049 * 050 * <jc>// The target class declares which factory creates it</jc> 051 * <ja>@Marshalled</ja>(factory=ItemChannelFactory.<jk>class</jk>) 052 * <jk>public class</jk> ItemChannel <jk>implements</jk> BeanChannel<Item> { ... } 053 * </p> 054 * 055 * <h5 class='section'>See Also:</h5><ul> 056 * <li class='jc'>{@link BeanConsumer} - Parse-only lifecycle interface 057 * <li class='jc'>{@link BeanSupplier} - Serialize-only lifecycle interface 058 * <li class='jc'>{@link BeanChannel} - Round-trip lifecycle interface 059 * <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/Marshalling">Marshalling</a> 060 * </ul> 061 * 062 * @param <T> The type of bean this factory creates. 063 */ 064@FunctionalInterface 065public interface BeanFactory<T> { 066 067 /** 068 * Creates a new instance of the bean. 069 * 070 * @return A new bean instance. 071 * @throws Exception If the bean cannot be created. 072 */ 073 @SuppressWarnings({ 074 "java:S112" // Functional-interface factory hook: implementations (e.g. Spring factory methods) must be free to throw any checked exception. 075 }) 076 T create() throws Exception; 077 078 /** 079 * Sentinel class used as the default value for {@code @BeanType(factory=...)} and 080 * {@code @BeanProp(factory=...)} when no factory is specified. 081 */ 082 @SuppressWarnings({ 083 "java:S9398", // Public API annotation-default sentinel; moving it breaks adopters. 084 "rawtypes" // Raw type required for use as annotation sentinel 085 }) 086 final class Void implements BeanFactory { 087 private Void() {} 088 089 @Override 090 public Object create() { 091 throw new UnsupportedOperationException("BeanFactory.Void is a sentinel and cannot be instantiated."); 092 } 093 } 094}