spring-core-4-36 | 实例化Spring Bean:Bean实例化的姿势有多少种?

Spring 4 Security MVC 登录登出完整骨架(XML配置版) Spring Security 是 Spring 生态中实现认证与授权的核心框架,其本质是通过 Filter Chain 拦截请求并委托 AuthenticationManager 执行校验。在传统 Spring MVC 架构中,Security 与 DispatcherServlet 协同工作:前者负责安全拦截与会话管理,后者处理控制器分发与视图渲染。这种组合具备强可控性、低侵入性和清晰的调试路径,特别适合遗留系统加固、教学实践及底层机制学习。本文聚焦 Spring 4 原生环境下的最小可行实现——基于 阅读详情

实例化Spring Bean

Bean 实例化(Instantiation)

常规方式

• 通过构造器(配置元信息:XML、Java 注解和Java API )
不演示了, 例子太多

• 通过静态工厂方法(配置元信息:XML 和Java API )

• 通过Bean 工厂方法(配置元信息:XML和Java API )

• 通过FactoryBean(配置元信息:XML、Java 注解和Java API )

特殊方式

• 通过ServiceLoaderFactoryBean(配置元信息:XML、Java 注解和Java API )

• 通过AutowireCapableBeanFactory#createBean(java.lang.Class, int,
boolean)

• 通过BeanDefinitionRegistry#registerBeanDefinition(String,BeanDefinition)

代码示例

spring-core项目
搜索 36 | 实例化Spring Bean
常规方式
BeanInstantiationDemo.java
UserFactory.java
UserFactoryBean.java
bean-instantiation-context.xml

BeanInstantiationDemo.java

/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.geekbang.thinking.in.spring.bean.definition;

import org.geekbang.thinking.in.spring.ioc.overview.domain.User;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * 36 | 实例化Spring Bean:Bean实例化的姿势有多少种?
 *
 * Bean 实例化示例, 这里实例化其实也包括初始化了
 *
 * • Bean 实例化(Instantiation)
 *      • 常规方式
 *          • 通过构造器(配置元信息:XML、Java 注解和Java API )
 *          • 通过静态工厂方法(配置元信息:XML 和Java API )
 *          • 通过Bean 工厂方法(配置元信息:XML和Java API ), 就是下面的 实例(Bean)方法实例化 Bean
 *          • 通过FactoryBean(配置元信息:XML、Java 注解和Java API )
 *      • 特殊方式
 *          • 通过ServiceLoaderFactoryBean(配置元信息:XML、Java 注解和Java API )
 *          • 通过AutowireCapableBeanFactory#createBean(java.lang.Class, int, boolean)
 *          • 通过BeanDefinitionRegistry#registerBeanDefinition(String,BeanDefinition) 见 31 | 定义Bean: 什么是BeanDefinition?
 *
 * @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
 * @since
 */
public class BeanInstantiationDemo {

    public static void main(String[] args) {
        // 配置 XML 配置文件, 下面bean的id都去xml文件里面去找
        // 启动 Spring 应用上下文
        BeanFactory beanFactory
                = new ClassPathXmlApplicationContext("classpath:/META-INF/bean-instantiation-context.xml");
        // 36.2 通过静态工厂方法实例化 Bean, 这里其实是一个静态工厂的模式, 可以看User类里面那个静态的工厂方法
        User userByStaticMethod = beanFactory.getBean("user-by-static-method", User.class);
        // 36.3 实例(Bean)方法实例化 Bean, 这里其实是一个代理工厂的模式, 看UserFactory和 DefaultUserFactory, 实现了代理工厂
        // UserFactory需要在配置文件中配置
        User userByInstanceMethod = beanFactory.getBean("user-by-instance-method", User.class);
        // 36.4 通过FactoryBean实例化 Bean
        User userByFactoryBean = beanFactory.getBean("user-by-factory-bean", User.class);

        System.out.println(userByStaticMethod);
        System.out.println(userByInstanceMethod);
        System.out.println(userByFactoryBean);

        // 相等性上应该是都不对等的, 都不是一种创建的方式
        System.out.println(userByStaticMethod == userByInstanceMethod);
        System.out.println(userByStaticMethod == userByFactoryBean);

    }
}

