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分模块开…...
Linux应用开发之网络套接字编程(实例篇)
服务端与客户端单连接 服务端代码 #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #include <pthread.h> …...
JavaSec-RCE
简介 RCE(Remote Code Execution),可以分为:命令注入(Command Injection)、代码注入(Code Injection) 代码注入 1.漏洞场景:Groovy代码注入 Groovy是一种基于JVM的动态语言,语法简洁,支持闭包、动态类型和Java互操作性,…...
以下是对华为 HarmonyOS NETX 5属性动画(ArkTS)文档的结构化整理,通过层级标题、表格和代码块提升可读性:
一、属性动画概述NETX 作用:实现组件通用属性的渐变过渡效果,提升用户体验。支持属性:width、height、backgroundColor、opacity、scale、rotate、translate等。注意事项: 布局类属性(如宽高)变化时&#…...
JavaScript 中的 ES|QL:利用 Apache Arrow 工具
作者:来自 Elastic Jeffrey Rengifo 学习如何将 ES|QL 与 JavaScript 的 Apache Arrow 客户端工具一起使用。 想获得 Elastic 认证吗?了解下一期 Elasticsearch Engineer 培训的时间吧! Elasticsearch 拥有众多新功能,助你为自己…...
转转集团旗下首家二手多品类循环仓店“超级转转”开业
6月9日,国内领先的循环经济企业转转集团旗下首家二手多品类循环仓店“超级转转”正式开业。 转转集团创始人兼CEO黄炜、转转循环时尚发起人朱珠、转转集团COO兼红布林CEO胡伟琨、王府井集团副总裁祝捷等出席了开业剪彩仪式。 据「TMT星球」了解,“超级…...
BCS 2025|百度副总裁陈洋:智能体在安全领域的应用实践
6月5日,2025全球数字经济大会数字安全主论坛暨北京网络安全大会在国家会议中心隆重开幕。百度副总裁陈洋受邀出席,并作《智能体在安全领域的应用实践》主题演讲,分享了在智能体在安全领域的突破性实践。他指出,百度通过将安全能力…...
第 86 场周赛:矩阵中的幻方、钥匙和房间、将数组拆分成斐波那契序列、猜猜这个单词
Q1、[中等] 矩阵中的幻方 1、题目描述 3 x 3 的幻方是一个填充有 从 1 到 9 的不同数字的 3 x 3 矩阵,其中每行,每列以及两条对角线上的各数之和都相等。 给定一个由整数组成的row x col 的 grid,其中有多少个 3 3 的 “幻方” 子矩阵&am…...
免费数学几何作图web平台
光锐软件免费数学工具,maths,数学制图,数学作图,几何作图,几何,AR开发,AR教育,增强现实,软件公司,XR,MR,VR,虚拟仿真,虚拟现实,混合现实,教育科技产品,职业模拟培训,高保真VR场景,结构互动课件,元宇宙http://xaglare.c…...
Xela矩阵三轴触觉传感器的工作原理解析与应用场景
Xela矩阵三轴触觉传感器通过先进技术模拟人类触觉感知,帮助设备实现精确的力测量与位移监测。其核心功能基于磁性三维力测量与空间位移测量,能够捕捉多维触觉信息。该传感器的设计不仅提升了触觉感知的精度,还为机器人、医疗设备和制造业的智…...
Docker拉取MySQL后数据库连接失败的解决方案
在使用Docker部署MySQL时,拉取并启动容器后,有时可能会遇到数据库连接失败的问题。这种问题可能由多种原因导致,包括配置错误、网络设置问题、权限问题等。本文将分析可能的原因,并提供解决方案。 一、确认MySQL容器的运行状态 …...
