[Spring] Spring5——IOC 简介(二)

news2024/11/30 0:35:35

目录

六、工厂 Bean(Factory)

1、普通 bean

2、工厂 bean

3、示例

七、Bean 的作用域

1、单例和多例

2、如何设置为单实例或多实例

八、Bean 的生命周期

1、生命周期

2、生命周期示例

3、Bean 的后置处理器

4、后置处理器示例

九、XML 的自动装配

1、什么是自动装配

2、byName 示例

3、byType 示例

十、外部属性文件

1、直接配置数据库信息

2、引入外部属性文件配置

十一、基于注解方式的创建对象

1、什么是注解

2、为创建对象提供的注解;

3、基于注解方式实现对象创建

 4、组件扫描的配置

十二、基于注解方式的属性注入

1、@Autowired(针对 Object 类型)

2、@Qualifier(针对 Object 类型)

3、@Resource(针对 Object 类型)

4、@Value(针对普通类型)

十三、完全注解开发


六、工厂 Bean(Factory)

Spring 有两种类型 bean,一种普通 bean,另外一种工厂 bean(FactoryBean)。

1、普通 bean

普通 bean:在配置文件中的 id 定位 bean实例,定义的 class 类型就是返回类型。

2、工厂 bean

工厂 bean:在配置文件定义 bean 类型可以和返回类型不一样

通过两个步骤即可实现工厂 bean:

  • 第一步:创建类,让这个类作为工厂 bean,实现接口 FactoryBean<T>
  • 第二步:实现接口里面的方法,在实现的方法中定义返回的 bean 类型

3、示例

建立一个 Factory 类,获取 Course 实例对象。在 xml 中 bean 类型写的是 Factory 类,但是可以返回 Course(通过继承接口 FactoryBean<T>)

(1)代码

(1-1)Factory 类:

package com.demo.factory;

import com.demo.pojo.Course;
import org.springframework.beans.factory.FactoryBean;

public class Factory implements FactoryBean<Course> {
    @Override
    public Course getObject() throws Exception {
        Course course = new Course();
        course.setName("course01");
        return course;
    }

    @Override
    public Class<?> getObjectType() {
        return null;
    }

    @Override
    public boolean isSingleton() {
        return FactoryBean.super.isSingleton();
    }
}

(1-2)Course 类:

package com.demo.pojo;

public class Course {
    private String name;

    public String getName() {
        return name;
    }

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

    @Override
    public String toString() {
        return "Course{" +
                "name='" + name + '\'' +
                '}';
    }
}

(1-3)FactoryBean.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 http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="CourseFactory" class="com.demo.factory.Factory">

    </bean>

</beans>

(1-4)测试代码

import com.demo.pojo.Course;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class FactoryTest {
    @Test
    public void test() {
        ApplicationContext context = new ClassPathXmlApplicationContext("FactoryBean.xml");
        Course course = context.getBean("CourseFactory", Course.class);
        System.out.println(course);
    }
}

(2)输出结果

七、Bean 的作用域

bean 的作用域,可以设置我们创建的 bean 实例,是单实例还是多实例。默认情况下,Spring 会将 bean 设置为单实例对象。

1、单例和多例

  • 单例就是所有的请求都用一个对象来处理,比如我们常用的service和dao层的对象通常都是单例的;
  • 多例则指每个请求用一个新的对象来处理,比如action; 

单例其实就在内存中该对象只有一个内存对应地址。无论你多少个线程访问那个对象,都是同一个地址。这样节省内存。

(1)单实例的输出结果

可以看到,两个实例的地址是一样的。说明该 bean 对象是一个单实例对象

2、如何设置为单实例或多实例

在 spring 配置文件中的 bean 标签里面有属性(scope)用于设置单实例还是多实例。

(1)scope 的属性值

  • scope = "singleton",表示单实例对象(默认值);
  • scope = "prototype",表示多实例对象;

(2)修改 scope = "prototype" 后

(3)singleton 和 prototype 区别

  • singleton 单实例,prototype 多实例;
  • scope = singleton 时,加载 spring 配置文件时候就会创建单实例对象;
  • scope = prototype 时,不是在加载 spring 配置文件时候创建对象,而是在调用 getBean() 方法时才创建多实例对象;

