Spring全注解开发

发布时间:2025-04-30 01:24

Java后端开发:Spring Boot框架入门 #生活技巧# #工作学习技巧# #编程语言学习路径#

{ }

peo没被扫描进来,完美

[](

)@Scope

=====================================================================

@Configuration //标注当前是一个配置类

@ComponentScan(value = “com.controller”)

public class MyConfig

{

@Scope(“prototype”)

@Bean(value = “dhy”)//指定id

public people getPeople()

{

return new people(“大忽悠”,18);

}

}

prototype:多实例的

ioc容器启动并不会去调用方法创建对象放在容器中,而是每次获取的时候才会调用方法创建对象

singleton:单实例的(默认值)

ioc容器启动时会调用方法创建对象放到ioc容器中,以后每一次获取就是直接从容器(map.get())中拿

request:同一次请求创建一个实例

session:同一个session创建一个实例

[](

)@Lazy —懒加载

=========================================================================

@Configuration //标注当前是一个配置类

@ComponentScan(value = “com.controller”)

public class MyConfig

{

@Lazy

@Bean(value = “dhy”)//指定id

public people getPeople()

{

return new people(“大忽悠”,18);

}

}

懒加载:

​ 单实例bean:默认在容器启动的时候创建对象

懒加载:容器启动不创建对象,第一次使用(获取)Bean创建对象,并初始化

[](

)@Conditional ({condition})

=========================================================================================

@Conditional: 按照一定的条件进行判断,满足条件给容器中注册Bean

LinuxCondition:

//判断是否linux系统

public class LinuxCondition implements Condition

{

public boolean matches(ConditionContext conditionContext, AnnotatedTypemetadata annotatedTypemetadata) {

//1.能获取到ioc容器使用的BeanFactory

ConfigurableListableBeanFactory beanFactory = conditionContext.getBeanFactory();

//2.获取类加载器

ClassLoader classLoader = conditionContext.getClassLoader();

//3.获取当前环境信息

Environment environment = conditionContext.getEnvironment();

//4.获取到bean定义的注册类:可以判断容器中的Bean的注册情况,也可以给容器中注册Bean

BeanDefinitionRegistry registry = conditionContext.getRegistry();

//获取当前操作系统名字

String property = environment.getProperty(“os.name”);

if(property.contains(“linux”))

return true;

return false;

}

}

windowsCondition:

//判断是否windows系统

public class WindowsCondition implements Condition

{

public boolean matches(ConditionContext conditionContext, AnnotatedTypemetadata annotatedTypemetadata) {

//3.获取当前环境信息

Environment environment = conditionContext.getEnvironment();

//获取当前操作系统名字

String property = environment.getProperty(“os.name”);

if(property.contains(“Windows”))

return true;

return false;

}

}

配置类:

//标注在类上,则只有符合条件时,当前配置类及其里面注册的Bean才会生效

//@Conditional({WindowsCondition.class})

@Configuration //标注当前是一个配置类

public class MyConfig

{

@Conditional({WindowsCondition.class})

@Bean

public people getWindows()

{

return new people(“windows系统”,18);

}

@Conditional(LinuxCondition.class)

@Bean

public people getLinux()

{

return new people(“Linux系统”,18);

}

}

[](

)给容器中注册组件方式:

1:包扫描+组件标注注解(@Controller/@Service/@Repository/@Component)

2:@Configuration注解标注类的会被放到容器中,因为AnnotationConfigApplicationContext(MyConfig.class),以前是通过配置文件的方式启动容器,现在是通过加载配置类的方式启动容器,并且@Configuration是个复合注解–里面由@Component等注解组成

3.@Bean导入第三方包里面的组件

4.@import:快速的给容器中导入一个组件

[](

)@import

======================================================================

@import导入组件,id默认是全类名

配置类:

@Configuration //标注当前是一个配置类

//这里没有进行包扫描,所以在不进行导入的情况下peoController是不会被注册到容器中的

@import({peoController.class,people.class})

public class MyConfig

{

@Conditional({WindowsCondition.class})

@Bean

public people getWindows()

{

return new people(“windows系统”,18);

}

@Conditional(LinuxCondition.class)

@Bean

public people getLinux()

{

return new people(“Linux系统”,18);

}

}

