当前位置: 首页 > 软件库 > Web应用开发 > Web框架 >

Today Context

轻量级依赖注入框架
授权协议 GPL
开发语言 Java
所属分类 Web应用开发、 Web框架
软件类型 开源软件
地区 国产
投 递 者 长孙淳
操作系统 跨平台
开源组织
适用人群 未知
 软件概览

TODAY Context 是一个轻量级依赖注入框架。

使用说明

标识一个Bean

  • 使用@Component
  • 任意注解只要注解上有@Component注解就会标识为一个Bean不论多少层
@Target({ ElementType.TYPE, ElementType.METHOD })
public @interface Component {
    /** @return bean name */
    String[] value() default {};

    /** @return bean's scope */
    Scope scope() default Scope.SINGLETON;

    String[] initMethods() default {};

    String[] destroyMethods() default {};

}

@Singleton

@Component(scope = Scope.SINGLETON)
@Target({ ElementType.TYPE, ElementType.METHOD })
public @interface Singleton {

    // bean name
    String[] value() default {};

    String[] initMethods() default {};

    String[] destroyMethods() default {};
}

@Prototype

@Retention(RetentionPolicy.RUNTIME)
@Component(scope = Scope.PROTOTYPE)
@Target({ ElementType.TYPE, ElementType.METHOD })
public @interface Prototype {

    // bean name
    String[] value() default {};

    String[] initMethods() default {};

    String[] destroyMethods() default {};
}

@Configuration

@Target(ElementType.TYPE)
@Component(scope = Scope.SINGLETON)
public @interface Configuration {

}

@Service

@Component(scope = Scope.SINGLETON)
@Target({ ElementType.TYPE, ElementType.METHOD })
public @interface Service {

    String[] value() default {};// bean names
}

注入Bean

  • 使用@Autowired注入
  • 使用@Resource注入
  • 使用@Inject注入
  • 可自定义注解和实现PropertyValueResolver
@FunctionalInterface
public interface PropertyValueResolver {

    default boolean supports(Field field) {
        return false;
    }
    PropertyValue resolveProperty(Field field) throws ContextException;
}
  • 注入示例:
@Controller
@SuppressWarnings("serial")
public class LoginController implements Constant, ServletContextAware {

    private String contextPath;
    @Autowired
    private UserService userService;
    //@Inject
    @Resource
    private BloggerService bloggerService;

    @GET("/login")
    public String login(@Cookie String email, String forward, Model model) {

        model.attribute(KEY_EMAIL, email);
        model.attribute("forward", forward);

        return "/login/index";
    }

    @POST("/login")
    @Logger(value = "登录", //
            content = "email:[${email}] " //
                    + "passwd:[${passwd}] "//
                    + "input code:[${randCode}] "//
                    + "in session:[${randCodeInSession}] "//
                    + "forward to:[${forward}] "//
                    + "msg:[${redirectModel.attribute('msg')}]"//
    )
    public String login(HttpSession session,
            @Cookie(KEY_EMAIL) String emailInCookie,
            @RequestParam(required = true) String email,
            @RequestParam(required = true) String passwd,
            @RequestParam(required = true) String randCode,
            @RequestParam(required = false) String forward,
            @Session(RAND_CODE) String randCodeInSession, RedirectModel redirectModel) //
    {
        session.removeAttribute(RAND_CODE);

        if (!randCode.equalsIgnoreCase(randCodeInSession)) {
            redirectModel.attribute(KEY_MSG, "验证码错误!");
            redirectModel.attribute(KEY_EMAIL, email);
            redirectModel.attribute(KEY_FORWARD, forward);
            return redirectLogin(forward);
        }

        User loginUser = userService.login(new User().setEmail(email));
        if (loginUser == null) {
            redirectModel.attribute(KEY_EMAIL, email);
            redirectModel.attribute(KEY_FORWARD, forward);
            redirectModel.attribute(KEY_MSG, email + " 账号不存在!");
            return redirectLogin(forward);
        }
     // �� 略
    }
    @GET("/logout")
    public String logout(HttpSession session) {
        session.invalidate();
        return "redirect:/index";
    }

    @Override
    public void setServletContext(ServletContext servletContext) {
        this.contextPath = servletContext.getContextPath();
    }
}
  • 实现原理
public class AutowiredPropertyResolver implements PropertyValueResolver {

