有谁做彩票网站吗,wordpress建站社区,微信文件传输网页版入口,无锡百度推广开户我们知道可以通过Spring当中提供的注解Component以及它的三个衍生注解#xff08;Controller、Service、Repository#xff09;来声明IOC容器中的bean对象#xff0c;同时我们也学习了如何为应用程序注入运行时所需要依赖的bean对象#xff0c;也就是依赖注入DI。
本篇主要…我们知道可以通过Spring当中提供的注解Component以及它的三个衍生注解Controller、Service、Repository来声明IOC容器中的bean对象同时我们也学习了如何为应用程序注入运行时所需要依赖的bean对象也就是依赖注入DI。
本篇主要介绍IOC容器中Bean的使用细节 如何从IOC容器中手动的获取到bean对象 bean的作用域 管理第三方的bean对象重点
1、如何从IOC容器中手动的获取到bean对象
获取Bean
默认情况下SpringBoot项目在启动的时候会自动的创建IOC容器(也称为Spring容器)并且在启动的过程当中会自动的将bean对象都创建好存放在IOC容器当中。应用程序在运行时需要依赖什么bean对象就直接进行依赖注入就可以了。
而在Spring容器中提供了一些方法可以主动从IOC容器中获取到bean对象下面介绍3种常用方式
1根据name获取bean
Object getBean(String name)2根据类型获取bean
T T getBean(ClassT requiredType)3根据name获取bean带类型转换
T T getBean(String name, ClassT requiredType)思考要从 IOC容器 当中来获取到 bean对象需要 先拿到 IOC容器对象怎么样才能拿到IOC容器呢
想获取到IOC容器直接将 IOC容器对象 注入进来就可以了java中万物皆对象。
step1: 创建 bean 容器
Mapper接口
Mapper
public interface UserMapper {//查询所有门派Select(select * from sects)ListSect selectAll();
}业务实现类: Service
public class UserServiceImpl implements UserService {Autowiredprivate UserMapper userMapper ;Overridepublic ListSect getAllSects() {ListSect sects sectsMapper.selectAll();return sects;}
}控制器
RestController
Slf4j
public class UserController {Autowiredprivate UserService userService;GetMapping(/get/all)public Result getAll() {ListSect sects sectsService.getAllSects();return Result.success(sects);}
}step2: 获取 Bean 容器
测试类
import org.springframework.context.ApplicationContext;SpringBootTest
class TianlongManagementApplicationTests {Autowiredprivate ApplicationContext applicationContext;Testpublic void testGetBean() {//根据bean的名称获取SectsController bean1 (UserController) applicationContext.getBean(userController);System.out.println(bean1);//根据bean的类型获取SectsController bean2 applicationContext.getBean(UserController.class);System.out.println(bean2);//根据bean的名称及类型获取SectsController bean3 applicationContext.getBean(userController, UserController.class);System.out.println(bean3);}
}输出的bean对象地址值一样说明在IOC容器中SectsController这个bean是 单例的。那能否将bean对象设置为非单例
说到这笔者之前想过一个问题为什么在SpringBoot项目中都是Controller类、ServiceImpl实现类和Mapper接口需要添加Componet及其衍生注解而我们写的POJO实现类却不用添加POJO也是一个一个的类在项目里也需要创建对象为什么这些POJO对象不需要添加到IOC容器来管理呢如下图Sects这个实现类并没有添加Component注解
谈一下我的拙见首先需要知道为啥Spring框架IOC控制反转很重要因为通过这个可以实现Controller、Service、DAO三层的解耦大白话就是当Controller需要用ServiceImpl对象就不用new的方式创建而是直接通过DI依赖注入从IOC容器中拿对象。
明白了上面这一点我们想想为啥POJO实现类和一些工具类不用加入IOC容器 原因一普通的POJO类、工具类通常是不涉及业务逻辑的辅助功能不涉及复杂的依赖关系和配置因此不需要被IOC容器管理 原因二Controller、Service和Mapper这三层主要是处理业务而普通的POJO类一般用于封装数据封装数据意味着每次封装的数据可能不同也就是每次对象不同交给IOC容器管理反而更复杂。
2、bean的作用域
在前面我们提到的IOC容器当中默认bean对象是单例模式(只有一个实例对象)。那么如何设置bean对象为非单例呢需要设置bean的作用域。
在Spring中支持五种作用域后三种在web环境才生效
作用域说明singleton容器内同名称的bean只有一个实例单例默认prototype每次使用该bean时会创建新的实例非单例request每个请求范围内会创建新的实例web环境中了解session每个会话范围内会创建新的实例web环境中了解application每个应用范围内会创建新的实例web环境中了解
可以借助Spring中的Scope注解来配置作用域
再次运行后控制台日志显示 UserController这个bean就生成了多份不过实际开发中绝大多数bean都是单例的也就是不用配置scope属性。
除此之外Spring还提供了一个注解Lazy用于延迟加载意思是当第一次使用bean对象时才会创建bean对象并交给ioc容器管理。
3、管理第三方的bean对象重点
前面所配置的bean像controller、servicedao三层体系下编写的类这些类都是我们在项目当中自己定义的类(自定义类)。当我们要声明这些bean也非常简单我们只需要在类上加上Component以及它的这三个衍生注解Controller、Service、Repository就可以来声明这个bean对象了。 但是在我们项目开发当中还有一种情况就是这个类它不是我们自己编写的而是我们引入的 第三方依赖 当中提供的。
在pom.xml文件中引入dom4j
!--Dom4j--
dependencygroupIdorg.dom4j/groupIdartifactIddom4j/artifactIdversion2.1.3/version
/dependencydom4j就是第三方组织提供的。dom4j中的SAXReader类就是第三方编写的。
当我们需要使用到SAXReader对象时直接进行依赖注入是不是就可以了呢
按照我们之前的做法需要在SAXReader类上添加一个注解Component将当前类交给IOC容器管理如下 注意看第三方提供的类是 只读的无法在第三方类上添加Component注解或衍生注解。
那应该怎样定义并使用第三方的bean对象呢
Spring框架又提供了一个注解 Bean可以用来管理来第三方不是自定义的容器。
方法一 在引导类/启动类上添加Bean标识的方法 不推荐抛砖引玉 SpringBootApplication
public class SpringbootWebConfig2Application {public static void main(String[] args) {SpringApplication.run(SpringbootWebConfig2Application.class, args);}//声明第三方beanBean //将当前方法的返回值对象交给IOC容器管理, 成为IOC容器beanpublic SAXReader saxReader(){return new SAXReader();}
}测试xml文件
?xml version1.0 encodingUTF-8?
empnameTom/nameage18/age
/emp测试类 SpringBootTest
class SpringbootWebConfig2ApplicationTests {Autowiredprivate SAXReader saxReader;//第三方bean的管理Testpublic void testThirdBean() throws Exception {Document document saxReader.read(this.getClass().getClassLoader().getResource(1.xml));Element rootElement document.getRootElement();String name rootElement.element(name).getText();String age rootElement.element(age).getText();System.out.println(name : age);}
}运行测试方法程序可以正常运行并解析xml数据说明SAXReader类的对象被成功注入进来了。
Tom : 18方法二 在配置类中定义Bean标识的方法 推荐
以上在启动类中声明第三方Bean的作法不建议使用项目中要保证启动类的 纯粹性。
创建配置类CommonConfig
package com.nvyao.conf;import com.nvyao.pojo.Dept;
import com.nvyao.service.DeptService;
import org.dom4j.io.SAXReader;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;import java.util.List;Configuration //配置类
public class CommonConfig {//声明第三方Bean一般情况下专门定一个配置类来声名第三方bean对象//加了这个注解spring框架会自动调用这个方法并且将方法返回值交给IOC容器管理成为IOC容器的bean对象//通过Bean注解的name或value属性可以声明Bean的名称如果不指定默认bean的名称就是方法名Bean//(reader)public SAXReader saxReader() {return new SAXReader();}
}去除之前启动类的Bean方法重启依然有效。
假如第三方Bean在使用过程还需要使用其他Bean也就是还需要依赖其他对象可以直接通过在Bean注解的这个方法添加需要依赖的对象的形参来解决如下 Configuration //配置类
public class CommonConfig {Beanpublic SAXReader saxReader(DeptService deptService) {System.out.println(deptService);ListDept deptList deptService.listDept();System.out.println(deptList);return new SAXReader();}
} 可以断点调试看到形参的对象已经注入进来了真挺好
总结一下
1SpringBoot的启动类也是一个配置类理论上声明第三方Bean的方法可以放在启动类但一般是单独定义一个配置类
2加了Bean注解Spring框架会自动调用Bean注解的方法并且将方法返回值交给IOC容器管理成为IOC容器的bean对象
3通过Bean注解的name或value属性可以声明Bean的名称如果不指定默认bean的名称就是方法名
4如果第三方Bean需要依赖其他bean对象直接在bean定义方法中设置行参即可容器会根据类型自动装配
4、bean 三种注入方式
属性注入 属性注入目前最 常用的注入方式使用Autowired注解实现。 在类的属性上添加Autowired注解Spring会自动注入对应的Bean对象。 需要注意的是属性注入可能会导致Bean状态的不完整性因为它们是在构造函数后才被注入的因此可能会出现空指针异常等问题。 适用于 类容器 Bean 容器
package com.xuzhongkj.components;import com.xuzhongkj.po.Users;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;Component
public class WttFunBeanTest {Bean(name aaa)public String aaa() {return aaaaaaaaaaa;}Bean(name bbb)public Users bb22b() {return new Users(1, wtt);}public String Hi() {return Hi;}
}属性注入
package com.xuzhongkj.controller;import com.xuzhongkj.components.WttFunBeanTest;
import com.xuzhongkj.po.Users;
import com.xuzhongkj.service.NewsService;
import com.xuzhongkj.service.impl.NewsServiceImpl;
import lombok.AllArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;RestController
RequestMapping(/test)
public class WttTest {Autowiredprivate WttFunBeanTest wttFunBeanTest;GetMapping(/wtt1)public int a1() {System.out.println(wttFunBeanTest.Hi());return 0;}
}构造函数注入 构造函数注入是一种类型安全、清晰明了的方式可以保证Bean的完整性。 在类中定义一个构造函数并在其参数列表中声明需要注入的Bean对象。Spring会在初始化Bean的时候自动将对应的Bean对象传入。 适用于 方法容器 package com.xuzhongkj.controller;import com.xuzhongkj.components.WttFunBeanTest;
import com.xuzhongkj.po.Users;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;RestController
RequestMapping(/test)
public class WttTest {private Users users;private String aaa2;// 注意 这里 一定要使用 要注入的 bean 名称 为 形参的参数名public WttTest(Users bbb,String aaa) {this.users bbb;this.aaa2 aaa;}GetMapping(/wtt1)public int a1() {System.out.println(users);System.out.println(aaa2);return 0;}
}上述代码的 简化版也叫 AllArgsConstructor 注解版
package com.xuzhongkj.controller;import com.xuzhongkj.components.WttFunBeanTest;
import com.xuzhongkj.po.Users;
import lombok.AllArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;RestController
RequestMapping(/test)
AllArgsConstructor
public class WttTest {// 注意 这里 一定要使用 要注入的 bean 名称 为 属性 的参数名private Users bbb;private String aaa;GetMapping(/wtt1)public int a1() {System.out.println(bbb);System.out.println(aaa);return 0;}
}方法注入 方法注入是一种灵活的注入方式在类中定义一个方法并在其参数列表中声明需要注入的Bean对象。 使用Autowired注解标记该方法Spring会在初始化Bean的时候自动调用该方法并传入对应的Bean对象。 适用于 方法、类 容器 的 再封装 容器 在 service 层 使用 方法注入
package com.xuzhongkj.service.impl;import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xuzhongkj.dao.NewsMapper;
import com.xuzhongkj.po.News;
import com.xuzhongkj.po.Users;
import com.xuzhongkj.service.NewsService;
import lombok.Data;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;Service
Data
public class NewsServiceImpl extends ServiceImplNewsMapper, News implements NewsService {private Users bbb;private String aaa;// 注意 这里 一定要使用 要注入的 bean 名称 为 形参的参数名Autowiredpublic void aaa(Users bbb, String aaa) {this.bbb bbb;this.aaa aaa;}
}在 controller层验证 是否注入成功
package com.xuzhongkj.controller;import com.xuzhongkj.components.WttFunBeanTest;
import com.xuzhongkj.po.Users;
import com.xuzhongkj.service.NewsService;
import com.xuzhongkj.service.impl.NewsServiceImpl;
import lombok.AllArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;RestController
RequestMapping(/test)
public class WttTest {Autowiredprivate NewsServiceImpl newsServiceImpl;GetMapping(/wtt1)public int a1() {System.out.println(newsServiceImpl.getAaa());System.out.println(newsServiceImpl.getBbb());return 0;}
}好文分享 一起加油