(4)属性值为 request 和 session

  • scope = "request" 时,创建的对象会放到 request 域中;
  • scope = "session" 时,创建的对象会放到 session 域中;

八、Bean 的生命周期

1、生命周期

Bean 对象从创建到销毁的过程。有如下 5 个步骤:

  • 通过无参构造函数创建 bean 实例;
  • 为 bean 实例的属性设置值或对其他 bean 的引用(如:外部 bean、内部 bean);(调用 set 方法)
  • 调用 bean 的初始化的方法(需要手动写出初始化的方法);
  • bean 可以使用了(对象获取到了);
  • 当容器关闭时候,调用 bean 的销毁的方法(需要手动写出销毁的方法)

2、生命周期示例

(1)代码

(1-1)Course 类

package com.demo.pojo;

public class Course {
    private String name;

    public Course() {
        System.out.println("1.无参构造 bean 实例");
    }

    // 创建执行的初始化方法
    public void initFunc() {
        System.out.println("3.执行初始化方法");
    }

    // 创建销毁的方法
    public void destroyFunc() {
        System.out.println("5.执行销毁方法");
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        System.out.println("2.调用 set 方法");
        this.name = name;
    }

    @Override
    public String toString() {
        return "Course{" +
                "name='" + name + '\'' +
                '}';
    }
}

(1-2)LifeBean.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 http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="course" class="com.demo.pojo.Course" init-method="initFunc" destroy-method="destroyFunc">
        <property name="name" value="C++从入门到入土"></property>
    </bean>

</beans>

(1-3)测试代码

import com.demo.pojo.Course;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class LifeBeanTest {
    @Test
    public void test() {
        ApplicationContext context = new ClassPathXmlApplicationContext("LifeBean.xml");
        Course course = context.getBean("course", Course.class);
        System.out.println("4.getBean 对象:" + course);
        // 最后要手动销毁 bean 实例,Application 的子类才有 close 方法
        ((ClassPathXmlApplicationContext)context).close();
    }
}

(2)输出结果

3、Bean 的后置处理器

Bean 的生命周期除了前面的 5 个步骤外,还有两个步骤,分别位于初始化方法前和初始化方法后

  • 通过无参构造函数创建 bean 实例;
  • 为 bean 实例的属性设置值或对其他 bean 的引用(如:外部 bean、内部 bean);(调用 set 方法)
  • 把 bean 实例传递给 bean 的后置处理器的方法 postProcessBeforeInitialization
  • 调用 bean 的初始化的方法(需要手动写出初始化的方法);
  • 把 bean 实例传递给 bean 的后置处理器的方法 postProcessAfterInitialization
  • bean 可以使用了(对象获取到了);
  • 当容器关闭时候,调用 bean 的销毁的方法(需要手动写出销毁的方法)

4、后置处理器示例

(1)创建类,实现接口 BeanPostProcessor

package com.demo.impl;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;

public class PostProcess implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("初始化之前执行 postProcessBeforeInitialization");
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("初始化之后执行 postProcessAfterInitialization");
        return bean;
    }
}

(2)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 http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="course" class="com.demo.pojo.Course" init-method="initFunc" destroy-method="destroyFunc">
        <property name="name" value="C++从入门到入土"></property>
    </bean>

    <!-- 配置后置处理器 -->
    <bean id="postProcess" class="com.demo.impl.PostProcess"></bean>
</beans>

(3)输出结果

九、XML 的自动装配

1、什么是自动装配

  • 手动装配:通过 <property name="" value="">、外部/内部 Bean、等等,来给属性值赋值,就是手动装配。
  • 自动装配:根据指定的装配规则(属性名称或者属性类型),Spring 自动将匹配的属性值进行注入。

(1)bean 标签属性 autowire,配置自动装配

  • autowire = "byName",表示根据属性名称注入,要求 bean 的 id 值目标属性的属性名一致;
  • autowire = "byType",表示根据属性类型注入,也因此在 xml 中同一类型只能配置 1 个 bean; 