    private static final Class<? extends Annotation> NAMED_CLASS = ClassUtils.loadClass("javax.inject.Named");
    private static final Class<? extends Annotation> INJECT_CLASS = ClassUtils.loadClass("javax.inject.Inject");

    @Override
    public boolean supports(Field field) {
        return field.isAnnotationPresent(Autowired.class)
                || field.isAnnotationPresent(Resource.class)
                || (NAMED_CLASS != null && field.isAnnotationPresent(NAMED_CLASS))
                || (INJECT_CLASS != null && field.isAnnotationPresent(INJECT_CLASS));
    }
    
    @Override
	public PropertyValue resolveProperty(Field field) {
	
	    final Autowired autowired = field.getAnnotation(Autowired.class); // auto wired
	
	    String name = null;
	    boolean required = true;
	    final Class<?> propertyClass = field.getType();
	
	    if (autowired != null) {
	        name = autowired.value();
	        required = autowired.required();
	    }
	    else if (field.isAnnotationPresent(Resource.class)) {
	        name = field.getAnnotation(Resource.class).name(); // Resource.class
	    }
	    else if (NAMED_CLASS != null && field.isAnnotationPresent(NAMED_CLASS)) {// @Named
	        name = ClassUtils.getAnnotationAttributes(NAMED_CLASS, field).getString(Constant.VALUE);
	    } // @Inject or name is empty
	
	    if (StringUtils.isEmpty(name)) {
	        name = byType(propertyClass);
	    }
	
	    return new PropertyValue(new BeanReference(name, required, propertyClass), field);
	}
}

看到这你应该明白了注入原理了

使用@Autowired构造器注入

// cn.taketoday.web.servlet.DispatcherServlet
public class DispatcherServlet implements Servlet, Serializable {

    private static final Logger log = LoggerFactory.getLogger(DispatcherServlet.class);

    /** exception resolver */
    private final ExceptionResolver exceptionResolver;
    /** Action mapping registry */
    private final HandlerMappingRegistry handlerMappingRegistry;
    /** intercepter registry */
    private final HandlerInterceptorRegistry handlerInterceptorRegistry;

    private final WebServletApplicationContext applicationContext;

    private ServletConfig servletConfig;

    @Autowired
    public DispatcherServlet(//
            ExceptionResolver exceptionResolver, //
            HandlerMappingRegistry handlerMappingRegistry, //
            WebServletApplicationContext applicationContext,
            HandlerInterceptorRegistry handlerInterceptorRegistry) //
    {
        if (exceptionResolver == null) {
            throw new ConfigurationException("You must provide an 'exceptionResolver'");
        }
        this.exceptionResolver = exceptionResolver;

        this.applicationContext = applicationContext;
        this.handlerMappingRegistry = handlerMappingRegistry;
        this.handlerInterceptorRegistry = handlerInterceptorRegistry;
    }

    public static RequestContext prepareContext(final ServletRequest request, final ServletResponse response) {
        return RequestContextHolder.prepareContext(//
                new ServletRequestContext((HttpServletRequest) request, (HttpServletResponse) response)//
        );
    }

    @Override
    public void service(final ServletRequest req, final ServletResponse res) //
            throws ServletException, IOException //
    {
        // Lookup handler mapping
        final HandlerMapping mapping = lookupHandlerMapping((HttpServletRequest) req);

        if (mapping == null) {
            ((HttpServletResponse) res).sendError(404);
            return;
        }

        final RequestContext context = prepareContext(req, res);
        try {

            final Object result;
            // Handler Method
            final HandlerMethod method;// = requestMapping.getHandlerMethod();
            if (mapping.hasInterceptor()) {
                // get intercepter s
                final int[] its = mapping.getInterceptors();
                // invoke intercepter
                final HandlerInterceptorRegistry registry = getHandlerInterceptorRegistry();
                for (final int i : its) {
                    if (!registry.get(i).beforeProcess(context, mapping)) {
                        if (log.isDebugEnabled()) {
                            log.debug("Interceptor: [{}] return false", registry.get(i));
                        }
                        return;
                    }
                }
                result = invokeHandler(context, method = mapping.getHandlerMethod(), mapping);
                for (final int i : its) {
                    registry.get(i).afterProcess(context, mapping, result);
                }
            }
            else {
                result = invokeHandler(context, method = mapping.getHandlerMethod(), mapping);
            }

            method.resolveResult(context, result);
        }
        catch (Throwable e) {
            ResultUtils.resolveException(context, exceptionResolver, mapping, e);
        }
    }

