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;
}

源碼中有兩處需要注意:

  1. 該注解可以標注在哪里?
  • 構造方法上
  • 方法上
  • 形參上
  • 屬性上
  • 注解上
  1. 該注解有一個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();
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/40219.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/40219.shtml
英文地址,請注明出處:http://en.pswp.cn/news/40219.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

深入探索JavaEE單體架構、微服務架構與云原生架構

課程鏈接&#xff1a; 鏈接: https://pan.baidu.com/s/1xSI1ofwYXfqOchfwszCZnA?pwd4s99 提取碼: 4s99 復制這段內容后打開百度網盤手機App&#xff0c;操作更方便哦 --來自百度網盤超級會員v4的分享 課程介紹&#xff1a; &#x1f50d;【00】模塊零&#xff1a;開營直播&a…

ARM-M0內核MCU,內置24bit ADC,采樣率4KSPS,傳感器、電子秤、體脂秤專用,國產IC

ARM-M0內核MCU 內置24bit ADC &#xff0c;采樣率4KSPS flash 64KB&#xff0c;SRAM 32KB 適用于傳感器&#xff0c;電子秤&#xff0c;體脂秤等等

[BitSail] Connector開發詳解系列三:SourceReader

更多技術交流、求職機會&#xff0c;歡迎關注字節跳動數據平臺微信公眾號&#xff0c;回復【1】進入官方交流群 Source Connector 本文將主要介紹負責數據讀取的組件SourceReader&#xff1a; SourceReader 每個SourceReader都在獨立的線程中執行&#xff0c;只要我們保證Sou…

Jmeter進階使用:BeanShell實現接口前置和后置操作

一、背景 我們使用Jmeter做壓力測試或者接口測試時&#xff0c;除了最簡單的直接對接口發起請求&#xff0c;很多時候需要對接口進行一些前置操作&#xff1a;比如提前生成測試數據&#xff0c;以及一些后置操作&#xff1a;比如提取接口響應內容中的某個字段的值。舉個最常用…

c語言——拷貝數組

這段代碼是一個簡單的數組拷貝示例。它的功能是將一個原始數組 original 的內容拷貝到另一個數組 copied 中&#xff0c;并輸出兩個數組的元素。 代碼執行過程如下&#xff1a; 首先&#xff0c;在 main() 函數中定義了一個整型數組 original&#xff0c;并初始化了它的元素。…

【ARM 嵌入式 編譯 Makefile 系列 15 - Makefile define 宏與調用宏函數詳細介紹】

文章目錄 Makefile define 宏與調用宏函數帶參數的宏函數帶返回值的宏函數Makefile define 宏與調用宏函數 在Makefile中,可以通過define關鍵字來定義一個多行的宏(也稱為變量)。這種宏定義通常用于定義一個復雜的命令序列,然后在其他地方調用。 以下是定義一個宏的例子:…

物聯網在制造業中的應用

制造業目前正在經歷第四次工業革命&#xff0c;物聯網、人工智能和機器人等技術進步正在推動行業的發展。研究表明&#xff0c;到2024年&#xff0c;全球制造商將在物聯網解決方案上投資700億美元&#xff0c;許多制造商正在實施物聯網設備&#xff0c;以利用預測性維護和復雜的…

接口測試工具——Postman測試工具 Swagger接口測試+SpringBoot整合 JMeter高并發測試工具

目錄 Postman測試工具接口測試工具swaggerKnife4j1.引入依賴2.配置3.常用注解4.接口測試 JMeter什么是JMeter?JMeter安裝配置1.官網下載2.下載后解壓3.漢語設置 JMeter的使用方法1.新建線程組2.設置參數3.添加取樣器4.設置參數&#xff1a;協議&#xff0c;ip&#xff0c;端口…

SDK是什么,SDK和API有什么區別

SDK&#xff08;Software Development Kit&#xff09;是一種開發工具包&#xff0c;通常由軟件開發公司或平臺提供&#xff0c;用于幫助開發人員構建、測試和集成特定平臺或軟件的應用程序。SDK 包含一系列的庫、工具、示例代碼和文檔&#xff0c;旨在簡化開發過程并提供所需的…

基于Mysql+Vue+Django的協同過濾和內容推薦算法的智能音樂推薦系統——深度學習算法應用(含全部工程源碼)+數據集