(2)易错点

注意目标类路径所指向的类是否与配置的类一致,比如有很多 Util 类,不论在 java 文件中导入错误的类路径,还是在 xml 中写错了类路径,都无法匹配 set() 方法。

2、byName 示例

(1)代码

(1-1)Employee 类

package com.demo.autowire;

import com.demo.autowire.Department;

public class Employee {
    private Department department;

    @Override
    public String toString() {
        return "Employee{" +
                "department=" + department +
                '}';
    }

    public Department getDepartment() {
        return department;
    }

    public void setDepartment(Department department) {
        this.department = department;
    }
}

(1-2)Department 类

package com.demo.autowire;

public class Department {
    private String name;

    public String getName() {
        return name;
    }

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

}

(1-3)AutoWireBean.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 http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="employee" class="com.demo.autowire.Employee" autowire="byName">

    </bean>
    <bean id="department" class="com.demo.autowire.Department">
        <property name="name" value="技术部门"></property>
    </bean>

</beans>

(1-4)测试代码

import com.demo.autowire.Employee;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class AutoWireBeanTest {
    @Test
    public void test() {
        ApplicationContext context = new ClassPathXmlApplicationContext("AutoWireBean.xml");
        Employee employee = context.getBean("employee", Employee.class);
        System.out.println(employee);
        System.out.println(employee.getDepartment().getName());
    }
}

(2)输出结果

3、byType 示例

将 autowire = "byName" 改成 byType 即可。但是如果使用 byType,同一个类型就只能有 1 个 bean。

在实际开发中,更多情况下使用的是注解的方法来做到自动注入。

十、外部属性文件

当一个类中的属性非常的多的时候,使用 <property> 的方式进行注入,既麻烦又不好维护。对于一些固定的属性值,我们可以统一放到某个配置文件中,再用 xml 配置文件去读取相关信息。(比如数据库连接池使用的就是 properties 文件)

下面以数据库的直接配置和引用外部文件作比较为例。

1、直接配置数据库信息

下面用一个自定义的 Druid 类,包含一个数据库连接池属性,然后通过写死配置信息的方式注入 Druid 的数据库连接池。

需要用到 druid 和 jdbc,jdbc 根据自己使用的数据库引入依赖,导 jar 包或者 maven 都可以。

(1)配置 druid 连接池

<?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 http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="druid" class="com.demo.pojo.Druid">
        <property name="dataSource" ref="dataSource"></property>
    </bean>

    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="org.postgresql.Driver"></property>
        <property name="url" value="jdbc:postgresql://localhost:5432/MyDatabase"></property>
        <property name="username" value="postgres"></property>
        <property name="password" value="123456"></property>
    </bean>


</beans>

(2)Druid 类(包含 DruidDataSource 属性)

package com.demo.pojo;

import com.alibaba.druid.pool.DruidDataSource;

public class Druid {
    private DruidDataSource dataSource;

    public void setDataSource(DruidDataSource dataSource) {
        this.dataSource = dataSource;
    }

    public DruidDataSource getDataSource() {
        return dataSource;
    }

}

(3)测试代码