    protected Object invokeHandler(final RequestContext request,
            final HandlerMethod method, final HandlerMapping mapping) throws Throwable //
    {
        // log.debug("set parameter start");
        return method.getMethod()//
                .invoke(mapping.getBean(), method.resolveParameters(request)); // invoke
    }

    protected HandlerMapping lookupHandlerMapping(final HttpServletRequest req) {
        // The key of handler
        String uri = req.getMethod() + req.getRequestURI();

        final HandlerMappingRegistry registry = getHandlerMappingRegistry();
        final Integer i = registry.getIndex(uri); // index of handler mapping
        if (i == null) {
            // path variable
            uri = StringUtils.decodeUrl(uri);// decode
            for (final RegexMapping regex : registry.getRegexMappings()) {
                // TODO path matcher pathMatcher.match(requestURI, requestURI)
                if (regex.pattern.matcher(uri).matches()) {
                    return registry.get(regex.index);
                }
            }
            log.debug("NOT FOUND -> [{}]", uri);
            return null;
        }
        return registry.get(i.intValue());
    }

    @Override
    public void init(ServletConfig servletConfig) throws ServletException {
        this.servletConfig = servletConfig;
    }

    @Override
    public ServletConfig getServletConfig() {
        return servletConfig;
    }

    public String getServletName() {
        return "DispatcherServlet";
    }

    @Override
    public String getServletInfo() {
        return "DispatcherServlet, Copyright © TODAY & 2017 - 2019 All Rights Reserved";
    }

    @Override
    public void destroy() {

        if (applicationContext != null) {
            final State state = applicationContext.getState();

            if (state != State.CLOSING && state != State.CLOSED) {

                applicationContext.close();

                final DateFormat dateFormat = new SimpleDateFormat(Constant.DEFAULT_DATE_FORMAT);//
                final String msg = new StringBuffer()//
                        .append("Your application destroyed at: [")//
                        .append(dateFormat.format(new Date()))//
                        .append("] on startup date: [")//
                        .append(dateFormat.format(applicationContext.getStartupDate()))//
                        .append("]")//
                        .toString();

                log.info(msg);
                applicationContext.getServletContext().log(msg);
            }
        }
    }

    public final HandlerInterceptorRegistry getHandlerInterceptorRegistry() {
        return this.handlerInterceptorRegistry;
    }

    public final HandlerMappingRegistry getHandlerMappingRegistry() {
        return this.handlerMappingRegistry;
    }

    public final ExceptionResolver getExceptionResolver() {
        return this.exceptionResolver;
    }

}
//cn.taketoday.web.view.FreeMarkerViewResolver

@Props(prefix = "web.mvc.view.")
@MissingBean(value = Constant.VIEW_RESOLVER, type = ViewResolver.class)
public class FreeMarkerViewResolver extends AbstractViewResolver implements InitializingBean, WebMvcConfiguration {

    private final ObjectWrapper wrapper;

    @Getter
    private final Configuration configuration;
    private final TaglibFactory taglibFactory;
    private final TemplateLoader templateLoader;
    private final ServletContextHashModel applicationModel;

    public FreeMarkerViewResolver(Configuration configuration, //
            TaglibFactory taglibFactory, TemplateLoader templateLoader, Properties settings) //
    {
        this(new DefaultObjectWrapper(Configuration.VERSION_2_3_28), //
                configuration, taglibFactory, templateLoader, settings);
    }

