Spring

bean的实例化

1.通过构造方法实例化

1.Spring通过setter方法往bean里注入他依赖的bean。所以记得提供提供对应的setter方法

package com.example;

public class MyClass {

 
MyOtherClass myOtherClass;

public void setMyOtherClass(MyOtherClass myOtherClass)
{
this.myOtherClass=myOtherClass;
}

public void run(){
myOtherClass.run();
}

}

1.定义一个SpringConfiguration  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  name属性是bean的别名,可多个,使用, ; 空格 分隔-->
    <bean id="myOtherBean" name="name1 name2 name3 " class="com.example.MyOtherClass">
        <!-- 可以在这里设置myOtherBean的属性 -->
    </bean>

    <!-- 定义一个简单的Bean,依赖于myOtherBean -->
    <bean id="myBean" class="com.example.MyClass">
        <!-- property name代表给哪个属性赋值,ref标识给这个属性赋值哪个名字的bean -->
        <property name="propertyName" ref="myOtherBean"/>
    </bean>

</beans>

2.通过静态工厂实例化

通过此方式可以提前进行一些配置

1.创建一个工厂类,里面创建类的实例化方法

public class MyBeanFactory {
    public static MyClass createMyClass() {
        system.out.println("这里开始你的配置")
        return new MyClass("初始化参数");
    }
}

2.在xml文件中配置工厂中的bean

<bean id="myBean" class="com.example.MyBeanFactory" factory-method="createMyClass"/>

3.通过实例化工厂实例化bean

1. 定义工厂类

首先,创建一个工厂类,这个类包含一个实例方法,该方法返回要创建的Bean对象。

public class MyBeanFactory {
    public MyClass createMyClass() {
        return new MyClass("初始化参数");
    }
}

2. 在Spring配置中定义Bean

接下来,在Spring的配置文件(如XML配置)中,定义工厂类的Bean和使用工厂方法创建的Bean。

<bean id="myBeanFactory" class="com.example.MyBeanFactory"/>

<bean id="myBean" factory-bean="myBeanFactory" factory-method="createMyClass"/>

4.通过继承FactoryBean接口实例化bean

1. 实现FactoryBean接口

首先,你需要创建一个类实现FactoryBean接口。该接口要求实现三个方法:getObject()getObjectType()isSingleton()

import org.springframework.beans.factory.FactoryBean;

public class MyBeanFactory implements FactoryBean<MyClass> {

    @Override
    public MyClass getObject() throws Exception {
        // 创建并返回Bean实例
        return new MyClass("初始化参数");
    }

    @Override
    public Class<?> getObjectType() {
        // 返回Bean的类型
        return MyClass.class;
    }

    @Override
    public boolean isSingleton() {
        // 指示该Bean是否为单例
        return true;
    }
}
<bean id="myBean" class="com.example.MyBeanFactory"/>

bean的生命周期

在XML配置中,使用<bean>元素定义Bean。常用的属性包括:

  • class:指定Bean的实现类。
  • id:给Bean命名,便于在其他地方引用。
  • init-method:指定初始化方法的名称。
  • destroy-method:指定销毁方法的名称。

1.创建bean类

package com.example;

public class MyBean {

    public void initMethod() {
        System.out.println("MyBean 初始化");
    }

    public void destroyMethod() {
        System.out.println("MyBean 销毁");
    }
}
2. 编写XML配置文件

    <bean id="myBean" class="com.example.MyBean" 
          init-method="initMethod" 
          destroy-method="destroyMethod"/>
</beans>

 摧毁操作要关闭容器才会执行到。

public class MainApp {
    public static void main(String[] args) {
        // 加载Spring配置文件
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
context.registerShootDownHook;//关闭虚拟机前关闭容器
        
        // 获取Bean
        MyBean myBean = (MyBean) context.getBean("myBean");

        // 在这里可以使用myBean
        // ...

        // 关闭上下文
     //  context.close(); // 这将调用destroyMethod,暴力方法

    }
}

还可以通过实现接口重写方法的方式来固定配置格式

 1.InitializingBean接口

当你实现InitializingBean接口时,需要重写afterPropertiesSet()方法,这个方法在Bean的所有属性设置完毕后调用,适合放置初始化逻辑。

2. DisposableBean接口

实现DisposableBean接口需要重写destroy()方法,此方法在Bean被销毁时调用,适合放置清理逻辑。

public class MyBean implements InitializingBean, DisposableBean {

    private String message;

    public void setMessage(String message) {
        this.message = message;
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        // 初始化逻辑
        System.out.println("MyBean 初始化: " + message);
    }

    @Override
    public void destroy() throws Exception {
        // 清理逻辑
        System.out.println("MyBean 销毁");
    }
}

bean的属性注入

1.setter方法注入

public class MyBean {

    private String dependency;

    // 提供setter方法
    public void setDependency(Stringdependency) {
        this.dependency = dependency;
    }

}
  <bean id="myBean" class="com.example.MyBean">
        <property name="dependency" value="你好啊"/><!...基本数据类型使用value注入..>
    </bean>

2.构造方法注入

package com.example;