peoController:

@Controller(“大忽悠”)//这里同样可以起一个别名

public class peoController

{}

测试:

public class Main

{

//传入的是配置类的位置,一开始是加载配置类,之前是加载配置文件的位置

private ApplicationContext ioc= new AnnotationConfigApplicationContext(MyConfig.class);

@Test

public void test()

{

//获取容器中所有定义的Bean的名字

String[] beans = ioc.getBeanDefinitionNames();

for (String bean : beans) {

System.out.println(bean);

}

}

}

这里@Controller(“大忽悠”)已经起了一个别名,只是没被扫描到容器中,所以这里使用其别名作为id

[](

)自定义选择器导入组件

MyimportSelector:

//自定义逻辑返回需要导入的组件

public class MyimportSelector implements importSelector

{

//返回值就是要导入到容器中的组件的全类名

//Annotationmetadata:当前标注@import注解的类的所有信息

public String[] selectimports(Annotationmetadata annotationmetadata) {

//方法不要返回null

return new String[]{“com.Pojo.rea”, “com.Pojo.ha”};

}

}

MyConfig:

@Configuration //标注当前是一个配置类

//加入自定义导入选择器

@import({peoController.class,people.class,MyimportSelector.class})

public class MyConfig

{

@Conditional({WindowsCondition.class})

@Bean

public people getWindows()

{

return new people(“windows系统”,18);

}

@Conditional(LinuxCondition.class)

@Bean

public people getLinux()

{

return new people(“Linux系统”,18);

}

}

[](

)importBeanDefinitionRegistrar 手动注册Bean到容器

MyimportBeanDefinitionRegister:

public class MyimportBeanDefinitionRegister implements importBeanDefinitionRegistrar

{

public void registerBeanDefinitions(Annotationmetadata annotationmetadata, BeanDefinitionRegistry beanDefinitionRegistry) {

boolean ha = beanDefinitionRegistry.containsBeanDefinition(“com.Pojo.rea”);

boolean rea = beanDefinitionRegistry.containsBeanDefinition(“com.Pojo.ha”);

if(ha&&rea)

{

//指定Bean定义信息(Bean的类型,Bean的作用域…)

RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(dhy.class);

//指定Bean名

beanDefinitionRegistry.registerBeanDefinition(“手动组成的Bean”,rootBeanDefinition);

}

}

}

MyConfig:

@Configuration //标注当前是一个配置类

//加入自定义导入选择器

@import({people.class,MyimportSelector.class,MyimportBeanDefinitionRegister.class})

public class MyConfig

{

@Conditional({WindowsCondition.class})

@Bean

public people getWindows()

{

return new people(“windows系统”,18);

}

@Conditional(LinuxCondition.class)

@Bean

public people getLinux()

{

return new people(“Linux系统”,18);

}

}

[](

)使用Spring提供的FactoryBean(工厂Bean)来注册容器

==================================================================================================

自定义工厂类继承FactoryBean

//创建一个Spring定义的工厂Bean

public class MyFactoryBean implements FactoryBean {

//返回一个Mine对象,这个对象会添加到容器中

public Mine getObject() throws Exception {

return new Mine();

}

public Class getObjectType() {

return Mine.class;

}

//返回false:创建的Bean是多实例的

public boolean isSingleton() {

return false;

}

}

在配置类中,将自定义工厂类放到容器中:

@Configuration //标注当前是一个配置类

public class MyConfig

{

@Bean

public FactoryBean getFactoryBean()

{

return new MyFactoryBean();

}

}

测试:

public class Main

{

//传入的是配置类的位置,一开始是加载配置类,之前是加载配置文件的位置

private ApplicationContext ioc= new AnnotationConfigApplicationContext(MyConfig.class);

@Test

public void test()

{

//这里我们在自定义工厂Bean时,规定Bean为多实例

Object b1 = ioc.getBean(“getFactoryBean”);

Object b2 = ioc.getBean(“getFactoryBean”);

//工厂Bean获取的是调用getObject创建的对象

System.out.println(b1.getClass());

System.out.println(b2.getClass());

System.out.println(b1==b2);

//获取工厂Bean本身

Object b3 = ioc.getBean("&getFactoryBean");

System.out.println(b3.getClass());

}

}

