Spring学习笔记之Spring IoC注解式开发
文章目录
- 声明Bean的注解
- Component注解
- Controller注解
- Service注解
- Repository
- Spring注解的使用
- 选择性实例化Bean
- 负责注入的注解
- @Value
- @Autowired与@Quaifier
- @Resource
- 全注解式开发
注解的存在主要是为了简化XML的配置。Spring6倡导全注解开发
- 注解怎么定义,注解中的属性怎么定义?
- 注解怎么使用
- 通过反射机制怎么读取注解
注解怎么定义,注解中的属性怎么定义?
package com.powernode.annotation;import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;@Target(value = {ElementType.TYPE})
@Retention(value = RetentionPolicy.RUNTIME)
public @interface Component {String value();
}
以上是自定义了一个注解:Component
该注解上面修饰的注解包括:Target注解和Retention注解,这两个注解被称为元注解。
Target注解用来设置Component注解可以出现的位置,以上代表表示Component注解只能用在类和接口上。
Retention注解用来设置Component注解的保持性策略,以上代表Component注解可以被反射机制读取。
String value();是Component注解中的一个属性。该属性类型String属性名是value。
//使用User
package com.powernode.bean;import com.powernode.annotation.Component;@Component(value = "userBean")
public class User {
}
语法格式:@注解类型名(属性名=属性值,属性名=属性值,属性名=属性值....)
userBean为什么使用双引号括起来,因为value属性是String类型,字符串
另外如果属性名是value,则在使用的时候可以省略属性名
package com.powernode.bean;import com.powernode.annotation.Component;//@Component(value = "userBean")
@Component("userBean")
public class User {
}
通过反射机制怎么读取注解?
//有注解的Bean
package com.powernode.bean;import com.powernode.annotation.Component;@Component("userBean")
public class User {
}
//没有注解的Bean
package com.powernode.bean;public class Vip {
}
//反射解析注解
package com.powernode.test;import com.powernode.annotation.Component;import java.io.File;
import java.net.URL;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;/*** @author 动力节点* @version 1.0* @className Test* @since 1.0**/
public class Test {public static void main(String[] args) throws Exception {// 存放Bean的Map集合。key存储beanId。value存储Bean。Map<String,Object> beanMap = new HashMap<>();String packageName = "com.powernode.bean";String path = packageName.replaceAll("\\.", "/");URL url = ClassLoader.getSystemClassLoader().getResource(path);File file = new File(url.getPath());File[] files = file.listFiles();Arrays.stream(files).forEach(f -> {String className = packageName + "." + f.getName().split("\\.")[0];try {Class<?> clazz = Class.forName(className);if (clazz.isAnnotationPresent(Component.class)) {Component component = clazz.getAnnotation(Component.class);String beanId = component.value();Object bean = clazz.newInstance();beanMap.put(beanId, bean);}} catch (Exception e) {e.printStackTrace();}});System.out.println(beanMap);}
}
声明Bean的注解
负责声明Bean的注解,常见的包括四个
- @Component
- @Controller
- @Service
- @Respository
Component注解
package com.powernode.annotation;import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;@Target(value = {ElementType.TYPE})
@Retention(value = RetentionPolicy.RUNTIME)
public @interface Component {String value();
}
Controller注解
package org.springframework.stereotype;import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.core.annotation.AliasFor;@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Controller {@AliasFor(annotation = Component.class)String value() default "";
}
Service注解
package org.springframework.stereotype;import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.core.annotation.AliasFor;@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Service {@AliasFor(annotation = Component.class)String value() default "";
}
Repository
package org.springframework.stereotype;import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.core.annotation.AliasFor;@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Repository {@AliasFor(annotation = Component.class)String value() default "";
}
其实@Controller、@Service、@Repository这三个注解都是@Component注解的别名
也就是说:这四个注解的功能都一样,用哪个都可以
只是为了增强程序的可读性,建议
- 控制类上使用:Controller
- service类上使用:Service
- dao类上使用Respsitory
它们都是只有一个value属性。value属性用来指定bean的id,也就是bean的名字
Spring注解的使用
- 第一步:加入aop的依赖
- 第二步:在配置文件中添加context命名空间
- 第三步:在配置文件中指定扫描的包
- 第四步:在Bean类上使用注解
第一步:加入aop的依赖
当加入spring-context依赖之后,会关联加入aop的依赖。所以不需要再加什么另外的依赖
第二步:在配置文件中添加context命名空间
<?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.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"></beans>
第三步:在配置文件中指定要扫描的包
<?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.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"><context:component-scan base-package="com.powernode.spring6.bean"/>
</beans>
第四步:在Bean类上使用注解
package com.powernode.spring6.bean;import org.springframework.stereotype.Component;@Component(value = "userBean")
public class User {
}
//test
package com.powernode.spring6.test;import com.powernode.spring6.bean.User;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;public class AnnotationTest {@Testpublic void testBean(){ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");User userBean = applicationContext.getBean("userBean", User.class);System.out.println(userBean);}
}
如果注解的属性名是value,那么value是可以省略的。
package com.powernode.spring6.bean;import org.springframework.stereotype.Component;@Component("vipBean")
public class Vip {
}
package com.powernode.spring6.test;import com.powernode.spring6.bean.Vip;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;public class AnnotationTest {@Testpublic void testBean(){ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");Vip vipBean = applicationContext.getBean("vipBean", Vip.class);System.out.println(vipBean);}
}
如果把value属性彻底去掉,spring会被Bean自动取名,默认名字的规律是Bean类名首字母小写即可
如果是多个包怎么办?有两种解决方案:
- 第一种:在配置文件中指定多个包,用逗号隔开
- 第二种:指定多个包的共同父包
用逗号隔开
package com.powernode.spring6.bean2;import org.springframework.stereotype.Service;@Service
public class Order {
}
<?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.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"><context:component-scan base-package="com.powernode.spring6.bean,com.powernode.spring6.bean2"/>
</beans>
//test
package com.powernode.spring6.test;import com.powernode.spring6.bean.BankDao;
import com.powernode.spring6.bean2.Order;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;public class AnnotationTest {@Testpublic void testBean(){ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");BankDao bankDao = applicationContext.getBean("bankDao", BankDao.class);System.out.println(bankDao);Order order = applicationContext.getBean("order", Order.class);System.out.println(order);}
}
指定父包
<?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.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"><context:component-scan base-package="com.powernode.spring6"/>
</beans>
选择性实例化Bean
假设在某个包下有很多Bean,有的Bean上标注了Component,有的标注了Controller,有的标注了Service,有的标注了Repository,现在由于某种特殊业务的需求,只允许其中所有的Controller参与Bean管理,其他的都不是实例化。该如何实现
package com.powernode.spring6.bean3;import org.springframework.stereotype.Component;
import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Repository;
import org.springframework.stereotype.Service;@Component
public class A {public A() {System.out.println("A的无参数构造方法执行");}
}@Controller
class B {public B() {System.out.println("B的无参数构造方法执行");}
}@Service
class C {public C() {System.out.println("C的无参数构造方法执行");}
}@Repository
class D {public D() {System.out.println("D的无参数构造方法执行");}
}@Controller
class E {public E() {System.out.println("E的无参数构造方法执行");}
}@Controller
class F {public F() {System.out.println("F的无参数构造方法执行");}
}
<!-- spring-choose.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.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"><context:component-scan base-package="com.powernode.spring6.bean3" use-default-filters="false"><context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/></context:component-scan></beans>
其中:
use-default-filters="true"
表示:使用spring默认的规则,只要有Compoment、Controller、Service、Repository中的任意一个注解标注,则进行实例化。
use-default-filters="false"
标识:不再spring默认实例化规则,即使有Component、Controller、Service、Repository这些注解标注,也不再实例化.
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
表示只有Controller进行实例化。
//test
@Test
public void testChoose(){ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-choose.xml");
}
也可以将use-default-filters设置为true(不写就是true),并且采用exclude-filter方式排除哪些注解标注的Bean不参与实例化:
<!-- spring-choose.xml -->
<context:component-scan base-package="com.powernode.spring6.bean3"><context:exclude-filter type="annotation" expression="org.springframework.stereotype.Repository"/><context:exclude-filter type="annotation" expression="org.springframework.stereotype.Service"/><context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
负责注入的注解
@Component@Controller@Service@Repository这四个注解是用来声明Bean的,声明后这些Bean将被实例化。
给Bean属性赋值需要用到这些注解:
- @Value
- @Autowired
- @Qualifier
- @Resource
@Value
当属性的类型是简单类型时,可以使用@Value注解进行注入
//User
package com.powernode.spring6.bean4;import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;@Component
public class User {@Value(value = "zhangsan")private String name;@Value("20")private int age;@Overridepublic String toString() {return "User{" +"name='" + name + '\'' +", age=" + age +'}';}
}
开启包扫描
<?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.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"><context:component-scan base-package="com.powernode.spring6.bean4"/>
</beans>
//test
@Test
public void testValue(){ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-injection.xml");Object user = applicationContext.getBean("user");System.out.println(user);
}
通过测试可以发现,我们并没有给属性提供setter方法,但仍然可以完成属性赋值
如果提供setter方法,并且再setter方法上添加@Value注解,更能完成此功能
package com.powernode.spring6.bean4;import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;@Component
public class User {private String name;private int age;@Value("李四")public void setName(String name) {this.name = name;}@Value("30")public void setAge(int age) {this.age = age;}@Overridepublic String toString() {return "User{" +"name='" + name + '\'' +", age=" + age +'}';}
}
@Value可以直接使用在属性上,也可以使用在setter方法上,都是可以的,都可以完成属性的赋值
为了简化代码,一般是不提供setter方法,直接在属性上使用@Value注解完成属性赋值。
package com.powernode.spring6.bean4;import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;@Component
public class User {private String name;private int age;public User(@Value("隔壁老王") String name, @Value("33") int age) {this.name = name;this.age = age;}@Overridepublic String toString() {return "User{" +"name='" + name + '\'' +", age=" + age +'}';}
}
@Value注解可以出现在属性上、setter方法上、以及构造方法的形参上。
@Autowired与@Quaifier
@Autowired注解可以用来注入非简单类型(翻译为:自动连线的,或者自动装配)
单独使用@Autowired注解,默认根据类型装配。(默认是byType)
//@Autowired源码
package org.springframework.beans.factory.annotation;import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Autowired {boolean required() default true;
}
源码中有两处需要注意:
- 该注解可以标注在哪里?
- 构造方法上
- 方法上
- 形参上
- 属性上
- 注解上
- 该注解有一个required属性,默认值是true,表示在注入的时候要求被注入的Bean必须是存在的,如果不存在则报错。如果required属性设置为false,表示注入的Bean存在或者不存在都没关系,存在的话就注入,不存在的话也不报错
在属性上使用@Autowired注解
//
package com.powernode.spring6.dao;public interface UserDao {void insert();
}
package com.powernode.spring6.dao;import org.springframework.stereotype.Repository;@Repository //纳入bean管理
public class UserDaoForMySQL implements UserDao{@Overridepublic void insert() {System.out.println("正在向mysql数据库插入User数据");}
}
package com.powernode.spring6.service;import com.powernode.spring6.dao.UserDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;@Service // 纳入bean管理
public class UserService {@Autowired // 在属性上注入private UserDao userDao;// 没有提供构造方法和setter方法。public void save(){userDao.insert();}
}
<!-- 配置包扫描 -->
<?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.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"><context:component-scan base-package="com.powernode.spring6.dao,com.powernode.spring6.service"/>
</beans>
//test
@Test
public void testAutowired(){ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-injection.xml");UserService userService = applicationContext.getBean("userService", UserService.class);userService.save();
}
没有提供构造方法和setter方法,仍然可以注入成功
@Autowired注解出现在setter方法上
package com.powernode.spring6.service;import com.powernode.spring6.dao.UserDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;@Service
public class UserService {private UserDao userDao;@Autowiredpublic void setUserDao(UserDao userDao) {this.userDao = userDao;}public void save(){userDao.insert();}
}
@Autowired出现在构造方法上
package com.powernode.spring6.service;import com.powernode.spring6.dao.UserDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;@Service
public class UserService {private UserDao userDao;@Autowiredpublic UserService(UserDao userDao) {this.userDao = userDao;}public void save(){userDao.insert();}
}
@Autowired只标注在构造方法的形参上
package com.powernode.spring6.service;import com.powernode.spring6.dao.UserDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;@Service
public class UserService {private UserDao userDao;public UserService(@Autowired UserDao userDao) {this.userDao = userDao;}public void save(){userDao.insert();}
}
当参数的构造方法只有一个时,@Autowired注解可以省略
package com.powernode.spring6.service;import com.powernode.spring6.dao.UserDao;
import org.springframework.stereotype.Service;@Service
public class UserService {private UserDao userDao;public UserService(UserDao userDao) {this.userDao = userDao;}public void save(){userDao.insert();}
}
如果有多个构造方法,@Autowired肯定是不能省略的
package com.powernode.spring6.service;import com.powernode.spring6.dao.UserDao;
import org.springframework.stereotype.Service;@Service
public class UserService {private UserDao userDao;public UserService(UserDao userDao) {this.userDao = userDao;}public UserService(){}public void save(){userDao.insert();}
}
@Autowired注解默认是byType进行注入的,也就是说根据类型注入的,
如果以上程序中,UserDao接口还有另外一个实现类,会出现什么问题
会提示出错:不能装配,UseDao这个Bean的数量大于一
怎么解决这个问题,当然要byName,根据名称进行装配。
@Autowired注解和@Qualifier注解联合起来才可以根据名称进行装配,在@Qualifier注解中指定Bean名称
package com.powernode.spring6.dao;import org.springframework.stereotype.Repository;@Repository // 这里没有给bean起名,默认名字是:userDaoForOracle
public class UserDaoForOracle implements UserDao{@Overridepublic void insert() {System.out.println("正在向Oracle数据库插入User数据");}
}
package com.powernode.spring6.service;import com.powernode.spring6.dao.UserDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;@Service
public class UserService {private UserDao userDao;@Autowired@Qualifier("userDaoForOracle") // 这个是bean的名字。public void setUserDao(UserDao userDao) {this.userDao = userDao;}public void save(){userDao.insert();}
}
总结:
- @Autowired注解可以出现在:属性上、构造方法上、构造方法的参数上、setter方法上。
- 当带参数的构造方法只有一个,@Autowired注解可以省略
- @Autowired注解默认根据类型注入。如果要根据名称注入的话,需要配合@Qualifier注解一起使用。
@Resource
@Resource注解也可以完成非简单类型注入。那它和@Autowired注解有什么区别
- @Resource注解是JDK拓展包中的,也就是说属于JDK的一部分。所有该注解是标准注解,更加具有通用性。(JSR-250标准中制定的注解类型。JSR是Java规范提案。)
- @Autowired注解是Spring框架自己的
- @Resorce注解默认根据名称装配byName,未指定name时,使用属性名作为name。通过name找不到的话会自动启动通过类型byType装配。
- @Autowired注解默认根据类型装配byType,如果想根据名称装配,需要配合@Qualifier注解一起用
- @Resource注解用在属性上、setter方法上。
- @Autowired注解用在属性上、setter方法上、构造方法上、构造方法参数上
@Resource注解属于JDK拓展包,所以不再JDK当中,需要额外引入以下依赖(如果时JDK8的话不需要额外引入依赖。高于JDK11或低于JDK8需要引入以下依赖):
<!-- spring-6 -->
<dependency><groupId>jakarta.annotation</groupId><artifactId>jakarta.annotation-api</artifactId><version>2.1.1</version>
</dependency>
一定要注意:如果你用Spring6,要知道Spring6不再支持JavaEE,它支持的是JakartaEE9。
(Oracle把JavaEE贡献给Apache了,Apache把JavaEE的名字改成JaKartaEE了,所以之前所接触的所有javax.*
包名统一修改为jakarta.*
包名了)
<!-- spring-5 -->
<dependency><groupId>javax.annotation</groupId><artifactId>javax.annotation-api</artifactId><version>1.3.2</version>
</dependency>
package com.powernode.spring6.dao;import org.springframework.stereotype.Repository;@Repository("xyz")
public class UserDaoForOracle implements UserDao{@Overridepublic void insert() {System.out.println("正在向Oracle数据库插入User数据");}
}
package com.powernode.spring6.service;import com.powernode.spring6.dao.UserDao;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;@Service
public class UserService {@Resource(name = "xyz")private UserDao userDao;public void save(){userDao.insert();}
}
把UseDaoForOracle的名字xyz修改为userDao,让这个Bean的名字和UserService类中的UseDao属性名一致:
package com.powernode.spring6.dao;import org.springframework.stereotype.Repository;@Repository("userDao")
public class UserDaoForOracle implements UserDao{@Overridepublic void insert() {System.out.println("正在向Oracle数据库插入User数据");}
}
package com.powernode.spring6.service;import com.powernode.spring6.dao.UserDao;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;@Service
public class UserService {@Resourceprivate UserDao userDao;public void save(){userDao.insert();}
}
当@Resource注解使用时没有指定name的时候,还是根据name进行查找,这个name是属性名
当通过name找不到的时候,自然会启动byType进行注入。
package com.powernode.spring6.service;import com.powernode.spring6.dao.UserDao;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;@Service
public class UserService {private UserDao userDao;@Resourcepublic void setUserDao(UserDao userDao) {this.userDao = userDao;}public void save(){userDao.insert();}
}
setUserDao去掉set之后,将首字母小写userDao,userDao就是name
也可以指定name
package com.powernode.spring6.service;import com.powernode.spring6.dao.UserDao;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;@Service
public class UserService {private UserDao userDao;@Resource(name = "userDaoForMySQL")public void setUserDao(UserDao userDao) {this.userDao = userDao;}public void save(){userDao.insert();}
}
@Resource注解:默认byName注入,没有指定name时把属性名当作name,根据name找不到时,才会byType注入。byType注入时,某种类型的Bean只能有一个
全注解式开发
省略省略省略省略,还有这个,全部省略
所谓的全注解开发就是不再使用spring配置文件了。写一个配置类来代替配置文件
package com.powernode.spring6.config;import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ComponentScans;
import org.springframework.context.annotation.Configuration;@Configuration
@ComponentScan({"com.powernode.spring6.dao", "com.powernode.spring6.service"})
public class Spring6Configuration {
}
编写test程序时不用再new ClassPathXmlApplicationContext()对象了
@Test
public void testNoXml(){ApplicationContext applicationContext = new AnnotationConfigApplicationContext(Spring6Configuration.class);UserService userService = applicationContext.getBean("userService", UserService.class);userService.save();
}
相关文章:
Spring学习笔记之Spring IoC注解式开发
文章目录 声明Bean的注解Component注解Controller注解Service注解Repository Spring注解的使用选择性实例化Bean负责注入的注解ValueAutowired与QuaifierResource 全注解式开发 注解的存在主要是为了简化XML的配置。Spring6倡导全注解开发 注解怎么定义,注解中的属性…...

C语言入门教程,C语言学习教程(非常详细)第二章 c语言初探
第一个C语言程序 我们有两种方式从计算机获得信息:一是看屏幕上的文字、图片、视频等,二是听从喇叭发出来的声音。让喇叭发出声音目前还比较麻烦,我们先来看看如何在屏幕上显示一些文字吧。 在屏幕上显示文字非常简单,只需要一个…...
HOT99-下一个排列
leetcode原题链接:下一个排列 题目描述 整数数组的一个 排列 就是将其所有成员以序列或线性顺序排列。 例如,arr [1,2,3] ,以下这些都可以视作 arr 的排列:[1,2,3]、[1,3,2]、[3,1,2]、[2,3,1] 。整数数组的 下一个排列 是指其…...

JAVA基础知识(二)——程序流程控制
程序流程控制 一、程序流程控制1.1 程序流程控制1.2 顺序结构1.3 分支结构1.4 循环结构1.5 嵌套循环1.6 return的使用 一、程序流程控制 1.1 程序流程控制 流程控制语句是用来控制程序中各语句执行顺序的语句,可以把语句组合成能完成一定功能的小逻辑模块。 其流程…...
mysql知识点+面试总结
目录 1 mysql介绍 2 数据库常见语法 3 数据库表的常见语法 4 其他常见语法(日期,查询表字段) 5 JDBC开发步骤 6 索引 6.1 索引常见语法 7 常见面试总结 8 java代码搭建监控页面 1 mysql介绍 数据库:存储在硬盘上的文件系统…...

前端大屏常用的适配方案
假设我们正在开发一个可视化拖拽的搭建平台,可以拖拽生成工作台或可视化大屏,或者直接就是开发一个大屏,首先必须要考虑的一个问题就是页面如何适应屏幕,因为我们在搭建或开发时一般都会基于一个固定的宽高,但是实际的…...
技术债 笔记
目录 1. 技术债 笔记1.1. 什么是技术债1.2. 讨论1.3. 国内技术从业者怎么看? 1. 技术债 笔记 1.1. 什么是技术债 1992 年, Ward Cunningham 在敏捷宣言中首次提出了"技术债"概念, 主要指有意或无意地做了错误的或不理想的技术决策所累积的债务。随后, 《重构》一书…...

【Leetcode】102.二叉树的层序遍历
一、题目 1、题目描述 给你二叉树的根节点 root ,返回其节点值的 层序遍历 。 (即逐层地,从左到右访问所有节点)。 示例1: 输入:root = [3,9,20,null,null,15,7] 输出:[[3],[9,20],[15,7]]示例2: 输入:root = [1] 输出:[[1]]示例3: 输入:root = [] 输出:[]…...
上传文件报413Request EntityToo Large错误解决办法
产生这种原因是因为服务器限制了上传大小 1、nginx服务器的解决办法 修改nginx.conf的值就可以解决了 将以下代码粘贴到nginx.conf内 client_max_body_size 20M 可以选择在http{ }中设置:client_max_body_size 20m; 也可以选择在server{ }中设置:cli…...
Neo4j之MERGE基础
在 Neo4j 中,MERGE 语句用于根据指定的模式进行创建或匹配节点和关系。它可以在节点或关系不存在时创建它们,并在已存在时进行匹配。 创建或匹配节点: MERGE (p:Person {name: John});这个查询会检查是否已经存在一个具有 "Person&quo…...
AbstractRoutingDataSource,spring配置多数据源问题
AbstractRoutingDataSource,spring配置多数据源问题 首先引入pom.xml依赖 <!--测试--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><version>2.3.12.RE…...

日常BUG—— SpringBoot项目DEBUG模式启动慢、卡死。
😜作 者:是江迪呀✒️本文关键词:日常BUG、BUG、问题分析☀️每日 一言 :存在错误说明你在进步! 一、问题描述 我们调试程序时,需要使用DEBUG模式启动SpringBoot项目, 有时候会发…...

Linux网络编程(TCP状态转换关系)
文章目录 前言一、TCP状态转换图二、TCP连接状态转换解析三、TCP断开状态转换解析四、为什么需要有2MLS时长总结 前言 本篇文章来讲解一下TCP的状态转换关系,学习这个状态转换关系对于我们深入了解网络编程是非常有必要的。 一、TCP状态转换图 二、TCP连接状态转换…...

tauri-vue:快速开发跨平台软件的架子,支持自定义头部UI拖拽移动和窗口阴影效果
Tauri Vue Typescript 一个使用 taurivuets 开发跨平台软件的模板,支持窗口头部自定义 UI 和拖拽和窗口阴影,不用再自己做适配了,拿来即用,非常 nice。而且已经封装好了 tauri 的 http 请求工具,省去很多弯路。开源…...

做好以下几点,可以让我们延长周末体验感,好好放松!!!
工作以后常常容易感到疲于奔命,让我们找到适合自己方式,来让我们度过一个充实放松的周末! 方向一:分享你周末的时间规划 我们可以把每个月当做一个周期,制定一个简单的计划,如:第一周,锻炼身体…...

Python 学习笔记——代码基础
目录 Python基础知识 变量 赋值 数据类型 print用法 print格式化输出 运算符 if-else 数据结构 元组 in运算符 列表 切片 [ : ] 追加 append() 插入 insert() 删除 pop() 字典 循环 for循环 for循环应用——遍历 for循环应用——累加…...
Android Studio 无法正常导入项目
Android Studio 无法正常导入 model,运行按钮边出现“Add Configuration”,可进行以下方法处理: 解决办法: 1、点击Run三角按钮左边紧挨的下拉按钮,选择Edit Configuration,选择 Default 新建一个Android…...

Grafana+Prometheus技术文档-进阶使用-监控spring-boot项目
阿丹: 之前已经实现了使用Prometheus来对服务器进行了监控和仪表盘的创建,现在就需要对这些监控方法使用在spring-boot中去。 实现思路: 1、集成Actuator 2、加入Prometheus的依赖 3、配置开放端口、以及开放监控 4、配置Prometheus中的配置…...

PG常用SQL
数据库 创建数据库 PostgreSQL 创建数据库可以用以下三种方式: 1、使用 CREATE DATABASE SQL 语句来创建。2、使用 createdb 命令来创建。3、使用 pgAdmin 工具。 CREATE DATABASE 创建数据库 CREATE DATABASE 命令需要在 PostgreSQL 命令窗口来执行࿰…...

分模块开发的意义及开发步骤
🐌个人主页: 🐌 叶落闲庭 💨我的专栏:💨 c语言 数据结构 javaweb 石可破也,而不可夺坚;丹可磨也,而不可夺赤。 Maven进阶 一、分模块开发1.1分模块开发的意义1.2分模块开…...

学习STC51单片机31(芯片为STC89C52RCRC)OLED显示屏1
每日一言 生活的美好,总是藏在那些你咬牙坚持的日子里。 硬件:OLED 以后要用到OLED的时候找到这个文件 OLED的设备地址 SSD1306"SSD" 是品牌缩写,"1306" 是产品编号。 驱动 OLED 屏幕的 IIC 总线数据传输格式 示意图 …...
Java入门学习详细版(一)
大家好,Java 学习是一个系统学习的过程,核心原则就是“理论 实践 坚持”,并且需循序渐进,不可过于着急,本篇文章推出的这份详细入门学习资料将带大家从零基础开始,逐步掌握 Java 的核心概念和编程技能。 …...

【论文阅读28】-CNN-BiLSTM-Attention-(2024)
本文把滑坡位移序列拆开、筛优质因子,再用 CNN-BiLSTM-Attention 来动态预测每个子序列,最后重构出总位移,预测效果超越传统模型。 文章目录 1 引言2 方法2.1 位移时间序列加性模型2.2 变分模态分解 (VMD) 具体步骤2.3.1 样本熵(S…...

全志A40i android7.1 调试信息打印串口由uart0改为uart3
一,概述 1. 目的 将调试信息打印串口由uart0改为uart3。 2. 版本信息 Uboot版本:2014.07; Kernel版本:Linux-3.10; 二,Uboot 1. sys_config.fex改动 使能uart3(TX:PH00 RX:PH01),并让boo…...

Spring数据访问模块设计
前面我们已经完成了IoC和web模块的设计,聪明的码友立马就知道了,该到数据访问模块了,要不就这俩玩个6啊,查库势在必行,至此,它来了。 一、核心设计理念 1、痛点在哪 应用离不开数据(数据库、No…...

dify打造数据可视化图表
一、概述 在日常工作和学习中,我们经常需要和数据打交道。无论是分析报告、项目展示,还是简单的数据洞察,一个清晰直观的图表,往往能胜过千言万语。 一款能让数据可视化变得超级简单的 MCP Server,由蚂蚁集团 AntV 团队…...
管理学院权限管理系统开发总结
文章目录 🎓 管理学院权限管理系统开发总结 - 现代化Web应用实践之路📝 项目概述🏗️ 技术架构设计后端技术栈前端技术栈 💡 核心功能特性1. 用户管理模块2. 权限管理系统3. 统计报表功能4. 用户体验优化 🗄️ 数据库设…...
在Ubuntu24上采用Wine打开SourceInsight
1. 安装wine sudo apt install wine 2. 安装32位库支持,SourceInsight是32位程序 sudo dpkg --add-architecture i386 sudo apt update sudo apt install wine32:i386 3. 验证安装 wine --version 4. 安装必要的字体和库(解决显示问题) sudo apt install fonts-wqy…...
MySQL 8.0 事务全面讲解
以下是一个结合两次回答的 MySQL 8.0 事务全面讲解,涵盖了事务的核心概念、操作示例、失败回滚、隔离级别、事务性 DDL 和 XA 事务等内容,并修正了查看隔离级别的命令。 MySQL 8.0 事务全面讲解 一、事务的核心概念(ACID) 事务是…...

计算机基础知识解析:从应用到架构的全面拆解
目录 前言 1、 计算机的应用领域:无处不在的数字助手 2、 计算机的进化史:从算盘到量子计算 3、计算机的分类:不止 “台式机和笔记本” 4、计算机的组件:硬件与软件的协同 4.1 硬件:五大核心部件 4.2 软件&#…...