Spring 自动装配及其注解

僤鯓⒐⒋嵵緔 提交于 2020-12-06 12:37:28

一.属性自动装配

 首先,准备三个类,分别是User,Cat,Dog。其中User属性拥有Cat和Dog对象。

 1 package com.hdu.autowire;
 2 
 3 public class User {
 4     private Cat cat;
 5     private Dog dog;
 6     private String str;
 7     
 8     public Cat getCat() {
 9         return cat;
10     }
11     public void setCat(Cat cat) {
12         this.cat = cat;
13     }
14     public Dog getDog() {
15         return dog;
16     }
17     public void setDog(Dog dog) {
18         this.dog = dog;
19     }
20     public String getStr() {
21         return str;
22     }
23     public void setStr(String str) {
24         this.str = str;
25     }
26 }
Class User
1 package com.hdu.autowire;
2 
3 public class Cat {
4     public void shout() {
5         System.out.println("miao~");
6     }
7 }
Class Cat
1 package com.hdu.autowire;
2 
3 public class Dog {
4     public void shout() {
5         System.out.println("wang~");
6     }
7 }
Class Dog

 测试代码:

 1 package com.hdu.test;
 2 
 3 import org.junit.Test;
 4 import org.springframework.context.ApplicationContext;
 5 import org.springframework.context.support.ClassPathXmlApplicationContext;
 6 
 7 public class TestIOCDI {
 8     @Test
 9     public void testMethodAutowire() {
10         ApplicationContext context = new ClassPathXmlApplicationContext("resources/spring_autowire.xml");
11         com.hdu.autowire.User user = context.getBean("user", com.hdu.autowire.User.class);
12         user.getCat().shout();
13         user.getDog().shout();
14     }
15 }
Test

    1.1 xml配置文件

<bean id="cat" class="com.hdu.autowire.Cat"></bean>
<bean id="dog" class="com.hdu.autowire.Dog"></bean>
    
<bean id="user" 
          class="com.hdu.autowire.User">
    <property name="cat" ref="cat"></property>
    <property name="dog" ref="dog"></property>
    <property name="str" value="haha"></property>
</bean>

 

    1.2 autowire byName (按名称自动装配)

        由于在手动配置xml过程中,常常发生字母缺漏和大小写等错误,而无法对其进行检查,使得开发效率降低。采用自动装配将避免这些错误,并且使配置简单化。

  当一个bean节点带有 autowire byName的属性时。

    ①将查找其类中所有的set方法名,例如setCat,获得将set去掉并且首字母小写的字符串,即cat。

    ②去spring容器中寻找是否有此字符串名称id的对象。

    ③如果有,就取出注入;如果没有,就报空指针异常。

<bean id="cat" class="com.hdu.autowire.Cat"></bean>
<bean id="dog" class="com.hdu.autowire.Dog"></bean>
    
<bean id="user" 
      class="com.hdu.autowire.User"
      autowire="byName">
</bean>

        如果将 <bean id="cat" class="com.hdu.autowire.Cat"></bean> 改成

<bean id="catXXX" class="com.hdu.autowire.Cat"></bean>

        执行时报空指针java.lang.NullPointerException。因为按byName规则找不对应set方法,真正的setCat就没执行,对象就没有初始化,所以调用时就会报空指针错误。

 

    1.3autowire byType (按类型自动装配)

        使用autowire byType首先需要保证:同一类型的对象,在spring容器中唯一。如果不唯一,会报不唯一的异常。

<bean id="cat" class="com.hdu.autowire.Cat"></bean>
<bean id="dog" class="com.hdu.autowire.Dog"></bean>
    
<bean id="user" 
      class="com.hdu.autowire.User"
      autowire="byType">
</bean>

        将<bean id="cat" class="com.hdu.autowire.Cat"></bean> 改成

<bean id="catXXX" class="com.hdu.autowire.Cat"></bean>

        因为是按类型装配,所以并不会报异常,也不影响最后的结果。

        甚至将id属性去掉,也不影响结果。

<bean class="com.hdu.autowire.Cat"></bean>

 

    1.4全局autowire