public class MyBean {
    private Dependency dependency;

    // 构造方法
    public MyBean(Dependency dependency) {
        this.dependency = dependency;
    }

    public void execute() {
        dependency.doSomething();
    }
}
   <bean id="dependency" class="com.example.Dependency"/>
    
    <bean id="myBean" class="com.example.MyBean">
        <constructor-arg ref="dependency"/>
    </bean>

如果你的构造函数有多个参数,你可以通过 name 指定参数名称:

<constructor-arg name="dependency" ref="dependency"/>
<constructor-arg name="anotherDependency" ref="anotherDependency"/>

自动装配

使用自动装配就不用手动的配置此bean的依赖bean。

基本用法

  1. 按类型自动装配
xmlCopy Code

<bean id="myBean" class="com.example.MyBean" autowire="byType"/>

在这种情况下,Spring会查找类型为 MyBean 的构造函数参数,并自动注入匹配的 Bean。

  1. 按名称自动装配

xmlCopy Code

<bean id="myBean" class="com.example.MyBean" autowire="byName"/>

在此情况下,Spring会查找与 Bean ID 匹配的名称并进行注入。

注意:还是要提供对应的setter方法。

集合注入

在Spring的XML配置中,注入集合属性(如列表、集合、映射等)是一个常见的需求。以下是如何通过XML配置注入集合属性的几种方式:

1. 注入列表(List)

<bean id="myBean" class="com.example.MyBean"> 
<property name="myList"> 
<list> 
<value>Item1</value> 
<value>Item2</value> 
<value>Item3</value> 
</list> 
</property> </bean>

2. 注入集合(Set)

<bean id="myBean" class="com.example.MyBean"> 
<property name="mySet"> 
<set> 
<value>ItemA</value>
 <value>ItemB</value> 
<value>ItemC</value> 
</set> 
</property> 
</bean>

3. 注入映射(Map)

<bean id="myBean" class="com.example.MyBean">
 <property name="myMap">
 <map>
 <entry key="key1" value="value1"/>
 <entry key="key2" value="value2"/>
 <entry key="key3" value="value3"/> 
</map>
 </property> 
</bean>

示例类

假设我们有一个类 MyBean,其中包含一个列表、一个集合和一个映射

public class MyBean {
    private List<String> myList;
    private Set<String> mySet;
    private Map<String, String> myMap;

    // setters
    public void setMyList(List<String> myList) {
        this.myList = myList;
    }

    public void setMySet(Set<String> mySet) {
        this.mySet = mySet;
    }

    public void setMyMap(Map<String, String> myMap) {
        this.myMap = myMap;
    }

    // 方法来打印集合内容
    public void printCollections() {
        System.out.println("List: " + myList);
        System.out.println("Set: " + mySet);
        System.out.println("Map: " + myMap);
    }
}

配置文件

当我们要使用外部类进行属性配置时,例如要连接数据库,这时候我们要将数据库的类交给IOC容器管理,并且给类中的属性,例如用户名,密码等数据项进行配置时,我们通过属性注入的方式进行配置,但是最好这些配置属性能抽离出来,于是我们把他放到配置文件中,xml配置中只要引用properties属性值即可注入。

1.创建properties文件

service.url=http://example.com/api

2.我们在xml文件中首先开启context命名空间。并加载配置文件

<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">
//加载配置文件属性,location多个属性可用逗号分隔
    <context:property-placeholder location="classpath:application.properties"/>
    <context:component-scan base-package="com.example"/>
</beans>

3.配置bean属性,通过表达式引用properties

    <bean id="thirdPartyService" class="com.example.ThirdPartyService">
        <property name="url" value="${service.url}"/>
    </bean>

注解开发

注解开发直接在类上加上@Component注解即可替代XML配置bean。但是需要spring去扫描这个注解才能使用。

于是XML文件中需要配置扫描包Component-scan组件的扫描范围。

<context:component-scan base-package="com.example"/>

Spring3.0开启了纯注解开发。使用java配置类代替配置文件。

1.定义一个配置类,上面加上@Configuration注解指明他是配置类

  1. @Configuration:标记一个类为配置类,它可以包含 Bean 的定义,但仅仅使用 @Configuration 并不会触发组件扫描。

  2. @ComponentScan:如果需要扫描特定包中的组件,需要在配置类中显式添加 @ComponentScan 注解。这个注解的作用是告诉 Spring 在指定的包中查找带有特定注解的类并将其注册为 Spring 的 Bean。

  3. 默认行为:如果没有配置 @ComponentScan,Spring 会扫描配置类本身所在的包(及其子包),但这仅限于配置类本身,并不会扫描其他类。

@ComponentScan指定包中组件扫描范围
@PropertySource // 加载properties文件

@Configuration
@ComponentScan(basePackages = "com.example") // 自动扫描指定包中的组件
@PropertySource("classpath:application.properties") // 加载properties文件
public class AppConfig {


}

在主程序中,可以使用AnnotationConfigApplicationContext来获取容器:

public class Main {
    public static void main(String[] args) {
        ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
        ThirdPartyService service = context.getBean(ThirdPartyService.class);
        // 使用service
    }
}