bean-instantiation-context.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd">

    <!-- 36 | 实例化Spring Bean:Bean实例化的姿势有多少种? -->
    <!-- 36.2 静态方法实例化 Bean -->
    <!-- 这里的意思就是通过一个静态方法来创建这个bean, 而这个方法定义在这个User类里面 -->
    <bean id="user-by-static-method" class="org.geekbang.thinking.in.spring.ioc.overview.domain.User"
          factory-method="createUser"/>

    <!-- 36.3 实例(Bean)方法实例化 Bean / 通过Bean 工厂方法 -->
    <!-- 这里其实是定义了一个UserFactory代理工厂类(有默认实现的接口), 然后DefaultUserFactory是实现类,
        createUser则是实现类的一个实例方法, 故而是一个Bean工厂方法实现的实例化Bean -->
    <bean id="user-by-instance-method" factory-bean="userFactory" factory-method="createUser"/>
    <bean id="userFactory" class="org.geekbang.thinking.in.spring.bean.factory.DefaultUserFactory"/>


    <!-- 36.4 FactoryBean实例化 Bean -->
    <!-- 这个方式比较特殊在于并不会去定义这个bean, 而是一个factoryBean,
    那么这里不仅能实例化, 其实还能进行初始化, 看实现了哪些方法了 -->
    <bean id="user-by-factory-bean" class="org.geekbang.thinking.in.spring.bean.factory.UserFactoryBean"/>


</beans>

User.java

/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.geekbang.thinking.in.spring.ioc.overview.domain;

import org.geekbang.thinking.in.spring.ioc.overview.enums.City;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.core.io.Resource;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.util.Arrays;
import java.util.List;
import java.util.Properties;

/**
 * 用户类
 * <p>
 * spring-core-2-17 | 传统IoC容器实现:JavaBeans也是IoC容器吗?
 * 这个类也用于JavaBeans作为IoC容器功能的演示
 * <p>
 * 常见叫法: Setter方法 / Getter 方法
 * Java Beans叫法: 可写方法(writable) / 可读方法(Readable)
 *
 * @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
 * @since
 */
public class User implements BeanNameAware {

    // 61 | 基础类型注入  有没有思考过配置文件里的属性值是字符串, 怎么转换成这的Long?
    private Long id;// 属性也称为Property

    private String name;

    // 61 | 基础类型注入, 枚举也可以注入
    private City city;

    // 62 | 集合类型注入, 数组类型注入
    private City[] workCities;

    // 62 | 集合类型注入, List类型注入
    private List<City> lifeCities;

    // 61 | 基础类型注入, spring的类型也可以注入
    // 其实在调用User 的 toString() 方法时, 对configFileLocation 的展示也是调了一个 toString(),
    // 可以看 org.springframework.core.io.ClassPathResource 的 父接口
    // org.springframework.core.io.AbstractResource, 有 toString() 方法,
    // 可以看到是使用 getDescription() 实现的, 那么再转回去:
    // org.springframework.core.io.ClassPathResource.getDescription, 就是这么来的
    private Resource configFileLocation;

    private Company company;

    private Properties context;

    private String contextAsText;

    /**
     * 当前 Bean 的名称
     */
    private transient String beanName;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public City getCity() {
        return city;
    }

    public void setCity(City city) {
        this.city = city;
    }

    public Resource getConfigFileLocation() {
        return configFileLocation;
    }

    public void setConfigFileLocation(Resource configFileLocation) {
        this.configFileLocation = configFileLocation;
    }

    public City[] getWorkCities() {
        return workCities;
    }

    public void setWorkCities(City[] workCities) {
        this.workCities = workCities;
    }

    public List<City> getLifeCities() {
        return lifeCities;
    }

    public void setLifeCities(List<City> lifeCities) {
        this.lifeCities = lifeCities;
    }

    public Company getCompany() {
        return company;
    }

    public void setCompany(Company company) {
        this.company = company;
    }

    /**
     * 36.2 静态的工厂方法, 用于bean的实例化
     * @return
     */
    public static User createUser() {
        User user = new User();
        user.setId(1L);
        user.setName("小马哥");
        return user;
    }

    @PostConstruct
    public void init() {
        System.out.println("User Bean [" + beanName + "] 初始化...");
    }

    @PreDestroy
    public void destroy() {
        System.out.println("User Bean [" + beanName + "] 销毁中...");
    }