import com.alibaba.druid.pool.DruidDataSource;
import com.demo.pojo.Druid;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class DruidTest {
    @Test
    public void test1() {
        ApplicationContext context = new ClassPathXmlApplicationContext("Druid.xml");
        Druid druid = context.getBean("druid", Druid.class);
        try {
            DruidDataSource druidDataSource = druid.getDataSource();
            System.out.println(druidDataSource.getConnection());
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}

(4)输出结果

2、引入外部属性文件配置

引入外部配置文件,只需要在上面的基础上修改 xml 配置文件即可:

  • xml 文件要添加两个命名空间:util 和 context;
  • property 的 value 属性值改用 EL 表达式的形式;

(1)修改 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"
       xmlns:util="http://www.springframework.org/schema/util"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd
            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">


    <context:property-placeholder location="druid.properties"/>

    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="${prop.driverClassName}"></property>
        <property name="url" value="${prop.url}"></property>
        <property name="username" value="${prop.username}"></property>
        <property name="password" value="${prop.password}"></property>
    </bean>

    <bean id="druid" class="com.demo.pojo.Druid">
        <property name="dataSource" ref="dataSource"></property>
    </bean>


</beans>

(2)duird.properties

prop.url = jdbc:postgresql://localhost:5432/bookmarket
prop.username = postgres
prop.password = 123456
prop.driverClassName = org.postgresql.Driver

十一、基于注解方式的创建对象

1、什么是注解

注解是代码特殊标记,格式:@注解名称(属性名称=属性值, 属性名称=属性值..)

  • 注解可以作用在类上面,方法上面,属性上面
  • 使用注解目的:简化 xml 配置,减少 xml 代码的书写

2、为创建对象提供的注解;

  • @Component
  • @Service,一般用于 Service 层
  • @Controller,一般用于 Web 层
  • @Repository,一般用于 Dao 层(持久层)

上面四个注解功能是一样的,都可以用来创建 bean 实例,只是为了区分不同的层次而用不同的名称

3、基于注解方式实现对象创建

(1)引入依赖 spring-aop-5.2.6.RELEASE

需要注意的是,此时 JDK 版本如果不兼容,就会报错:

  • 17-21,建议使用 6.0 以上的版本;
  • 8-16,建议使用 5.3 的版本,其中 16 最特殊,只能用 5.3 的版本;

(2)开启组件扫描,使得 spring 可以找到我们写的类

在 xml 配置文件中,添加 context 命名空间,然后写上:

(3)创建类,在类上面添加创建对象注解

@Component,包括另外几个注解,其中的 value 属性值,代表了 <bean> 中的 id 属性值。而如果没有显式地写出 value,那么默认值就是类名且首字母小写。

package com.demo.service.impl;

import com.demo.dao.UserDao;
import com.demo.service.UserService;
import org.springframework.stereotype.Component;

@Component(value = "userService")
public class UserServiceImpl implements UserService {
    private UserDao userDao;

    public UserDao getUserDao() {
        return userDao;
    }

    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }

    @Override
    public void func() {
        System.out.println("调用 UserService 的 func");
        userDao.func();
    }
}

(4)测试代码

import com.demo.service.UserService;
import com.demo.service.impl.UserServiceImpl;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class AopBeanTest {
    @Test
    public void test() {
        ApplicationContext context = new ClassPathXmlApplicationContext("AopBean.xml");
        UserService userService = context.getBean("userService", UserServiceImpl.class);
        userService.func();
    }

}

 4、组件扫描的配置

前面我们知道,对于一个 base-package,Spring 会扫描这个目录下的所有 class。而通过添加其他配置,可以规定哪些需要扫描、哪些不需要扫描。

(1)use-default-filters

当它的值为 false 时,表示不使用默认的 filter,而使用自己配置的 filter。

(2)如何自己配置 filter

(2-1)设置需要扫描哪些内容

  • 在组件扫描中,设置 use-default-filters="false",然后嵌套 context:include-filter。

(2-2)设置不需要扫描哪些内容,而是扫描其他的所有内容

  • 在组件扫描中,不需要设置 use-default-filters="false",直接嵌套 context:exclude-filter。
  • (因为还要扫描其他所有内容,所以不用设置 use-default-filters="false")

(3)内容如何规定

在 context:include-filter 和 context:exclude-filter 中,有两个属性配合使用:

<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>

表示目标内容就是带有注解 @Controller 的类

十二、基于注解方式的属性注入

1、@Autowired(针对 Object 类型)

@Autowired:根据属性类型进行自动装配。

其缺点在于,如果一个接口有多个实现类(比如有 DaoImpl1、DaoImpl2),那么就无法得知在 UserServiceImpl 中的属性 UserDao,具体应该被注入哪一个实现类,因此 @Autowired 只适合仅有一种实现类的情况。

(1)创建 service 和 dao 对象,在 service 和 dao 的 Impl 类中添加创建对象注解

Service 添加 @Service,Dao添加 @Repository。

(2)在 service 类添加 dao 类型属性,在属性上面使用注解

注意:不需要添加 set 方法,Spring 已经封装好 set 方法。

(3)代码

(3-1)UserDaoImpl 类

package com.demo.dao.impl;

import com.demo.dao.UserDao;
import org.springframework.stereotype.Repository;

@Repository
public class UserDaoImpl implements UserDao {
    @Override
    public void func() {
        System.out.println("调用 UserDao 的 func");
    }
}

(3-2)UserServiceImpl 类

package com.demo.service.impl;

import com.demo.dao.UserDao;
import com.demo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class UserServiceImpl implements UserService {
    @Autowired
    private UserDao userDao;

    @Override
    public void func() {
        System.out.println("调用 UserService 的 func");
        userDao.func();
    }
}

(3-3)AnnotationBean.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"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
                           http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <context:component-scan base-package="com.demo" use-default-filters="false">
        <context:include-filter type="annotation" expression="org.springframework.stereotype.Repository"/>
        <context:include-filter type="annotation" expression="org.springframework.stereotype.Service"/>
    </context:component-scan>

</beans>

(3-4)测试代码

import com.demo.service.UserService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class AnnotationBeanTest {
    @Test
    public void test() {
        ApplicationContext context = new ClassPathXmlApplicationContext("AnnotationBean.xml");
        UserService userService = context.getBean("userServiceImpl", UserService.class);
        userService.func();
    }

}

(4)输出结果

2、@Qualifier(针对 Object 类型)

@Qualifier:根据属性名称进行自动装配,并且需要跟 @Autowired 一起使用

当有多个实现类,比如:Impl1、Impl2,这时候 @Autowired 配合上 @Qualifier(value = "Impl1"),就可以明确注入 Impl1 这个实现类。

简单来说,就是 @Autowired 确定了接口,Qualifier 确定了具体的实现类。

(1)在 AnnotationBean.xml 和 测试代码 不变的情况下,修改以下内容

(1-1)UserDaoImpl1 类

package com.demo.dao.impl;

import com.demo.dao.UserDao;
import org.springframework.stereotype.Repository;

@Repository(value = "userDaoImpl1")
public class UserDaoImpl1 implements UserDao {
    @Override
    public void func() {
        System.out.println("调用 UserDaoImpl1 的 func");
    }
}

(1-2)UserDaoImpl2 类

package com.demo.dao.impl;

import com.demo.dao.UserDao;
import org.springframework.stereotype.Repository;

@Repository(value = "userDaoImpl2")
public class UserDaoImpl2 implements UserDao {
    @Override
    public void func() {
        System.out.println("调用 UserDaoImpl2 的 func");
    }
}

(1-3)UserServiceImpl 类

package com.demo.service.impl;

import com.demo.dao.UserDao;
import com.demo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

@Service
public class UserServiceImpl implements UserService {
    @Autowired
    @Qualifier(value = "userDaoImpl2")
    private UserDao userDao;

    @Override
    public void func() {
        System.out.println("调用 UserService 的 func");
        userDao.func();
    }
}

(2)输出结果

3、@Resource(针对 Object 类型)

@Resource:可以根据类型注入,也可以根据名称注入。

  • @Resource:根据类型注入;
  • @Resource(name = "userDaoImpl1"):根据名称注入

需要注意的是,@Resource 是 javax 提供的注解,不是 Spring 官方提供的,因此建议还是使用 @Autowired 和 @Qualifier。

(1)修改 UserServiceImpl 类

package com.demo.service.impl;

import com.demo.dao.UserDao;
import com.demo.service.UserService;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

@Service
public class UserServiceImpl implements UserService {
    @Resource(name = "userDaoImpl2")
    private UserDao userDao;

    @Override
    public void func() {
        System.out.println("调用 UserService 的 func");
        userDao.func();
    }
}

(2)输出结果

4、@Value(针对普通类型)

@Value:注入普通类型属性。

  • @Value(value = "MyValue"),表示给属性注入值为 MyValue。

十三、完全注解开发

不需要使用 xml 文件去配置,仅使用注解,就可以实现创建对象和属性注入。

(1)创建配置类,替代 xml 配置文件:

package com.demo.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration // 作为配置类,代替 xml 配置文件
@ComponentScan(basePackages = {"com.demo"})
public class SpringConfig {

}

(2)测试代码

import com.demo.config.SpringConfig;
import com.demo.service.UserService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class AnnotationConfigTest {
    @Test
    public void test() {
        ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
        UserService userService = context.getBean("userServiceImpl", UserService.class);
        userService.func();
    }

}

(3)输出结果

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1055058.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

JavaScript设计模式

✨JavaScript设计模式 &#x1f380;设计模式 在 面向对象软件设计中针对特定问题的简洁而优雅的解决方案 &#x1f390;常见的设计模式 &#x1f384;1. 工厂模式 在JavaScript中&#xff0c;工厂模式的表现形式就是一个调用即可返回新对象的函数 // ------------- 工厂模…

gitlab配置webhook限制提交注释

一、打开gitlab相关配置项 vim /etc/gitlab/gitlab.rb gitlab_shell[custom_hooks_dir] "/etc/gitlab/custom_hooks" 二、创建相关文件夹 mkdir -p /etc/gitlab/custom_hooks mkdir -p /etc/gitlab/custom_hooks/post-receive.d mkdir -p /etc/gitlab/custom_h…

springboot和vue:九、v-for中的key+vue组件化开发

v-for中的key 目的 现在想要实现这样的一种效果&#xff0c;页面上存在初始姓名表单&#xff0c;同时存在输入框&#xff0c;输入姓名后点击添加按钮可以将新输入的姓名加入显示的姓名表单中。 代码 <!DOCTYPE html> <html lang"en"><head><…

数学建模Matlab之数据预处理方法

本文综合代码来自文章http://t.csdnimg.cn/P5zOD 异常值与缺失值处理 %% 数据修复 % 判断缺失值和异常值并修复&#xff0c;顺便光滑噪音&#xff0c;渡边笔记 clc,clear;close all; x 0:0.06:10; y sin(x)0.2*rand(size(x)); y(22:34) NaN; % 模拟缺失值 y(89:95) 50;% 模…

Mars3d的graphic/entity/model示例的glb的ModelEntity修改颜色失效说明

1.Mars3d的graphic/entity/model示例的glb的ModelEntity修改颜色失效说明 2.测试时发现示例的glb的ModelEntity使用setStyle()修改颜色没成功 setTimeout(() > { graphicModel.setStyle({ color: "red" }) }, 500) 相关链接 1.http://mars3d.cn/editor-vue.html?…

使用sqlmap总是提示需要302跳转重新登录的解决方法

如果在命令中不指定cookie&#xff0c;sqlmap在执行时会提示需要重新登录 如果给了cookie但发现还是提示需要重新登录&#xff0c;且按它给的提示发现还是找不到注入点&#xff0c;原因是url没有加引号 url加了双引号后解决问题

MySQL在线修改表结构-PerconaTookit工具

在线修改表结构必须慎重 在业务系统 运行 过程中随意删改字段&#xff0c;会 造成重大事故。 常规的做法是&#xff1a;业务停机&#xff0c;再 维护表结构 比如&#xff1a;12306 凌晨 0 点到早上 7 点是停机维护 如果是不影响正常业务的表结构是允许在线修改的。 比如&…

16数据处理

plotly 设置x/y轴名称 yaxis_title‘金额(元)’,xaxis_title‘日期’ fig px.line(df_grouped, x"Order_time", y"Money", title日销图) fig.update_layout(yaxis_title金额(元),xaxis_title日期, xaxis_tickformat%Y-%m-%d,yaxis_tickformat 0.2f) fig…

多线程案例 - 单例模式

单例模式 ~~ 单例模式是常见的设计模式之一 什么是设计模式 你知道象棋,五子棋,围棋吗?如果,你想下好围棋,你就不得不了解一个东西,”棋谱”,设计模式好比围棋中的 “棋谱”. 在棋谱里面,大佬们,把一些常见的对局场景,都给推演出来了,照着棋谱来下棋,基本上棋力就不会差到哪…

面试必考精华版Leetcode437. 路径总和 III

题目&#xff1a; 代码&#xff08;首刷看解析&#xff0c;暴力法&#xff09;&#xff1a; class Solution { public:long rootSum(TreeNode* root,long targetSum){if(!root) return 0;long res0;if(root->valtargetSum){res;} resrootSum(root->left,targetSum-root-…

2022年9月及10月

9月 1.Halcon12的HObject和Hobject halcon12 可以用HObject&#xff0c;也可以用Hobject&#xff0c;用法都一样 包括HalconCpp.h 如果附加目录中&#xff1a; C:\Program Files\MVTec\HALCON-12.0\include\halconcpp\ 在前面&#xff0c;则用 HalconCpp::HObject 如果附加目录…

【论文阅读】DiffusionDet: Diffusion Model for Object Detection

原文链接&#xff1a;https://arxiv.org/abs/2211.09788 1. 引言 过去的目标检测方法依赖手工设计的候选对象&#xff08;如滑动窗口、区域提案、锚框和参考点&#xff09;&#xff1b;或是依赖可学习的物体查询。   本文使用更加简单的方法&#xff0c;随机初始化边界框&am…

防火墙基础之H3C防火墙和三层交换机链路聚合的配置

H3C防火墙和三层交换机链路聚合的配置 原理概述&#xff1a; 防火墙&#xff08;英语&#xff1a;Firewall&#xff09;技术是通过有机结合各类用于安全管理​与筛选的软件和硬件​设备&#xff0c;帮助计算机网络于其内、外网之间构建一道相对隔绝的保护屏障&#xff0c;以保…

Docker从认识到实践再到底层原理(七)|Docker存储卷

前言 那么这里博主先安利一些干货满满的专栏了&#xff01; 首先是博主的高质量博客的汇总&#xff0c;这个专栏里面的博客&#xff0c;都是博主最最用心写的一部分&#xff0c;干货满满&#xff0c;希望对大家有帮助。 高质量博客汇总 然后就是博主最近最花时间的一个专栏…

如何让你网站统计的更加精准?

引言 最近对比了自己网站在Cloudflare Analytics和51.la统计的数据&#xff0c;结果发现数值差距的比较大&#xff0c;这是为什么&#xff1f; 经过了摸索&#xff0c;发现了以下几个情况&#xff1a; 广告插件的拦截&#xff0c;大部分广告插件都会拦截网站统计&#xff0c…

select实现服务器并发

select的TCP服务器代码 #include <stdio.h> #include <unistd.h> #include <string.h> #include <sys/types.h> #include <sys/socket.h> #include <arpa/inet.h> #include <netinet/in.h> #include <sys/select.h> #include…

【教学类-36-10】20230908方脸爷爷和圆脸奶奶(midjounery-niji)(中班:《我爱我家》数:连线、涂色)

背景需求&#xff1a; 领导们鼓动我去参加上海市高级职称评审&#xff08;科研成果比较多&#xff09;&#xff0c;为下一轮保教主任评高级“探探路”。虽然自我感觉道行浅薄&#xff0c;无缘高级&#xff0c;但领导给机会&#xff0c;自然要参与一下&#xff0c;努力了解整个…

10.1select并发服务器以及客户端

服务器&#xff1a; #include<myhead.h>//do-while只是为了不让花括号单独存在&#xff0c;并不循环 #define ERR_MSG(msg) do{\fprintf(stderr,"%d:",__LINE__);\perror(msg);\ }while(0);#define PORT 8888//端口号1024-49151 #define IP "192.168.2.5…

10月1日作业

汇编指令合集 用select实现服务器并发代码 #include<myhead.h> #define IP "192.168.0.106" #define PORT 8888int main(int argc, const char *argv[]) {//新建套接字文件int sfd socket(AF_INET, SOCK_STREAM, 0);if(sfd < 0){ERR_MSG("socket&quo…

imgui开发笔记<4>、image-slider online

在线滑条二值化。 // // Created by sry on 2021/6/30. //#include"imgui.h" #include "imgui_impl_glfw.h" #include "imgui_impl_opengl3.h" #include <stdio.h> // Initialize with gl3wInit() #include<GL/gl3w.h> // Include …