bean的作用范围

pring中Bean的作用范围(Scope)决定了Bean的创建和生命周期。常见的作用范围包括:

  1. singleton(单例):

    • 默认作用域。
    • Spring容器只会创建一个Bean实例,并在整个应用上下文中共享这个实例。
    @Bean 
    @Scope("singleton") 
    public MyBean myBean() { 
    return new MyBean(); }

  2. prototype(原型):

    • 每次请求都会创建一个新的Bean实例。
    • 对于每个getBean()调用,Spring容器会返回一个新的实例。
     
    @Bean
    @Scope("prototype") 
    public MyBean myBean() { 
    return new MyBean(); }

bean的生命周期

在Spring框架中,Bean的生命周期可以通过多种注解进行管理,主要包括以下几种注解:

1. @PostConstruct

  • 用途:用于标注在一个方法上,表示该方法将在Bean的依赖注入完成后被调用。可以用于执行初始化逻辑。

  • 使用示例

     
    public class MyBean {
    
        @PostConstruct
        public void init() {
            // 初始化逻辑
            System.out.println("Bean is initialized");
        }
    }
    

2. @PreDestroy

  • 用途:用于标注在一个方法上,表示该方法将在Bean被销毁之前被调用。可以用于执行清理工作。

  • 使用示例

     
    public class MyBean {
    
        @PreDestroy
        public void cleanup() {
            // 清理逻辑
            System.out.println("Bean is being destroyed");
        }
    }
    

3. @Bean(initMethod = "methodName") 和 @Bean(destroyMethod = "methodName")

  • 用途:在@Configuration类中定义Bean时,可以通过这两个属性指定初始化和销毁的方法。

  • 使用示例

     
    @Configuration
    public class AppConfig {
    
        @Bean(initMethod = "init", destroyMethod = "cleanup")
        public MyBean myBean() {
            return new MyBean();
        }
    }
    
    public class MyBean {
    
        public void init() {
            // 初始化逻辑
        }
    
        public void cleanup() {
            // 清理逻辑
        }
    }
    

 依赖注入

@Autowired

使用@Autowired注解。不需要提供对应setter方法,他通过暴力反射给属性注入值。可以用于构造器、字段和方法。

@Component
public class UserService {

    private final UserRepository userRepository;

    @Autowired
    public UserService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    // 业务逻辑方法
}

@Qualifier

用途:在存在多个相同类型的Bean时,结合@Autowired使用,以指定具体的Bean。

@Component
public class UserService {

    private final UserRepository userRepository;

    @Autowired
    public UserService(@Qualifier("specificUserRepository") UserRepository userRepository) {
        this.userRepository = userRepository;
    }
}

@Value

用途:用于注入外部化配置,如properties文件中的值。记得要在spring配置文件上加注解@PropertySource("classpath:application.properties") // 加载properties文件

@Component
public class AppConfig {

    @Value("${app.name}")
    private String appName;

    // Getter和Setter
}

管理第三方bean

当我们要管理第三方bean时,不能在别人的代码上加上注解,于是可以把他放到配置类中。

通过@Bean注解方式来定义bean。将当前方法的返回值对象交给IOC容器进行管理。通过注解的name/value属性指定bean名称,默认为方法名。

@Configuration
public class CommonConfig {
//声明bean对象
@Bean
public SAXReader saxReader(){
return new SAXReader();
 
}

第三方bean想要进行依赖注入,直接在方法中指定形参即可。

@Configuration
public class CommonConfig {
//声明bean对象
@Bean
public SAXReader saxReader(Service service){
service.方法;
return new SAXReader();
 
}

但是如果把他放到spring的配置类里,显得不是那么回事儿,这是第三方配置类,跟spring没关系。于是我们把他放到另一个文件中。

方式一:

这时候可以自己定义另一个配置类,上面加上@Configuration注解。

方式二:

在配置类上使用@Import注解,它能够导入其他配置类或者 普通类。将类加入IOC容器中

@Configuration
@Import(OtherConfig.class) // 导入其他配置类
public class MainConfig {
    // Bean 定义
}

答疑: 

问:不使用componentScan,他会扫描到配置类吗?

答:使用 @Configuration 注解的类会被注册,但前提是这些类在主应用类所在包或通过其他方式(如 @Import)被显式提及。(例如主类通过注解获取IOC容器)。

问:@ComponentScan 注解会去注册配置类吗

答:是的,@ComponentScan 注解会注册指定包及其子包中的所有 Spring 组件,包括配置类(使用 @Configuration 注解的类)、服务类(使用 @Service 注解的类)、控制器类(使用 @Controller 注解的类)等。

问:也就是说,spring配置类假如被主类提及,那他包下的其他configuration配置类也会被注册吗

答:默认行为:这是因为 @ComponentScan 默认只扫描配置类所在的包及其子包。

问:@Import注解他能把普通类注册到IOC容器中,不需要CompontentScan扫描吗

答:是的,@Import 确实可以将普通类注册到 Spring 的 IOC 容器中,而不需要通过 @ComponentScan 进行扫描。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值