    @Override
    public void setBeanName(String name) {
        this.beanName = name;
    }

    public Properties getContext() {
        return context;
    }

    public void setContext(Properties context) {
        this.context = context;
    }

    public String getContextAsText() {
        return contextAsText;
    }

    public void setContextAsText(String contextAsText) {
        this.contextAsText = contextAsText;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", city=" + city +
                ", workCities=" + Arrays.toString(workCities) +
                ", lifeCities=" + lifeCities +
                ", configFileLocation=" + configFileLocation +
                ", company=" + company +
                ", context=" + context +
                ", contextAsText='" + contextAsText + '\'' +
                ", beanName='" + beanName + '\'' +
                '}';
    }
}

DefaultUserFactory.java

/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.geekbang.thinking.in.spring.bean.factory;

import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;

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

/**
 * 36 | 实例化Spring Bean:Bean实例化的姿势有多少种?
 * 36.3 默认 {@link UserFactory} 实现
 *
 * 37 | 初始化Spring Bean:Bean初始化有哪些方式?
 *
 * 39 | 销毁Spring Bean
 *
 * @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
 * @since
 */
public class DefaultUserFactory implements UserFactory, InitializingBean, DisposableBean {

    // 37.1. 基于 @PostConstruct 注解
    @PostConstruct
    public void init() {
        System.out.println("@PostConstruct : UserFactory 初始化中...");
    }

    public void initUserFactory() {
        System.out.println("自定义初始化方法 initUserFactory() : UserFactory 初始化中...");
    }

    /**
     * 37.2 实现InitializingBean 接口的afterPropertiesSet() 方法
     * @throws Exception
     */
    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("InitializingBean#afterPropertiesSet() : UserFactory 初始化中...");
    }

    /**
     * 39.1 @PreDestroy 标注方法
     */
    @PreDestroy
    public void preDestroy() {
        System.out.println("@PreDestroy : UserFactory 销毁中...");
    }

    /**
     * 39.2 实现DisposableBean 接口的destroy() 方法
     * @throws Exception
     */
    @Override
    public void destroy() throws Exception {
        System.out.println("DisposableBean#destroy() : UserFactory 销毁中...");
    }

    public void doDestroy() {
        System.out.println("自定义销毁方法 doDestroy() : UserFactory 销毁中...");
    }

    /**
     * 40 Spring Bean 覆盖的finalize() 方法
     * 垃圾回收时 ,finalize()会被java回调
     * @throws Throwable
     */
    @Override
    public void finalize() throws Throwable {
        System.out.println("当前 DefaultUserFactory 对象正在被垃圾回收...");
    }
}

UserFactoryBean.java

/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.geekbang.thinking.in.spring.bean.factory;

import org.geekbang.thinking.in.spring.ioc.overview.domain.User;
import org.springframework.beans.factory.FactoryBean;

/**
 * 36 | 实例化Spring Bean:Bean实例化的姿势有多少种?
 * 36.4  {@link User} Bean 的 {@link org.springframework.beans.factory.FactoryBean} 实现
 *
 * @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
 * @since
 */
public class UserFactoryBean implements FactoryBean {

    /**
     * 相当于我的实例方法, 静态方法以及 FactoryBean的实现均采用User类的静态方法createUser()来实现
     * @return
     * @throws Exception
     */
    @Override
    public Object getObject() throws Exception {
        return User.createUser();
    }

    @Override
    public Class<?> getObjectType() {
        return User.class;
    }
}

特殊方式
SpecialBeanInstantiationDemo.java
special-bean-instantiation-context.xml
META-INF\services\org.geekbang.thinking.in.spring.bean.factory.UserFactory

SpecialBeanInstantiationDemo.java

/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.geekbang.thinking.in.spring.bean.definition;

import org.geekbang.thinking.in.spring.bean.factory.DefaultUserFactory;
import org.geekbang.thinking.in.spring.bean.factory.UserFactory;
import org.geekbang.thinking.in.spring.ioc.overview.domain.User;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.util.Iterator;
import java.util.ServiceLoader;

import static java.util.ServiceLoader.load;