<?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:aop="http://www.springframework.org/schema/aop"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:p="http://www.springframework.org/schema/p"
    xmlns:util="http://www.springframework.org/schema/util" 
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop 
        http://www.springframework.org/schema/aop/spring-aop.xsd
        http://www.springframework.org/schema/tx 
        http://www.springframework.org/schema/tx/spring-tx.xsd
        http://www.springframework.org/schema/util 
        http://www.springframework.org/schema/util/spring-util.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc.xsd"  default-autowire="byName">
        
    <bean id="cat" class="com.hdu.autowire.Cat"></bean>
    <bean id="dog" class="com.hdu.autowire.Dog"></bean>
    
    <bean id="user" class="com.hdu.autowire.User" autowire="default"/>
    <bean id="user2" class="com.hdu.autowire.User" autowire="default"/>
    <bean id="user3" class="com.hdu.autowire.User" autowire="default"/>

</beans>

 

二.属性注解

    jdk1.5开始支持注解,spring2.5开始全面支持注解。

    利用注解的方式注入属性。

    ①spring引入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:aop="http://www.springframework.org/schema/aop"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:p="http://www.springframework.org/schema/p"
    xmlns:util="http://www.springframework.org/schema/util"  xmlns:context="http://www.springframework.org/schema/context"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop 
        http://www.springframework.org/schema/aop/spring-aop.xsd
        http://www.springframework.org/schema/tx 
        http://www.springframework.org/schema/tx/spring-tx.xsd
        http://www.springframework.org/schema/util 
        http://www.springframework.org/schema/util/spring-util.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc.xsd">
        
    <context:annotation-config/>
</beans>

 

    2.1 @Autowired

        @Autowired是按类型自动转配的,不支持id匹配。

        将User中的set方法去掉,加入@Autowired注解。

        其中这里依赖一个的jar包。

 1 package com.hdu.autowire;
 2 
 3 import org.springframework.beans.factory.annotation.Autowired;
 4 
 5 public class User {
 6     @Autowired
 7     private Cat cat;
 8     @Autowired
 9     private Dog dog;
10     private String str;
11     
12     public Cat getCat() {
13         return cat;
14     }
15     
16     public Dog getDog() {
17         return dog;
18     }
19     
20     public String getStr() {
21         return str;
22     }
23 }
<context:annotation-config/>
    
<bean id="catXXX" class="com.hdu.autowire.Cat"></bean>
<bean id="dogXXX" class="com.hdu.autowire.Dog"></bean>
    
<bean id="user" class="com.hdu.autowire.User"></bean>

    @Autowired(required=false)   

    false,对象可以为null;true,对象必须存对象,不能为null。

 

    2.2 @Qualifier

        @Autowired是根据类型自动装配的,加上@Qualifier则可以根据byName的方式自动装配,其中@Qualifier不能单独使用。

 1 package com.hdu.autowire;
 2 
 3 import org.springframework.beans.factory.annotation.Autowired;
 4 import org.springframework.beans.factory.annotation.Qualifier;
 5 
 6 public class User {
 7     @Autowired
 8     @Qualifier(value="carXXX")
 9     private Cat cat;
10     @Autowired
11     @Qualifier(value="dogXXX")
12     private Dog dog;
13     private String str;
14     
15     public Cat getCat() {
16         return cat;
17     }
18     
19     public Dog getDog() {
20         return dog;
21     }
22     
23     public String getStr() {
24         return str;
25     }
26 }

 

    2.3 @Resource

    @Resource如有指定的name属性,先按该属性进行byName方式查找装配;其次再进行默认的byName方式进行装配;如果以上都不成功,则按byType的方式自动装配。都不成功,则报异常。

 1 package com.hdu.autowire;
 2 
 3 import javax.annotation.Resource;
 4 
 5 public class User {
 6     @Resource
 7     private Cat cat;
 8     @Resource(name="dogXXX")
 9     private Dog dog;
10     private String str;
11     
12     public Cat getCat() {
13         return cat;
14     }
15     
16     public Dog getDog() {
17         return dog;
18     }
19     
20     public String getStr() {
21         return str;
22     }
23 }

配置文件1:

<bean id="catXXX" class="com.hdu.autowire.Cat"></bean>
<bean id="cat" class="com.hdu.autowire.Cat"></bean>
<bean id="dogXXX" class="com.hdu.autowire.Dog"></bean>
    
<bean id="user" class="com.hdu.autowire.User"></bean>

  先进行byName查找,成功。

 

配置文件2:

<context:annotation-config/> 
    