1.默认获取到的是工厂Bean调用getObject创建的对象

2.要获取工厂Bean本身,我们需要给id前面加上一个&

[](

)Bean的生命周期(注解版本),通过@Bean注解指定Bean的初始化和销毁方法

=======================================================================================================

car类:

public class Car

{

public Car()

{

System.out.println(“car创建中…”);

}

public void init()

{

System.out.println(“car init…”);

}

public void destory()

{

System.out.println(“car destory…”);

}

}

配置类:

@Configuration

public class MyConfig

{

//指定初始化和销毁方法

@Bean(initMethod = “init”,destroyMethod = “destory”)

public Car car()

{

return new Car();

}

}

[](

)Bean的生命周期小结:

bean的创建—初始化—销毁的过程

容器管理bean的生命周期

我们可以自定义初始化和销毁方法,容器在bean进行到当前生命周期的时候来调用我们自定义的初始化和销毁方法

1.指定初始化和销毁方法

构造(对象创建)

单实例:在容器启动的时候创建对象

多实例:在每次获取的时候创建对象

初始化方法调用时机:

对象创建完成并赋值好,调用初始化方法

销毁方法调用时机:

​ 单实例: 容器关闭的时候

​ 多实例:容器不会管理这个Bean,容器不会调用销毁方法

[](

)对应Bean继承InitializingBean和DisposableBean接口,来指定Bean的初始化和销毁方法

Dhy类:

@Component

public class Dhy implements InitializingBean, DisposableBean

{

public Dhy()

{

System.out.println(“Dhy创建中…”);

}

//销毁方法

public void destroy() throws Exception {

System.out.println(“Dhy destory…”);

}

//初始化方法

public void afterPropertiesSet() throws Exception {

System.out.println(“Dhy init…”);

}

}

配置类:

@ComponentScan(“com.Pojo”)

@Configuration

public class MyConfig

{}

测试类:

public class Main

{

//传入的是配置类的位置,一开始是加载配置类,之前是加载配置文件的位置

private ApplicationContext ioc= new AnnotationConfigApplicationContext(MyConfig.class);

@Test

public void test()

{

Dhy bean = ioc.getBean(Dhy.class);

System.out.println(bean);

}

}

[](

)使用JSR250的@PostConstruct和@PreDestory注解指定bean的初始化和销毁方法

@PostConstruct:在bean创建完成并属性赋值完成,来执行初始化方法

@PreDestory:在容器销毁bean之前通知我们进行清理工作

@Component

public class Dhy

{

public Dhy()

{

System.out.println(“Dhy创建中…”);

}

//销毁方法

@PreDestroy

public void destroy() {

System.out.println(“Dhy destory…”);

}

//初始化方法

@PostConstruct

public void afterPropertiesSet() {

System.out.println(“Dhy init…”);

}

}

测试:

public class Main

{

//传入的是配置类的位置,一开始是加载配置类,之前是加载配置文件的位置

private ApplicationContext ioc= new AnnotationConfigApplicationContext(MyConfig.class);

@Test

public void test()

{

Dhy bean = ioc.getBean(Dhy.class);

System.out.println(bean);

bean.destroy();

}

}

[](

)Bean的后置处理器

自定义后置处理器MyBeanPostprocess

//后置处理器:在bean初始化前后进行处理工作

@Component//放到容器中

public class MyBeanPostprocess implements BeanPostProcessor

{

//bean是容器创建的实例,还没初始化

//beanname是实例在容器中的名字

//返回值是后来将要用的bean实例,我们可以直接返回,也可以包装后再返回

public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {

System.out.println(“后置处理器初始化前调用”+" “+beanName+”==》"+bean);

return bean;

}

public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {

System.out.println(“后置处理器初始化后调用”+" “+beanName+”==》"+bean);

return bean;

}

}

配置类

@ComponentScan({“com.Pojo”,“com.config”})

@Configuration

public class MyConfig

{}

测试:

public class Main