/**
 * 36 | 实例化Spring Bean:Bean实例化的姿势有多少种?
 *
 * 特殊的 Bean 实例化示例
 * • 通过ServiceLoaderFactoryBean(配置元信息:XML、Java 注解和Java API )
 * • 通过AutowireCapableBeanFactory#createBean(java.lang.Class, int, boolean)
 *
 * @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
 * @since
 */
public class SpecialBeanInstantiationDemo {

    public static void main(String[] args) {
        // 配置 XML 配置文件
        // 启动 Spring 应用上下文
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:/META-INF/special-bean-instantiation-context.xml");

        // 36.6 通过 ApplicationContext 获取 AutowireCapableBeanFactory
        // 这里有个意思的就是 beanFactory 就不能获取到 AutowireCapableBeanFactory, ApplicationContext是beanFactory的超类
        AutowireCapableBeanFactory beanFactory = applicationContext.getAutowireCapableBeanFactory();

        // 创建 UserFactory 对象,通过 AutowireCapableBeanFactory
        // 这里我们在创建一个类的实体的时候, 一定要用实现类, 但是不要用接口, 会报错
        UserFactory userFactory = beanFactory.createBean(DefaultUserFactory.class);
        System.out.println(userFactory.createUser());

        // 36.5.2 serviceLoader的获取方式二, 通过spring的ServiceLoaderFactoryBean来获取 ServiceLoader, 这里有spring的参与了
        // 这里是通过ServiceLoaderFactoryBean 来创建一个 ServiceLoader , 并且这个 ServiceLoader 只关注 UserFactory,
        // 如果有多个对象, 与方式一相比这种方式不会逐一输出
        ServiceLoader<UserFactory> serviceLoader = beanFactory.getBean("userFactoryServiceLoader", ServiceLoader.class);

        displayServiceLoader(serviceLoader);

        // 36.5.1 ServiceLoader的获取方式一
        // 与方式二相比, 这里如果配置了多个类会逐一输出
//        demoServiceLoader();


    }

    public static void demoServiceLoader() {
        // ServiceLoader 是java1.6开始 提供的一个用于依赖注入的类, 其中
        //  private static final String PREFIX = "META-INF/services/";
        // 我们需要这么个路径, 里面的文件名是需要实例化的类的接口的全类名
        // 文件的内容则是接口实现类的全类名, 可以是一个或多个, 重复的话也会被去重, 这里就是jdk里面的反转控制/依赖查找

        // serviceLoader的获取方式一, 通过ServiceLoader的静态方法 load(), 这是纯jdk的方法
        ServiceLoader<UserFactory> serviceLoader = load(UserFactory.class, Thread.currentThread().getContextClassLoader());
        displayServiceLoader(serviceLoader);
    }

    private static void displayServiceLoader(ServiceLoader<UserFactory> serviceLoader) {
        // 可以看出这里允许实例化多个类
        Iterator<UserFactory> iterator = serviceLoader.iterator();
        while (iterator.hasNext()) {
            UserFactory userFactory = iterator.next();
            System.out.println(userFactory.createUser());
        }
    }
}