<bean id="catXXX" class="com.hdu.autowire.Cat"></bean>
<bean id="dogXXX" class="com.hdu.autowire.Dog"></bean>
    
<bean id="user" class="com.hdu.autowire.User"></bean>

    先进行byName查找,失败;再进行byType查找,成功。

 

配置文件3:

<bean id="catXXX" class="com.hdu.autowire.Cat"></bean>
<bean id="catYYY" class="com.hdu.autowire.Cat"></bean>
<bean id="dogXXX" class="com.hdu.autowire.Dog"></bean>
    
<bean id="user" class="com.hdu.autowire.User"></bean>

先进行byName查找,失败;再进行byType查找,有两个匹配,失败,报错。

 

    2.4小结:

    @Autowired与@Resource异同:

    1° @Autowired与@Resource都可以用来装配bean。都可以写在字段上,或写在setter方法上。

    2° @Autowired默认按类型装配(属于spring规范),默认情况下必须要求依赖对象必须存在,如果要允许null 值,可以设置它的required属性为false,如:@Autowired(required=false) ,如果我们想使用名称装配可以结合@Qualifier注解进行使用。

    3° @Resource(属于J2EE复返),默认按照名称进行装配,名称可以通过name属性进行指定。如果没有指定name属性,当注解写在字段上时,默认取字段名进行按照名称查找,如果注解写在setter方法上默认取属性名进行装配。 当找不到与名称匹配的bean时才按照类型进行装配。但是需要注意的是,如果name属性一旦指定,就只会按照名称进行装配。

它们的作用相同都是用注解方式注入对象,但执行顺序不同。@Autowired先byType,@Resource先byName。

 

三.类自动装配

    3.1 包扫描

    注解替换bean节点
        @Controller注解       只能用控制器类上
        @Service注解           只能用在业务类上
        @Repository注解      只能用在dao类上
        @Component注解     无法按照上面三个注解分类,就用此注解

 1 package com.hdu.autowire;
 2 
 3 import org.springframework.stereotype.Component;
 4 
 5 @Component
 6 public class Cat {
 7     public void shout() {
 8         System.out.println("miao~");
 9     }
10 }
Class Cat
 1 package com.hdu.autowire;
 2 
 3 import org.springframework.stereotype.Component;
 4 
 5 @Component
 6 public class Dog {
 7     public void shout() {
 8         System.out.println("wang~");
 9     }
10 }
Class Dog
 1 package com.hdu.autowire;
 2 
 3 import javax.annotation.Resource;
 4 import org.springframework.stereotype.Component;
 5 
 6 @Component
 7 public class User {
 8     @Resource
 9     private Cat cat;
10     @Resource
11     private Dog dog;
12     private String str;
13     
14     public Cat getCat() {
15         return cat;
16     }
17     
18     public Dog getDog() {
19         return dog;
20     }
21     
22     public String getStr() {
23         return str;
24     }
25 }
Class User
<!-- 解析注解
     @Controller
     @Service
     @Repository
     @Component
     component-scan:组件扫描
     base-package:基本包,指定包名,多个包名可以用逗号间隔
     也可以写多个<context:component-scan
     如果用了组件扫描后<context:annotation-config></context:annotation-config>就不用写了,组件扫描已经包含了 <context:annotation-config>
-->
<context:component-scan base-package="com.hdu.autowire"/>

测试:

 1 package com.hdu.test;
 2 
 3 import org.junit.Test;
 4 import org.springframework.context.ApplicationContext;
 5 import org.springframework.context.support.ClassPathXmlApplicationContext;
 6 
 7 import com.hdu.autowire.User;
 8 
 9 public class TestIOCDI {
10     @Test
11     public void testMethodAutowire() {
12         ApplicationContext context = new ClassPathXmlApplicationContext("resources/spring_autowire.xml");
13         User user = context.getBean("user", User.class);
14         user.getCat().shout();
15         user.getDog().shout();
16     }
17 }
Test

 

    3.2 类目和ID对应表:

        类名:    CAT        cAT         CaT        caT

        ID:          CAT         cAT        caT         caT

    分析:类名的关键在于第二个字母,第二个字母大写,首字母大写小写无所谓。如果第二个字母小写,那第一个必须小写。第二个字母之后大小写没关系。

               如果没有指定value,spring容器中id规则是类名的首字母小写。

 

    3.3 自定义bean的id

        @Component(value="cat")

 