{

//传入的是配置类的位置,一开始是加载配置类,之前是加载配置文件的位置

private ApplicationContext ioc= new AnnotationConfigApplicationContext(MyConfig.class);

@Test

public void test()

{

Dhy bean = ioc.getBean(Dhy.class);

System.out.println(bean);

bean.destroy();

}

}

[](

)bean的后置处理器底层原理

Spring底层对BeanPostProcessor的使用

bean赋值,注入其他组件,@Autowired,生命周期注解功能等,底层都是使用相关后置处理器来完成的

[](

)属性赋值

===================================================================

[](

)@Value

@Value注解里面参数可填内容:

1.基本数值

2.可以写SPEL表达式==>#{}

3.可以写${},取出配置文件中的值(在运行环境变量里面的值)

@Data

@Component

public class Dhy

{

@Value(“大忽悠”)

String name;

@Value("#{3*6}")

String age;

public Dhy()

{

System.out.println(“Dhy创建中…”);

}

}

测试:

public class Main

{

//传入的是配置类的位置,一开始是加载配置类,之前是加载配置文件的位置

private ApplicationContext ioc= new AnnotationConfigApplicationContext(MyConfig.class);

@Test

public void test()

{

Dhy bean = ioc.getBean(Dhy.class);

System.out.println(bean);

}

}

[](

)@Value从配置文件取出来赋值给属性的中文如果出现乱码,是因为配置文件的编码问题,解决方式如下:

[](

)@Value也可以加在方法的参数上,从配置文件中取出值,赋值给参数

[](

)@PropertySource配置的用法

**加载指定的属性文件(*.properties)到 Spring 的 Environment 中。可以配合 @Value 和

@ConfigurationProperties 使用。**

**@PropertySource 和 @Value

组合使用,可以将自定义属性文件中的属性变量值注入到当前类的使用@Value注解的成员变量中。**

**@PropertySource 和 @ConfigurationProperties

组合使用,可以将属性文件与一个Java类绑定,将属性文件中的变量值注入到该Java类的成员变量中。**

[](

)@PropertySource读取外部配置文件中的k/v保存到运行的环境变量中,加载完外部配置文件中的值后使用${}取出配置文件中的值

@Data

@Component

public class Dhy

{

@Value("${name}")

String name;

@Value("#{3*6}")

String age;

public Dhy()

{

System.out.println(“Dhy创建中…”);

}

}

配置文件:

name=大忽悠

测试结果:

[](

)获取环境变量中的值⇒ ioc.getEnvironment.getProperty

public class Main

{

//传入的是配置类的位置,一开始是加载配置类,之前是加载配置文件的位置

private ApplicationContext ioc= new AnnotationConfigApplicationContext(MyConfig.class);

@Test

public void test()

{

Dhy bean = ioc.getBean(Dhy.class);

System.out.println(bean);

//获取环境变量中的保存的name

Environment env = ioc.getEnvironment();

String name = env.getProperty(“name”);

System.out.println(name);

}

}

[](

)自动装配

===================================================================

[](

)@Autowired和@Qualifier

@Autowired:自动注入:

1.默认优先按照类型去容器中寻找对应的组件

2.如果找到多个相同类型的组件,再将属性的名称作为组件的id去容器中查找

3.@Qualifier(“book”):使用@Qualifier指定需要装配的组件的id,而不是使用属性名

4.自动装配默认一定要将属性赋值好,没有就会报错

可以使用@Autowired(required=false);

[](

)@Primary

@Primary:让spring进行自动装配的时候,默认使用首选的bean

也可以继续使用@Qualifier指定需要装配的bean的名字

Dhy:

@AllArgsConstructor

@Data

@Component(“d2”)//默认类名作为id

public class Dhy

{

String name;

String age;

public Dhy()

{

System.out.println(“Dhy创建中…”);

}

}

MyConfig:

//读取外部配置文件中的k/v保存到运行的环境变量中

@PropertySource(value = {“classpath:/dhy.properties”})

@ComponentScan({“com.Pojo”,“com.controller”})

@Configuration

public class MyConfig