    @Autowired
    public FreeMarkerViewResolver(//
            @Autowired(required = false) ObjectWrapper wrapper, //
            @Autowired(required = false) Configuration configuration, //
            @Autowired(required = false) TaglibFactory taglibFactory, //
            @Autowired(required = false) TemplateLoader templateLoader, //
            @Props(prefix = "freemarker.", replace = true) Properties settings) //
    {

        WebServletApplicationContext webApplicationContext = //
                (WebServletApplicationContext) WebUtils.getWebApplicationContext();

        if (configuration == null) {
            configuration = new Configuration(Configuration.VERSION_2_3_28);
            webApplicationContext.registerSingleton(configuration.getClass().getName(), configuration);
        }

        this.configuration = configuration;
        if (wrapper == null) {
            wrapper = new DefaultObjectWrapper(Configuration.VERSION_2_3_28);
        }
        this.wrapper = wrapper;
        ServletContext servletContext = webApplicationContext.getServletContext();
        if (taglibFactory == null) {
            taglibFactory = new TaglibFactory(servletContext);
        }
        this.taglibFactory = taglibFactory;
        this.configuration.setObjectWrapper(wrapper);
        // Create hash model wrapper for servlet context (the application)
        this.applicationModel = new ServletContextHashModel(servletContext, wrapper);

        webApplicationContext.getBeansOfType(TemplateModel.class).forEach(configuration::setSharedVariable);

        this.templateLoader = templateLoader;
        try {
            if (settings != null && !settings.isEmpty()) {
                this.configuration.setSettings(settings);
            }
        }
        catch (TemplateException e) {
            throw new ConfigurationException("Set FreeMarker's Properties Error, With Msg: [" + e.getMessage() + "]", e);
        }
    }

    /**
     * Use {@link afterPropertiesSet}
     * 
     * @since 2.3.3
     */
    @Override
    public void afterPropertiesSet() throws ConfigurationException {

        this.configuration.setLocale(locale);
        this.configuration.setDefaultEncoding(encoding);
        if (templateLoader == null) {
            this.configuration.setServletContextForTemplateLoading(servletContext, prefix); // prefix -> /WEB-INF/..
        }
        else {
            configuration.setTemplateLoader(templateLoader);
        }
        LoggerFactory.getLogger(getClass()).info("Configuration FreeMarker View Resolver Success.");
    }

    @Override
    public void configureParameterResolver(List<ParameterResolver> resolvers) {

        resolvers.add(new DelegatingParameterResolver((m) -> m.isAssignableFrom(Configuration.class), //
                (ctx, m) -> configuration//
        ));

        resolvers.add(new DelegatingParameterResolver((m) -> m.isAnnotationPresent(SharedVariable.class), (ctx, m) -> {
            final TemplateModel sharedVariable = configuration.getSharedVariable(m.getName());

            if (m.isInstance(sharedVariable)) {
                return sharedVariable;
            }

            if (sharedVariable instanceof WrapperTemplateModel) {
                final Object wrappedObject = ((WrapperTemplateModel) sharedVariable).getWrappedObject();
                if (m.isInstance(wrappedObject)) {
                    return wrappedObject;
                }
                throw ExceptionUtils.newConfigurationException(null, "Not a instance of: " + m.getParameterClass());
            }
            return null;
        }));

    }

    /**
     * Create Model Attributes.
     * 
     * @param requestContext
     *            Current request context
     * @return {@link TemplateHashModel}
     */
    protected TemplateHashModel createModel(RequestContext requestContext) {
        final ObjectWrapper wrapper = this.wrapper;

        final HttpServletRequest request = requestContext.nativeRequest();

        final AllHttpScopesHashModel allHttpScopesHashModel = //
                new AllHttpScopesHashModel(wrapper, servletContext, request);

        allHttpScopesHashModel.putUnlistedModel(FreemarkerServlet.KEY_JSP_TAGLIBS, taglibFactory);
        allHttpScopesHashModel.putUnlistedModel(FreemarkerServlet.KEY_APPLICATION, applicationModel);
        // Create hash model wrapper for request
        allHttpScopesHashModel.putUnlistedModel(FreemarkerServlet.KEY_REQUEST, new HttpRequestHashModel(request, wrapper));
        allHttpScopesHashModel.putUnlistedModel(FreemarkerServlet.KEY_REQUEST_PARAMETERS, new HttpRequestParametersHashModel(request));
        // Create hash model wrapper for session
        allHttpScopesHashModel.putUnlistedModel(FreemarkerServlet.KEY_SESSION,
                new HttpSessionHashModel(requestContext.nativeSession(), wrapper));

        return allHttpScopesHashModel;
    }

    /**
     * Resolve FreeMarker View.
     */
    @Override
    public void resolveView(final String template, final RequestContext requestContext) throws Throwable {

        configuration.getTemplate(template + suffix, locale, encoding)//
                .process(createModel(requestContext), requestContext.getWriter());
    }
}