四.其它注解

    4.1 @Value

jdbc_driverClass=com.mysql.jdbc.Driver
jdbc_url=jdbc:mysql://localhost:3306/tmpdb
jdbc_userName=root
jdbc_userPassword=root
mysql.properties

        4.1.1${}表达式

<context:component-scan base-package="com.hdu.util"></context:component-scan>
<!-- 用$表达式方式 -->
<context:property-placeholder location="classpath:/resources/mysql.properties"/>
 1 package com.hdu.util;
 2 
 3 import org.springframework.beans.factory.annotation.Value;
 4 import org.springframework.stereotype.Component;
 5 
 6 @Component("jdbcUtil")
 7 public class JDBCUtil {
 8     @Value("${jdbc_driverClass}")
 9     private String driverClass;
10     @Value("${jdbc_url}")
11     private String url;
12     @Value("${jdbc_userName}")
13     private String userName;
14     @Value("${jdbc_userPassword}")
15     private String password;
16     public String getDriverClass() {
17         return driverClass;
18     }
19     
20     public String getUrl() {
21         return url;
22     }
23     
24     public String getUserName() {
25         return userName;
26     }
27     
28     public String getPassword() {
29         return password;
30     }
31     
32     @Override
33     public String toString() {
34         return "JDBCUtil [driverClass=" + driverClass + ", url=" + url + ", userName=" + userName + ", password="
35                 + password + "]";
36     }
37     
38     
39     
40 }

测试:

 1 package com.hdu.test;
 2 
 3 import org.junit.Test;
 4 import org.springframework.context.ApplicationContext;
 5 import org.springframework.context.support.ClassPathXmlApplicationContext;
 6 
 7 import com.hdu.util.JDBCUtil;
 8 
 9 public class TestSpringIOCDI_Annoation {
10     @Test
11     public void testMethod() {
12         ApplicationContext context = new ClassPathXmlApplicationContext("resources/spring_annotation.xml");
13         JDBCUtil jdbcUtil = context.getBean("jdbcUtil", JDBCUtil.class);
14         System.out.println(jdbcUtil);
15     }
16 }

 

        4.1.2#{}表达式

<context:component-scan base-package="com.hdu.util"></context:component-scan>
<!-- 用#表达式方式 -->
<util:properties id="manyProperty" location="classpath:/resources/mysql.properties"></util:properties>
 1 package com.hdu.util;
 2 
 3 import org.springframework.beans.factory.annotation.Value;
 4 import org.springframework.stereotype.Component;
 5 
 6 @Component("jdbcUtil1")
 7 public class JDBCUtil1 {//@Value("#{manyProperty['jdbc_url']}")
 8     @Value("#{manyProperty.jdbc_driverClass}")
 9     private String driverClass;
10     @Value("#{manyProperty.jdbc_url}")
11     private String url;
12     @Value("#{manyProperty.jdbc_userName}")
13     private String userName;
14     @Value("#{manyProperty.jdbc_userPassword}")
15     private String password;
16     public String getDriverClass() {
17         return driverClass;
18     }
19     
20     public String getUrl() {
21         return url;
22     }
23     
24     public String getUserName() {
25         return userName;
26     }
27     
28     public String getPassword() {
29         return password;
30     }
31     
32     @Override
33     public String toString() {
34         return "JDBCUtil [driverClass=" + driverClass + ", url=" + url + ", userName=" + userName + ", password="
35                 + password + "]";
36     }
37 
38 }

测试:

package com.hdu.test;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.hdu.util.JDBCUtil1;

public class TestSpringIOCDI_Annoation {
    @Test
    public void testMethod() {
        //加载spring容器
        ApplicationContext context = new ClassPathXmlApplicationContext("resources/spring_annotation.xml");
        //从spring容器中取出对象
        JDBCUtil1 jdbcUtil = context.getBean("jdbcUtil1", JDBCUtil1.class);
        System.out.println(jdbcUtil);
    }
}

 

 

    4.2 @Scope(value="prototype")// 单例和多例 修饰在类上

    4.3 @Lazy //代表懒加载 修饰在类上 

    4.4 @PostConstruct //表示初始化操作 修饰在方法上

    4.5 @PreDestroy //表示销毁 修饰在方法上

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!