{

@Primary //在装配Dhy类型的bean时,默认使用下面id为d2的bean

@Bean(“d1”)//默认方法名作为id

public Dhy getDhy()

{

return new Dhy(“首选Bean”,“19”);

}

}

TestController:

@Controller

public class TestController

{

@Autowired

Dhy d;

public Dhy getDhy()

{

return d;

}

}

测试:

public class Main

{

//传入的是配置类的位置,一开始是加载配置类,之前是加载配置文件的位置

private ApplicationContext ioc= new AnnotationConfigApplicationContext(MyConfig.class);

@Test

public void test()

{

TestController b = ioc.getBean(TestController.class);

System.out.println(b.getDhy());

}

}

[](

)@Value和@bean执行顺序问题

如果2个标签在不同文件里,那么@Bean比@Value先执行,所以,有可能在使用@Value值为空

同一文件下,那么@Value比@Bean先执行

使用Environment取代@Value,它直接取配置文件,即getProperty()

[](

)@AutoWired所在类必须处于容器之中,该注解才会生效,原因如下:

如果一个类没有加注解如@component, @controller, @service等扫描这个类到容器中

在类中的变量加@Autowired注解无法生效。

因为如果一个类new对象生成的,那么这个类就不归spring容器管理,IOC等spring的功能也就无法使用了。

[](

)@Resource和@Inject

Spring还支持@Resource(JSR250)和@Inject(JSR330)[java规范的注解]

@Resource:

1.可以和@Autowired一样实现自动装配功能,默认是按照组件名称进行装配的,也可以指定要装配的组件id

2.没有能支持@Primary功能,没有能支持@Autowired(required=false)功能的

@Inject:

首先导入依赖:

javax.inject

javax.inject

1

功能和Autowired一样,但是没有required=false的功能,同样支持@Primary注解

[](

)@Autowired和@Resource,@Inject的区别:

@Autowired是spring定义的,@Resource和@Inject是java的规范,但是spring对其做了支持

因此@Resource和@Inject脱离了spring框架也可以使用,至于其他框架,只要对其做了对应的支持同样也可以使用

@Resource和@Autowired注解都是用来实现依赖注入的。只是@AutoWried默认先按by type自动注入,而@Resource默认按byName自动注入。

@Resource有两个重要属性,分别是name和type

spring将name属性解析为bean的名字,而type属性则被解析为bean的类型。所以如果使用name属性,则使用byName的自动注入策略,如果使用type属性则使用byType的自动注入策略。如果都没有指定,则通过反射机制使用byName自动注入策略。

@Resource依赖注入时查找bean的规则:(以用在field上为例)

1. 既不指定name属性,也不指定type属性,则自动按byName方式进行查找。如果没有找到符合的bean,则回退为一个原始类型进行查找,如果找到就注入。

2. 只是指定了@Resource注解的name,则按name后的名字去bean元素里查找有与之相等的name属性的bean,没有会报错

3. 只指定@Resource注解的type属性,则从上下文中找到类型匹配的唯一bean进行装配,找不到或者找到多个,都会抛出异常

4. 既指定了@Resource的name属性又指定了type,则从Spring上下文中找到唯一匹配的bean进行装配,找不到则抛出异常

@Autowired注解有一个required属性,当指定required属性为false时,意味着在容器中找相应类型的bean,如果找不到则忽略,而不报错(这一条是两个注解所没有的功能)。由于@Inject注解没有属性,在加载所需bean失败时,会报错

[](

)底层原理:

AutowiredAnnotationBeanPostProcessor:解析完成自动装配功能(注解自动注入后置解析器)

[](

)@Autowired和@Resource,@Inject等注解放在构造方法,普通方法上:

网址:Spring全注解开发 https://www.yuejiaxmz.com/news/view/896226

相关内容

Spring定时任务注解说明
为什么越来越多的开发者选择使用Spring Boot?
Spring 注解使用笔记(一)
spring事务管理(详解和实例)
Java 开发之关键注解详细汇总
spring
@EnableRetry(proxyTargetClass = true) . spring
JavaWeb开发实战:基于Spring Boot的在线任务管理系统(附详细代码~)
Spring Integration关键案例与现实生活场景 spring的应用场景
spring boot 获取天气预报

随便看看