使用@Props 注入Properties或Bean

  • 构造器
@Autowired
    public PropsBean(@Props(prefix = "site.") Bean bean) {
       //---------
    }
    @Autowired
    public PropsBean(@Props(prefix = "site.") Properties properties) {
        //-------
    }
    @Autowired
    public PropsBean(@Props(prefix = "site.") Map properties) {
        //-------
    }
  • Field
@Props(prefix = "site.")
    Bean bean;
    @Props(prefix = "site.")
    Map properties;
    @Props(prefix = "site.") 
    Properties properties
  • 实现原理
@Order(Ordered.HIGHEST_PRECEDENCE - 2)
public class PropsPropertyResolver implements PropertyValueResolver {

    @Override
    public boolean supports(Field field) {
        return field.isAnnotationPresent(Props.class);
    }

}

使用@Value 支持EL表达式

  • @Props一样同样支持构造器,Field注入
  • #{key} 和Environment#getProperty(String key, Class targetType)效果一样
  • ${1+1} 支持EL表达式
@Configuration
public class WebMvc implements WebMvcConfiguration {

    private final String serverPath;

    @Autowired
    public WebMvc(@Value("#{site.serverPath}") String serverPath) {
        this.serverPath = serverPath;
    }
    @Override
    public void configureResourceMappings(ResourceMappingRegistry registry) {

        registry.addResourceMapping("/assets/**")//
//                .enableGzip()//
//                .gzipMinLength(10240)//
                // G:\Projects\Git\today-technology\blog
                .addLocations("file:///G:/Projects/Git/today-technology/blog/blog-web/src/main/webapp/assets/");

        registry.addResourceMapping("/webjars/**")//
                .addLocations("classpath:/META-INF/resources/webjars/");

        registry.addResourceMapping("/swagger/**")//
                .cacheControl(CacheControl.newInstance().publicCache())//
                .addLocations("classpath:/META-INF/resources/");

        registry.addResourceMapping("/upload/**")//
                .addLocations("file:///" + serverPath + "/upload/");

        registry.addResourceMapping("/favicon.ico")//
                .addLocations("classpath:/favicon.ico")//
                .cacheControl(CacheControl.newInstance().publicCache());

        registry.addResourceMapping(AdminInterceptor.class)//
                .setPathPatterns("/assets/admin/**")//
                .setOrder(Ordered.HIGHEST_PRECEDENCE)//
                .addLocations("file:///G:/Projects/Git/today-technology/blog/blog-web/src/main/webapp/assets/admin/");
    
    }
}

@Configuration注解

该注解标识一个配置Bean,示例:

@Configuration
@Props(prefix = { "redis.pool.", "redis." })
public class RedisConfiguration {

    private int maxIdle;
    private int minIdle;
    private int timeout;
    private int maxTotal;

    private int database;
    private String address;

    private String password;
    private String clientName;

    private int connectTimeout;

    @Singleton("fstCodec")
    public Codec codec() {
        return new FstCodec();
    }
//  @Singleton("limitLock")
//  public Lock limitLock(Redisson redisson) {
//      return redisson.getLock("limitLock");
//  }

    @Singleton(destroyMethods = "shutdown")
    public Redisson redisson(@Autowired("fstCodec") Codec codec) {
        Config config = new Config();
        config.setCodec(codec)//
                .useSingleServer()//
                .setAddress(address)//
                .setTimeout(timeout)//
                .setPassword(password)//
                .setDatabase(database)//
                .setClientName(clientName)//
                .setConnectionPoolSize(maxTotal)//
                .setConnectTimeout(connectTimeout)//
                .setConnectionMinimumIdleSize(minIdle)//
                .setConnectionMinimumIdleSize(maxIdle);

        return (Redisson) Redisson.create(config);
    }

    @Singleton("loggerDetails")
    public <T> Queue<T> loggerDetails(Redisson redisson) {
        return new ConcurrentLinkedQueue<T>();
    }

    @Singleton("cacheViews")
    public Map<Long, Long> cacheViews(Redisson redisson) {
        return redisson.getMap("cacheViews", LongCodec.INSTANCE);
    }

    @Singleton("articleLabels")
    public Map<Long, Set<Label>> articleLabels(Redisson redisson, @Autowired("fstCodec") Codec codec) {
        return redisson.getMap("articleLabels", codec);
    }