special-bean-instantiation-context.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd">

    <!-- 36 | 实例化Spring Bean:Bean实例化的姿势有多少种? -->
    <!-- 方式二, 通过ServiceLoaderFactoryBean, 这里通过spring来获取的ServiceLoader, 就需要用到 ServiceLoaderFactoryBean
            public class ServiceLoaderFactoryBean extends AbstractServiceLoaderBasedFactoryBean implements BeanClassLoaderAware {

                @Override
                protected Object getObjectToExpose(ServiceLoader<?> serviceLoader) {
                    return serviceLoader;
                }

                @Override
                public Class<?> getObjectType() {
                    return ServiceLoader.class;
                }

            }

           这是spring提供的工厂类, 但是其中参数的注入怎么弄, 需要看下源码, 往父类找:
            org.springframework.beans.factory.config.AbstractFactoryBean.getObject()
            @Override
            public final T getObject() throws Exception {
                if (isSingleton()) {
                    return (this.initialized ? this.singletonInstance : getEarlySingletonInstance());
                }
                else {
                    return createInstance();
                }
            }

            其中 createInstance() 有很多种实现, 我们看其中的基础实现:
            org.springframework.beans.factory.serviceloader.AbstractServiceLoaderBasedFactoryBean.createInstance
            protected Object createInstance() {
                Assert.notNull(getServiceType(), "Property 'serviceType' is required");
                return getObjectToExpose(ServiceLoader.load(getServiceType(), this.beanClassLoader));
            }
            可以看出来其实和方式一是类似的, 还是需要配置一个 serviceType , 所以我们提供一个要实例化的接口的全类名

            我们再回来看 getObjectToExpose() 的实现
            org.springframework.beans.factory.serviceloader.ServiceFactoryBean.getObjectToExpose
            @Override
            protected Object getObjectToExpose(ServiceLoader<?> serviceLoader) {
                Iterator<?> it = serviceLoader.iterator();
                if (!it.hasNext()) {
                    throw new IllegalStateException(
                            "ServiceLoader could not find service for type [" + getServiceType() + "]");
                }
                return it.next();
            }
            发现它有且只返回一个实现

            有没有能返回多个的呢? 那是肯定的, AbstractServiceLoaderBasedFactoryBean 还有其他实现, 比如
            org.springframework.beans.factory.serviceloader.ServiceListFactoryBean
            public class ServiceListFactoryBean extends AbstractServiceLoaderBasedFactoryBean implements BeanClassLoaderAware {

                @Override
                protected Object getObjectToExpose(ServiceLoader<?> serviceLoader) {
                    List<Object> result = new LinkedList<>();
                    for (Object loaderObject : serviceLoader) {
                        result.add(loaderObject);
                    }
                    return result;
                }

                @Override
                public Class<?> getObjectType() {
                    return List.class;
                }

            }
             就可以看出来他就是返回一个list

             -->
    <bean id="userFactoryServiceLoader" class="org.springframework.beans.factory.serviceloader.ServiceLoaderFactoryBean">
        <property name="serviceType" value="org.geekbang.thinking.in.spring.bean.factory.UserFactory" />
    </bean>
</beans>

META-INF\services\org.geekbang.thinking.in.spring.bean.factory.UserFactory

/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.geekbang.thinking.in.spring.bean.factory;

import org.geekbang.thinking.in.spring.ioc.overview.domain.User;

/**
 * 36 | 实例化Spring Bean:Bean实例化的姿势有多少种?
 * {@link User} 36.3 工厂类, 这里是一个代理工厂, 需要用jdk1.8的编译器, pom文件中需要修改编译级别
 *
 * @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
 * @since
 */
public interface UserFactory {
    // 1.8编译器支持的接口默认实现
    default User createUser() {
        return User.createUser();
    }
}

SSM框架深度解析:Spring MVC工作流程、MyBatis缓存与三级缓存实战 在Java企业级开发中,依赖注入(DI)和面向切面编程(AOP)是构建松耦合、可维护应用的核心设计思想。Spring框架通过其IoC容器实现了这些思想,其中三级缓存机制巧妙地解决了单例Bean的循环依赖问题,这是理解Spring Bean生命周期的关键。在Web层,Spring MVC基于DispatcherServlet的前端控制器模式,通过HandlerMapping、HandlerAdapter和ViewResolver等组件协同工作,处理请求分发与视图渲染,其拦截器(Interceptor)为权限校 阅读详情

相关推荐

Spring AI+MyBatis-Plus+Spring Boot生产级版本兼容指南

