什么是bean
- 基本属性有id和class
- ID为bean在spring容器中的唯一标识
- class为bean的全限定名称,即类的路径
- spring读取配置文件,通过反射来创建bean
- 默认情况下spring调用类中的无参构造函数来创建bean,如果没有无参构造函数则不能创建成功。所以如果定义了有参构造一定要把无参构造也定义上
配置中Bean的顺序不重要,Spring根据依赖关系会自动正确初始化。
项目结构
注意
pom.xml
与src一样是最高级- xml文件必须写在
resource
下才能被识别到 - 类必须写
java
下才能被识别到。在spring看来java就是类的根目录
-
XML配置
导入Spring依赖
实现Spring基本功能ioc,只需导入
spring-context
即可。spring-webmvc
则包含了所有web开发需要的包,包括context<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.1.10.RELEASE</version>
</dependency>
创建类
public class Hello { private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } public void show(){ System.out.println("Hello,"+ name ); } }
装配/注入bean
装配与注入是一回事
bean就是java对象 , 由Spring创建和管理,此即装配。
id为对象名,class为对象类型。每个类的id必须是唯一的!
<?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="hello" class="com.kuang.pojo.Hello"> //必须在src/main/java下的包中才能识别到,所以一定要创建包 <property name="name" value="Spring"/> </bean> </beans>
xml中不像java这么容易识别类型,所以类型/文件必须写完整路径
获取bean以使用
ApplicationContext
它就是一个ioc容器
,可以实现装配,创建,获取beanBeanFactory
是另外一种ioc容器,BeanFactory的实现是按需创建,即第一次获取Bean时才创建这个Bean,而ApplicationContext会一次性创建所有的Bean。- 实际上,ApplicationContext接口是从BeanFactory接口继承而来的,并且,ApplicationContext提供了一些额外的功能,包括国际化支持、事件和通知机制等。通常情况下,我们总是使用ApplicationContext,很少会考虑使用BeanFactory。
//解析beans.xml文件 , 生成管理相应的Bean对象.使用xml配置则调用ClassPath...方法 ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); //getBean : 获取bean对象。参数即为spring配置文件中bean的id . Hello hello = (Hello) context.getBean("hello"); //bean对象的初始类型都是Object,必须强制转换为具体类型才能使用 //这里除了可以强制转换,还可以通过反射进行转换 getBean("hello",Hello.class); hello.show(); }
BeanFactory factory = new XmlBeanFactory(new ClassPathResource("application.xml")); MailService mailService = factory.getBean(MailService.class);
- 实际上,ApplicationContext接口是从BeanFactory接口继承而来的,并且,ApplicationContext提供了一些额外的功能,包括国际化支持、事件和通知机制等。通常情况下,我们总是使用ApplicationContext,很少会考虑使用BeanFactory。
hello 对象是由Spring创建的,对象的属性是由Spring容器设置的。
- 传统应用程序的对象是由程序本身控制创建的 , 使用Spring后 , 对象是由Spring来创建的,这个过程就叫控制反转 .我们要修改或者创建,直接改配置即可,不用再修改原代码了
- 反转 : 程序本身不创建对象 , 而变成被动的接收对象 .
- 依赖注入 : 就是利用set方法来进行注入的.
IOC是一种编程思想,由主动的编程变成被动的接
注解配置
@Compoent
默认创建一个名称为类名小写的bean对象;也可以添加参数,创建指定名称的对象- 相当于
<bean id="user" class="当前注解的类"/>
@Component("user001")
创建class为User类的叫user001的bean对象
- 相当于
@Value
注入值 只能用于原本可以property name="name" value="rao"/>
进行注入的- 这里不写set和有参构造也能注入,不知道
@Value
怎么实现注入的 - value注解只用于基本类和String类型的注入,除了自动装配还能直接设置值
- 这里不写set和有参构造也能注入,不知道
@Autowired
用于类类型的装配注入,不能设置值。相当于ref注入的xml。- 注意注入的bean要已经创建才能注入,创建使用
@Component
系列注解创建或者使用@Bean
,@bean
更灵活
- 注意注入的bean要已经创建才能注入,创建使用
@Configuration
表示这是一个配置类- 标注了该注解的类就相当于是spring的启动类
- 使用java类配置则使用
AnnotationConfigApplicationContext
来获取配置
@ComponentScan
:指定扫描某个包下的注解,将这些注解交给ioc容器管理。- 不清楚无参数的该注解有什么作用
- 等同于xml
<context:component-scan base-package="..."/>
关于getBean的具体使用方式见spring简介
@Component public class User { public String getInfoUser() { return infoUser.a; } @Value("rao") private String name; private InfoUser infoUser; public String getName() { return name; } @Autowired public User(InfoUser infoUser) { this.infoUser = infoUser; } }
@Component public class InfoUser { ... }
//这里测试和 @Configuration @ComponentScan public class Test { public static void main(String[] args) { ApplicationContext context = new AnnotationConfigApplicationContext(Test.class); User user = context.getBean(User.class); System.out.println(user.getName()); } }
java配置
注解配置是通过@Component及其延伸注解定义bean。java类配置则是通过@bean进行定义创建bean,无需@Component及其衍生注解。这是最本质的区别
- java配置比较灵活(比如可以写些逻辑到@Bean方法里,不同情况返回不同实现bean),java配置中还可以使用注解配置的功能,如
@Component
等。 - @Bean 注解是告诉 Spring 这是某个类的实例
- java配置比较灵活(比如可以写些逻辑到@Bean方法里,不同情况返回不同实现bean),java配置中还可以使用注解配置的功能,如
- 注解配置和java配置都需要用到
@Configuration
- 这个注解跟@Component作用差不多,不过还有个标注该类是注解类的作用(即仅仅是标明而已,实际作用跟component美色个么差别)
- 测试时和注解配置一样,也是
AnnotationConfigApplicationContext
getBean
…**AnnotationConfigApplicationContext**
相当于ioc容器,它的作用是将java配置作为参数传入ioc容器中(交由ioc容器托管)
springboot的主程序也可以配置
**bean**
。因为主程序的@SpringBootApplication
间接引用了@Configuration
在注解配置的基础上增加@Bean方法,然后取消@Component即可,因为@Configuration包含了@Component注解 @Configuration @ComponentScan public class Test { @Bean public User user(){ return new User(); } public static void main(String[] args) { //托管到ioc容器 ApplicationContext context = new AnnotationConfigApplicationContext(Test.class); //通过ioc容器获取bean User user = context.getBean(User.class); System.out.println(user.getName()); } }
三种配置总结:
spring最开始是使用xml,然后推出注解,最后推出java配置。现如今spring官方都推荐使用java类配置的方法
- 三种方式其实就是通过不同方式获取到
ApplicationContext
,然后通过getBean(Class/bean名)
获取bean
普通类获取spring的bean
普通类即没有controller,service,component等注解标注的类。如一个普通的java工具类,在这些类里面使用
autowired,resource
等注入注解注入不进去,会报空指针异常。//对于非web项目可以这样: ApplicationContext ac =new File../Annotatiion/ClassPathXmlApplicationContext; ac.getBean("?") //收入bean名或者路径 比如 ApplicationContext applicationContext=new AnnotationConfigApplicationContext(HelloController.class); HelloController helloController= (HelloController) applicationContext.getBean(HelloController.class);
```java //web应用上面这种方式不适合,相当于加载了两次 spring 容器。所以应当采用如下方式: //创建一个类并实现ApplicationContextAware,重写setApplicationContext。并托管该类到容器。该类提供外部方法供普通类获取ApplicationContext @Component public class SpringUtils implements ApplicationContextAware { private static ApplicationContext applicationContext;
@Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
if (SpringUtils.applicationContext == null) { SpringUtils.applicationContext = applicationContext; }
}
public static ApplicationContext getApplicationContext() {
return applicationContext;
} }
//普通类使用时直接调用即可,托管类中既可以注入使用也可以直接调。
//如果是获取不到SpringUtils类的地方,则使用如下方法得到SpringUtils: @SpringBootApplication @ServletComponentScan @Import(value={SpringUtil.class}) public class App {
} ```