    @Singleton("optionsMap")
    public Map<String, String> optionsMap(Redisson redisson) {
//      redisson.getKeys().flushdb();
        return redisson.getMap("optionsMap", StringCodec.INSTANCE);
    }

    @Singleton("categories")
    public List<Category> categories(Redisson redisson, @Autowired("fstCodec") Codec codec) {
        return redisson.getList("categories", codec);
    }

    @Singleton("labels")
    public Set<Label> labels(Redisson redisson, @Autowired("fstCodec") Codec codec) {
        return redisson.getSet("labels", codec);
    }

    @Value(value = "#{limit.time.out}", required = false)
    private int limitTimeOut = Constant.ACCESS_TIME_OUT;

    @Singleton("limitCache")
    public Map<String, Long> limitCache(Redisson redisson) {
        final RMapCache<String, Long> mapCache = redisson.getMapCache("limitCache", LongCodec.INSTANCE);
        mapCache.expire(limitTimeOut, TimeUnit.MILLISECONDS);
        return mapCache;
    }

}

生命周期

package test.context;

import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

import org.junit.Test;

import cn.taketoday.context.ApplicationContext;
import cn.taketoday.context.StandardApplicationContext;
import cn.taketoday.context.annotation.Singleton;
import cn.taketoday.context.bean.BeanDefinition;
import cn.taketoday.context.factory.DisposableBean;
import cn.taketoday.context.factory.InitializingBean;
import lombok.extern.slf4j.Slf4j;

/**
 * @author TODAY <br>
 *         2019-07-25 22:44
 */