Spring AI 是 Spring 生态官方推出的 AI 应用开发框架,旨在简化大模型集成;MyBatis-Plus 则是 Java 领域最主流的持久层增强工具,提供无侵入式 CRUD 与自动填充等能力。二者在 Spring Boot 3.x 基础上协同工作时,因依赖收敛、事务传播、线程上下文隔离及 Jakarta EE 兼容性等底层机制差异,极易引发启动失败、分页失效、自动填充丢失、事务不回滚等‘幽灵问题’。本指南聚焦真实生产环境验证的最小可行组合(Spring Boot 3.2.4 + MyBatis

weixin_34185320的博客 446

初步认识Spring

(一)Spring是什么? (1)Spring是优秀的开源框架 (2)Spring是为了简化企业级应用开发而生的。 (3)Spring是一个IOC(DI)和AOP的容器框架 (4)Spring是轻量级的,非侵入式的。使用Spring框架时,我们不需要实现任何接口,也不用继承任何父类。 (二)Spring模块 (1)由于Beans、Core、Context、SpEL这4个模块是最基本、

hhx_echo的博客 251

Spring Boot配置文件加密实战:从Jasypt到Vault的完整方案

在应用开发中,配置管理是保障系统安全的重要环节,尤其是涉及数据库密码、API密钥等敏感信息时,明文存储会带来严重的数据泄露风险。其核心原理是通过加密算法对敏感配置进行转换,确保即使配置文件被获取,攻击者也无法直接读取原始信息。这项技术的价值在于实现安全性与可用性的平衡,防止因代码泄露、服务器入侵或运维不当导致的核心凭证暴露。常见的应用场景包括微服务架构中的配置集中管理、CI/CD流水线的安全部署以及满足各类安全合规要求。本文聚焦于Spring Boot生态,深入探讨了Jasypt集成、自定义Environm

weixin_34320724的博客 371

spring-core-4.04 源码编译过程记录

spring-core-4.04 源码编译缺少jar包

dns007 1878

spring-core-4.3.20.RELEASE-API文档-中文版.zip

赠送jar包:spring-core-4.3.20.RELEASE.jar; 赠送原API文档:spring-core-4.3.20.RELEASE-javadoc.jar; 赠送源代码:spring-core-4.3.20.RELEASE-sources.jar; 包含翻译后的API文档:spring-core-4.3.20.RELEASE-javadoc-API文档-中文(简体)版.zip 对应Maven信息:groupId:org.springframework,artifactId:spring-core,version:4.3.20.RELEASE 使用方法:解压翻译后的API文档,用浏览器打开“index.html”文件,即可纵览文档内容。 人性化翻译,文档中的代码和结构保持不变,注释和说明精准翻译,请放心使用。

代码接单:用 ComfyUI 搭建电商模特换装工作流(保姆级教程)

在闲鱼和小红书上,搜一下“AI 模特图”或者“服装换模特”,你会发现大量的接单需求。太贵:请个外模拍一套图,动辄几千块。太慢:寄样品、排期、拍摄、修图,半个月过去了。太卷:竞对都在上新,你还在等图。“给我一张你的衣服平铺图(或假人图),我 10 分钟给你生成真人上身图,一张只要 50 块。对于商家是省钱,对于你是纯利润。为什么不用 Midjourney?因为 MJ 抽卡不可控,无法保持衣服版型一致。只有 ComfyUI,才能做到精准控制,实现工业化量产。

BUG猿的博客 1779

Spring jar包下载

Spring的下载及目录结构 Spring的第一个版本是在2004年发布的,经过10多年的发展,Spring的版本也在不断地升级优化中。 Spring开发所需的JAR包分为两个部分,具体如下。 1、Spring框架包 Spring4.3.6版本的框架压缩包,名称为spring-framework- 4.3.6.RELEASE-dist.zip, 此压缩包可以通过地址"https://repo.spring.io/simple/libs-release-local/org/springframework/sp

iijik55的博客 7583

基于单光子探测的高重频多通道符合测距

TDC专栏之基于单光子探测的高重频多通道符合测距

sdau2005的博客 1203

spring bean和spring context和spring core的区别

我们在这里把xmlBeanfactory看作一个bean,再将xmlBeanFactory对bean的额外处理也看作一个简单的bean,beanFactory额外处理也和没处理一样看作一个bean,再将其他扩展功能也看一系列的bean的组成,所有的都看作bean,bean就是组件,spring-bean提供的是一个组件,主要是beanFactory,一个提供了创建组件的功能(,每个组件在自己的模块与其他组件协同作用)而上下文有,时间发布,消息,资源处理,以及beanFactory。

2303_76384306的博客 355

081、空间降噪(Spatial Denoise)实战:双边滤波、非局部均值与BM3D在ISP中的调优

调参时,别只看PSNR/SSIM。找几个典型场景(夜景、人像、文字、天空),在真实设备上肉眼对比。我见过PSNR涨了2dB但图像看起来更差的案例——因为PSNR不惩罚纹理丢失。空间降噪这块,理论说再多,不如动手调一次。下次遇到噪点问题,先别急着上BM3D,试试双边滤波的自适应参数,说不定有惊喜。

zzfmlxs的博客 46

【NI Multisim 14.0原理图设计基础——元器件分类】

电阻(RESISTOR):该元器件栏中的电阻都是标称电阻,是根据真实电阻元器件而设计的,其电阻值不能改变。 排阻(RESISTOR PACK):相当于多个电阻并列封装在一个壳内,它们具有相同的阻值。 电位器(POTENTIOMETER):即可调电阻,可以通过键盘字母动态调节电阻,大写表示增加电阻值,小写表示减小电阻值,调节增量可以设置。 电容(CAPACITOR):所有电容都是无极性的,不能改变参数,没有考虑误差,也未考虑耐压大小。 电解电容器(CAP_ELECTROLIT):所有电容都是有极性的,“+”极

RL2698853114的博客 4万+

Spring Bean生命周期详解

API的方式Xml文件方式properties文件的方式注解的方式spring中提供了一个类PropertiesBeanDefinitionReader,将xml中定义的bean解析为BeanDefinition对象,过程和xml的方式类似。下面通过properties文件的方式实现上面xml方式定义的bean。来个properties文件:beans.propertiescar.name=??car1.name=???user.name=???Java。

sxlishaobin的博客 764

自动批量安装加载cran, bioconductor和github三个平台的所有的R包

自动批量安装加载cran, bioconductor和github三个平台的所有的R包

qq_40073899的博客 561

每周小记——Spring框架

本文解析了Spring框架的四大核心机制:工厂模式通过BeanFactory和ApplicationContext实现Bean生命周期管理,奠定IoC容器基础;控制反转与依赖注入将对象创建权移交容器,通过配置解耦组件,提升系统灵活性;面向切面编程基于代理模式(静态/JDK动态/CGLIB)实现横切关注点(如日志、事务)与业务逻辑分离,并总结了五种通知类型及其配置方法。文章系统阐述了Spring如何通过设计模式优化Java企业级开发,强化代码可维护性与模块化,凸显其在现代架构中的关键作用

weixin_57655687的博客 1553

反卷积通俗详细解析与nn.ConvTranspose2d重要参数解释

反卷积的作用 卷积中padding的几个概念 No Padding Half(Same) Padding Full Padding 反卷积 反卷积中的Padding参数 反卷积的stride参数 反卷积总结 参考资料

iioSnail的博客 2万+

qwen2vl ValueError: Image features and image tokens do not match: tokens: 568, features 600

本文介绍了一个用于计算多模态数据集中样本token数量的Python工具,特别针对包含文本和图像的Qwen2-VL模型数据集。

q742971636的博客 1012

Spring @Configuration 原理与最佳实践:从代理机制到配置编排

@Configuration 是 Spring 容器实现声明式配置的核心注解,其本质并非简单标记配置类,而是触发 ConfigurationClassPostProcessor 的元编程解析流程,通过 CGLIB 动态代理保障 @Bean 方法的单例语义与依赖一致性。它区别于 @Component 的关键在于参与容器启动早期的 BeanDefinition 注册拓扑排序,并深度整合 @Import、@Conditional 和 @Profile 等机制,构成可组合、可条件化、可环境隔离的配置编排能力。在微服

weixin_30745553的博客 314

实战:爬取某小程序的订单数据(解析小程序 API 参数)

本文以美团外卖小程序为例,详细分析了电商类小程序订单数据接口的技术实现与采集方法。首先通过抓包定位核心接口,解析其请求参数;重点破解了token验证机制与sign签名加密算法,通过逆向分析还原参数生成逻辑;最后基于Python实现了订单数据的自动化爬取与存储。文章强调数据采集需遵守法律合规性,提供应对反爬机制的策略,并指出了必须在获得合法授权的前提下使用这些技术。该研究为数据采集工程师提供了实用的技术参考,但必须严格遵循"最小必要"原则,确保不违反平台规则和用户隐私保护法规。

2503_91057718的博客 2317

用豆包辅助从头开始学习java spring cloud(三)

本文摘要(145字): 作者通过实践学习Spring Boot的核心配置机制,重点研究了@Configuration和@Bean注解的Full/Lite模式差异。创建User和Order实体类进行实验,通过配置类演示了两种模式下Bean创建行为的区别。特别关注了Full模式下proxyBeanMethods=true时,容器如何确保Bean单例特性。还探讨了@Conditional系列注解在自动配置中的应用,如@ConditionalOnClass和@ConditionalOnMissingBean,这些是

逸辰轩的博客 387

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

Spring AI 2.0与Spring Boot 4企业级AI应用开发指南

AI技术在现代企业应用中扮演着越来越重要的角色,特别是在自然语言处理和智能决策支持方面。Spring AI 2.0作为Spring官方推出的AI集成框架,通过与Spring Boot 4的深度整合,为Java开发者提供了便捷的AI能力接入方案。其核心原理是通过模块化设计封装不同AI服务提供商的API,实现像更换数据库驱动一样切换AI服务商的技术价值。在实际工程实践中,这种架构特别适合需要快速对接多个AI服务提供商(如OpenAI、Alibaba等)、统一管理AI调用Token消耗、以及要求AI功能与现有Sp

weixin_34221775的博客 342

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

Spring Boot设计哲学与自动配置原理深度解析

Spring Boot作为现代Java微服务开发的核心框架,其本质是通过‘约定优于配置’和条件化自动配置机制,将Spring生态的复杂性封装为可预测、可调试的工程契约。它基于@ConditionalOnClass、@ConditionalOnMissingBean等条件注解实现精准的Bean装配,依托spring.factories加载机制与Starter模块化依赖管理,达成开箱即用体验。这种设计不仅显著降低XML配置与Maven版本冲突风险,更支撑云原生部署、Kubernetes健康探针集成及Actuat

diaojin6880的博客 384

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

maven 集成spring

1、简历maven工程。   eclipse开发工具建立名为spring-maveng的工程 2、在pom.xml文件中引入所需的包 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:sche...

Jiuxia2016的博客 172

15个经典的Spring面试常见问题

这篇文章主要是想通过一些问题,加深大家对于 Spring 的理解,所以不会涉及太多的代码!这篇文章整理了挺长时间,下面的很多问题我自己在使用 Spring 的过程中也并没有注意,自己也是临时查阅了很多资料和书籍补上的。网上也有一些很多关于 Spring 常见问题/面试题整理的文章,我感觉大部分都是互相 copy,而且很多问题也不是很汗,有些回答也存在问题。所以,自己花了一周的业余时间整理了一下,希望对大家有帮助。Spring 是一种轻量级开发框架,旨在提高开发人员的开发效率以及系统的可维护性。Spring

429

Spring Boot入门指南:核心原理与实战配置

Spring Boot作为Java生态中的主流框架,通过自动配置和起步依赖等机制显著简化了Spring应用的开发流程。自动配置基于类路径和条件注解智能加载所需组件,起步依赖则通过预定义的依赖关系解决库版本冲突问题。这些特性使开发者能快速构建生产级应用,特别适合微服务架构和云原生场景。在实际开发中,合理的项目结构规范、多环境配置策略以及日志系统配置都是提升工程效率的关键。通过理解@SpringBootApplication注解背后的工作原理,开发者可以更好地应对自动配置失效等典型问题。结合Maven工具链和I

407

Sensitive与Spring Boot集成:快速构建安全可靠的日志脱敏系统

在当今数据驱动的时代,日志中的敏感信息保护已成为企业应用开发的关键环节。Sensitive作为一款基于Java注解的日志脱敏工具框架,能够帮助开发者更加优雅地处理日志打印,有效防止身份证号、手机号、邮箱等敏感信息泄露。本文将详细介绍如何将Sensitive与Spring Boot框架快速集成,从零开始构建一套安全可靠的日志脱敏系统。 ## 准备工作:环境配置与依赖引入 要实现Sensitive

gitblog_00700的博客 178

spring中各个jar的作用

你在练习项目的时候,看着别人的包是不是会觉得不知所踪,根本不知道到底是干什么用的,一起学习一下spring包的大概作用吧! 1.spring.jar   是包含有完整发布模块的单个jar 包。 2 org.springframework.aop   包含在应用中使用Spring的AOP特性时所需的类。 3 org.springframework.asm   Spring独立的asm程序, Spri...

小样样样样样样的博客 246
上一篇: spring-core-4-35 | 注册Spring Bean:如何将BeanDefinition注册到IoC容器?
下一篇: spring-core-4-37 | 初始化Spring Bean:Bean初始化有哪些方式?
sunforraining
博客等级 码龄9年 13粉丝 43原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值