目錄 前言總體設計系統整體結構圖系統流程圖 運行環境Python 環境MySQL環境VUE環境 模塊實現1. 數據請求和儲存2. 數據處理計算歌曲、歌手、用戶相似度計算用戶推薦集 3. 數據存儲與后臺4. 數據展示 系統測試工程源代碼下載其它資料下載 前言 本項目以豐富的網易云音樂數據為基…

SQLSERVER 查詢語句加with (NOLOCK) 報ORDER BY 報錯 除非另外還指定了 TOP、OFFSET 或 FOR XML

最近有一個項目在客戶使用時發現死鎖問題&#xff0c;用的數據庫是SQLSERVER &#xff0c;死鎖的原因是有的客戶經常去點報表&#xff0c;報表查詢時間又慢&#xff0c;然后又有人在做單導致了死鎖&#xff0c;然后主管要我們用SQLSERVER查詢時要加with (NOLOCK),但是我在加完 …

YOLOv5模型訓練流程

此文章只是記錄使用&#xff0c;以便后續查看&#xff0c;不作為教程&#xff0c;剛接觸&#xff0c;可能有錯誤 YOLOv5模型訓練流程 一、數據集的準備 1.在源碼根目錄新建mydata文件夾&#xff0c;在此文件夾下新建images和labels文件夾 目錄樹如下&#xff1a; ├───…

鏈表---

題目描述 一個學校里老師要將班上 N 個同學排成一列&#xff0c;同學被編號為 1~N&#xff0c;他采取如下的方法&#xff1a; 先將 11 號同學安排進隊列&#xff0c;這時隊列中只有他一個人&#xff1b; 2~N 號同學依次入列&#xff0c;編號為 i 的同學入列方式為&#xff…

2023骨傳導耳機推薦,適合運動骨傳導耳機推薦

相信很多人跟我一樣&#xff0c;隨著現在五花八門的耳機品種增多&#xff0c;選耳機的時候真是眼花繚亂&#xff0c;尤其還是網購&#xff0c;只能看&#xff0c;不能試&#xff0c;所以選擇起來比較困難&#xff0c; 作為一個運動達人&#xff0c;為了讓大家在購買耳機時少走彎…

〔012〕Stable Diffusion 之 中文提示詞自動翻譯插件 篇

? 目錄 &#x1f388; 翻譯插件&#x1f388; 下載谷歌翻譯&#x1f388; 谷歌翻譯使用方法&#x1f388; 谷歌翻譯使用效果 &#x1f388; 翻譯插件 在插件列表中搜索 Prompt Translator可以看到有2個插件選項&#xff1a;一個是基于谷歌翻譯 〔推薦〕、一個基于百度和deepl…

jvm從入門到精通

jvm 1.jvm與java體系結構???????

奧威BI財務數據分析方案:借BI之利,成就智能財務分析

隨著智能技術的發展&#xff0c;各行各業都走上借助智能技術高效運作道路&#xff0c;財務數據分析也不例外。借助BI商業智能技術能夠讓財務數據分析更高效、便捷、直觀立體&#xff0c;也更有助于發揮財務數據分析作為企業經營管理健康晴雨表的作用。隨著BI財務數據分析經驗的…

【RP2040】香瓜樹莓派RP2040之新建工程

本文最后修改時間&#xff1a;2022年09月05日 11:02 一、本節簡介 本節介紹如何新建一個自己的工程。 二、實驗平臺 1、硬件平臺 1&#xff09;樹莓派pico開發板 ①樹莓派pico開發板*2 ②micro usb數據線*2 2&#xff09;電腦 2、軟件平臺 1&#xff09;VS CODE 三、版…

【C++】一文帶你初識C++繼承

食用指南&#xff1a;本文在有C基礎的情況下食用更佳 &#x1f340;本文前置知識&#xff1a; C類 ??今日夜電波&#xff1a;napori—Vaundy 1:21 ━━━━━━?&#x1f49f;──────── 3:23 …

CSS中的calc()函數有什么作用?

聚沙成塔每天進步一點點 ? 專欄簡介? CSS中的calc()函數及其作用? 作用? 示例1. 動態計算寬度&#xff1a;2. 響應式布局&#xff1a;3. 自適應字體大小&#xff1a;4. 計算間距&#xff1a; ? 寫在最后 ? 專欄簡介 前端入門之旅&#xff1a;探索Web開發的奇妙世界 記得點…