@Slf4j
@Singleton
public class LifecycleBean //
        implements DisposableBean, BeanNameAware,
        InitializingBean, BeanFactoryAware,
        EnvironmentAware, ApplicationContextAware {

    @Override
    public void setBeanName(String name) {
        log.info("setBeanName: {}", name);
    }

    @Override
    public void setEnvironment(Environment environment) {
        log.info("setEnvironment: {}", environment);
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) {
        log.info("setBeanFactory: {}", beanFactory);
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) {
        log.info("setApplicationContext: {}", applicationContext);
    }

    @PostConstruct
    public void initData() {
        log.info("@PostConstruct");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        log.info("afterPropertiesSet");
    }

    @PreDestroy
    public void preDestroy() {
        log.info("preDestroy");
    }

    @Override
    public void destroy() throws Exception {
        log.info("destroy");
    }

    @Test
    public void testLifecycle() {

        final Set<Class<?>> beans = new HashSet<>();
        beans.add(LifecycleBean.class);
        ClassUtils.setClassCache(beans);
        try (final ApplicationContext applicationContext = new StandardApplicationContext("info.properties")) {

            applicationContext.loadContext(beans);

            Map<String, BeanDefinition> beanDefinitionsMap = applicationContext.getEnvironment().getBeanDefinitionRegistry().getBeanDefinitions();

            System.out.println(beanDefinitionsMap);
        }
    }

}
2019-07-25 23:14:37.712  INFO - [            main] c.t.context.AbstractApplicationContext    150 - Starting Application Context at [2019-07-25 23:14:37.707].
2019-07-25 23:14:37.751  INFO - [            main] c.t.context.env.StandardEnvironment       236 - Found Properties Resource: [file:/G:/Projects/Git/github/today-context/target/test-classes/info.properties]
2019-07-25 23:14:37.771  INFO - [            main] c.t.context.env.StandardEnvironment       129 - Active profiles: [test, dev]
2019-07-25 23:14:37.858 DEBUG - [            main] c.t.context.AbstractApplicationContext    325 - Loading Application Listeners.
2019-07-25 23:14:37.896 DEBUG - [            main] c.t.context.AbstractApplicationContext    480 - Publish event: [cn.taketoday.context.event.BeanDefinitionLoadingEvent]
2019-07-25 23:14:37.918 DEBUG - [            main] c.t.context.AbstractApplicationContext    480 - Publish event: [cn.taketoday.context.event.LoadingMissingBeanEvent]
2019-07-25 23:14:37.921 DEBUG - [            main] c.t.context.AbstractApplicationContext    480 - Publish event: [cn.taketoday.context.event.BeanDefinitionLoadedEvent]
2019-07-25 23:14:37.922 DEBUG - [            main] c.t.context.AbstractApplicationContext    480 - Publish event: [cn.taketoday.context.event.DependenciesHandledEvent]
2019-07-25 23:14:37.923 DEBUG - [            main] c.t.context.factory.AbstractBeanFactory   581 - Start loading BeanPostProcessor.
2019-07-25 23:14:37.926 DEBUG - [            main] c.t.context.AbstractApplicationContext    480 - Publish event: [cn.taketoday.context.event.ContextPreRefreshEvent]
2019-07-25 23:14:37.927 DEBUG - [            main] c.t.context.AbstractApplicationContext    480 - Publish event: [cn.taketoday.context.event.ContextRefreshEvent]
2019-07-25 23:14:37.928 DEBUG - [            main] c.t.context.factory.AbstractBeanFactory  1002 - Initialization of singleton objects.
2019-07-25 23:14:37.929 DEBUG - [            main] c.t.context.factory.AbstractBeanFactory   651 - Initializing bean named: [lifecycleBean].
2019-07-25 23:14:37.929  INFO - [            main] test.context.LifecycleBean                 59 - setBeanName: lifecycleBean
2019-07-25 23:14:37.930  INFO - [            main] test.context.LifecycleBean                 69 - setBeanFactory: cn.taketoday.context.factory.StandardBeanFactory@5ce81285
2019-07-25 23:14:37.930  INFO - [            main] test.context.LifecycleBean                 74 - setApplicationContext: cn.taketoday.context.StandardApplicationContext@78c03f1f
2019-07-25 23:14:37.930  INFO - [            main] test.context.LifecycleBean                 64 - setEnvironment: cn.taketoday.context.env.StandardEnvironment@5ec0a365
2019-07-25 23:14:37.931  INFO - [            main] test.context.LifecycleBean                 79 - @PostConstruct
2019-07-25 23:14:37.931  INFO - [            main] test.context.LifecycleBean                 84 - afterPropertiesSet
2019-07-25 23:14:37.931 DEBUG - [            main] c.t.context.factory.AbstractBeanFactory   511 - Singleton bean is being stored in the name of [lifecycleBean]
2019-07-25 23:14:37.932 DEBUG - [            main] c.t.context.factory.AbstractBeanFactory  1008 - The singleton objects are initialized.
2019-07-25 23:14:37.932 DEBUG - [            main] c.t.context.AbstractApplicationContext    480 - Publish event: [cn.taketoday.context.event.ContextStartedEvent]
2019-07-25 23:14:37.941  INFO - [            main] c.t.context.AbstractApplicationContext    210 - Application Context Startup in 234ms
{lifecycleBean={
    "name":"lifecycleBean",
    "scope":"SINGLETON",
    "beanClass":"class test.context.LifecycleBean",
    "initMethods":"[public void test.context.LifecycleBean.initData()]",
    "destroyMethods":"[]",
    "propertyValues":"[]",
    "initialized":"true",
    "factoryBean":"false",
    "abstract":"false"
}}
2019-07-25 23:14:37.943 DEBUG - [            main] c.t.context.AbstractApplicationContext    480 - Publish event: [cn.taketoday.context.event.ContextCloseEvent]
context is closing
2019-07-25 23:14:37.945  INFO - [            main] c.t.c.listener.ContextCloseListener        52 - Closing: [cn.taketoday.context.StandardApplicationContext@78c03f1f] at [2019-07-25 23:14:37.943]
2019-07-25 23:14:37.947  INFO - [            main] test.context.LifecycleBean                 89 - preDestroy
2019-07-25 23:14:37.947  INFO - [            main] test.context.LifecycleBean                 94 - destroy

 

  • 原文转自:https://www.cnblogs.com/zhaoweihang/p/9698852.html     <field name="partner_id" string="Customer" widget="res_partner_many2one" context="{'default_name': contact_name, 'default_street': street, '

  • 聚宽的API文档对Portfolio,Context对象的描述理解不清晰,自己动手输出了Portfolio,Context对象的详细属性。(遇到不理解不明白的地方,自己动手实践输出) Portfolio对象 Portfolio({ 'available_cash': 26581.98, 'subportfolios': [SubPortfolio({'available_cash': 26581.

  • <field name="partner_id" string="Customer" widget="res_partner_many2one" context="{'default_name': contact_name, 'default_street': street, 'default_city': city, 'default_state_id': state_id, 'default_

  • <context:annotation-config>与<context:component-scan>的区别 声明:本文转自stackoverflow;讲解十分详细,十分精彩,特此分享到CSDN;有时间的话,我会翻译一下,BUT,NOT TODAY; Ref:Difference between <context:annotation-config> vs <context:component-

  • The approaches in this post are now obsolete thanks to Go 1.7, which adds the context package to the standard library and uses it in the *net/http http.Request type. The background info here may still

  • title: "React v16.6.0: lazy, memo and contextType" author: [sebmarkbage] Today we're releasing React 16.6 with a few new convenient features. A form of PureComponent/shouldComponentUpdate for function

  • 写在首行:开发语言为JAVA 按照郭神的教程集成百度SDK之后运行失败,参考了百度官网的集成说明,发现需要做地图的初始化,引用自:androidsdk | 百度地图API SDK 第三步:地图初始化 注意:在SDK各功能组件使用之前都需要调用“SDKInitializer.initialize(getApplicationContext())”,因此建议在应用创建时初始化SDK引用的Context

  • 1.修改datepicker 中 today 按钮默认选中今天: 在jquery-ui.js中找到_attachHandlers _attachHandlers: function(e) { var i = this._get(e, "stepMonths"), s = "#" + e.id.replace(/\\\\/g, "\\"),

  • 今天遇到一个问题 ,在Fragment中使用Recyclerview设置空布局的时候, View view = LayoutInflater.from(getContext()).inflate(R.layout.item_today_plan_container, null); 出现如上问题: java.lang.NullPointerException: Attempt to invoke v

 相关资料
  • 在不讨论原因的情况下,假设有人想要一个老式的Play Framework web服务,并且不想使用依赖注入,也不想依赖Google的Guice。在玩法2.8.x中还可能吗? 有没有一个简单的方法可以让你不去这里就呆在老学校里? 我承认,但不完全理解https://www.playframework.com/documentation/2.4.x/migration24。我认为我的问题与2.7中删除

  • 在React中,想做依赖注入(Dependency Injection)其实相当简单。请看下面这个例子: // Title.jsx export default function Title(props) { return <h1>{ props.title }</h1>; } // Header.jsx import Title from './Title.jsx'; export defa

  • 依赖注入 Dependency Injection is a strong mechanism, which helps us easily manage dependencies of our classes. It is very popular pattern in strongly typed languages like C# and Java. 依赖注入是一个很强大的机制,该机制可以帮

  • 简介 Hyperf 默认采用 hyperf/di 作为框架的依赖注入管理容器,尽管从设计上我们允许您更换其它的依赖注入管理容器,但我们强烈不建议您更换该组件。 hyperf/di 是一个强大的用于管理类的依赖关系并完成自动注入的组件,与传统依赖注入容器的区别在于更符合长生命周期的应用使用、提供了 注解及注解注入 的支持、提供了无比强大的 AOP 面向切面编程 能力,这些能力及易用性作为 Hyper

  • 出自维基百科 Wikipedia: 依赖注入是一种允许我们从硬编码的依赖中解耦出来,从而在运行时或者编译时能够修改的软件设计模式。 这句解释让依赖注入的概念听起来比它实际要复杂很多。依赖注入通过构造注入,函数调用或者属性的设置来提供组件的依赖关系。就是这么简单。

  • 问题内容: 根据我的经验,Maven在小型/实验性应用程序中常常是过大的。但是,依赖管理是Maven的一项非常有用的功能,实际上是唯一对上述应用程序类型真正有用的功能。 我想知道是否可以有一个 非常最小的轻量级 Eclipse-Maven集成,该集成 仅以 最简单的方式 仅 将Maven依赖项添加到Eclipse项目类路径中。 特别是我不想: 适用于任何Maven约定(包括项目布局召集人) 安装并

  • 问题内容: 我想知道 _什么是Spring Framework? 为什么和何时应该在Java Enterprise开发中使用它? _ 答案将是“依赖注入框架”。好了,使用依赖注入框架时我们有什么优势?用setter值和/或构造函数参数描述类的想法对我来说似乎很奇怪。为什么这样 因为我们可以更改属性而无需重新编译项目?这就是我们所获得的一切吗? 那么,我们应该用什么对象来描述?所有对象还是只有几个?