Spring知识点总结(三)之注解方式实现IOC和DI

    1. 注解概念
        所谓注解就是给程序看的提示信息,很多时候都用来作为轻量级配置的方式。
        关于注解的知识点,参看java基础课程中java基础加强部分的内容。
    2. Spring中的注解
        Spring除了默认的使用xml配置文件的方式实现配置之外,也支持使用注解方式实现配置,这种方式效率更高,配置信息清晰,修改更方便,推荐使用。
        
        引入context名称空间:
            在MyEclipse中导入spring-context-3.2.xsd约束文件,要求Spring来管理。
            在applicationContext.xml文件中,引入该schema文件:

                1     <?xml version="1.0" encoding="UTF-8"?>
                2     <beans xmlns="http://www.springframework.org/schema/beans"
                3         xmlns:context="http://www.springframework.org/schema/context"
                4         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                5         xsi:schemaLocation="http://www.springframework.org/schema/beans
                6         http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
                7         http://www.springframework.org/schema/context
                8         http://www.springframework.org/schema/context/spring-context-3.2.xsd
                9         ">
               10     </beans>

**可以将以上头信息加入MyEclipse模版,方便后续自动生成。
    
    3. 使用类注解
        使用Spring的类注解可以通过注解注册类为bean,省去了配置文件中的<bean>配置。
        
        a. 开启包扫描
        在spring的配置文件中,开启包扫描,指定spring自动扫描哪些个包下的类。
            <context:component-scan base-package="cn.tedu.beans"/>
        案例:

            <?xml version="1.0" encoding="UTF-8"?>
            <beans xmlns="http://www.springframework.org/schema/beans"
                xmlns:context="http://www.springframework.org/schema/context"
                xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                xsi:schemaLocation="http://www.springframework.org/schema/beans
                http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
                http://www.springframework.org/schema/context
                http://www.springframework.org/schema/context/spring-context-3.2.xsd
                ">
                <!-- 开启包扫描 -->
                <context:component-scan base-package="cn.tedu.beans"></context:component-scan>
                <!--
                    <bean id="person" class="cn.tedu.beans.Person"></bean>
                    <bean id="cat" class="cn.tedu.beans.Cat"></bean>
                    <bean id="dog" class="cn.tedu.beans.Dog"></bean>
                     -->
            </beans>

b. 使用注解注册bean
            这个包中的类会在spring容器启动时自动被扫描,检测是否需要自动配置为bean.
            在配置的包中的类上使用@Component注解,则这个类会自动被注册为bean,使用当前类的class为<bean>的class,通常情况下使用类名首字母小写为<bean>id。
            案例:

                package cn.tedu.beans;
                import org.springframework.stereotype.Component;

                @Component
                public class Person{
                }

c. bean的id
            可以使bean类实现BeanNameAware接口,并实现其中的setBeanName方法,spring容器会在初始化bean时,调用此方法告知当前bean的id。通过这个方式可以获取bean的id信息。
            
            通常情况下注解注册bean使用类名首字母小写为bean的id,但是如果类名的第二个字母为大写则首字母保留原样.
                cn.tedu.beans.Person --> <bean id="person" class="cn.tedu.beans.Person"/>
                cn.tedu.beans.NBA --> <bean id="NBA" class="cn.tedu.beans.NBA"/>
            也可以通过在@Component中配置value属性,明确的指定当前类在注册到spring时bean的id
            案例:

 1                package cn.tedu.beans;
 2
 3                 import org.springframework.beans.factory.BeanNameAware;
 4                 import org.springframework.beans.factory.annotation.Autowired;
 5                 import org.springframework.beans.factory.annotation.Qualifier;
 6                 import org.springframework.stereotype.Component;
 7
 8                 @Component("per")
 9                 public class Person implements BeanNameAware{
10                     @Override
11                     public void setBeanName(String name) {
12                         System.out.println("==="+this.getClass().getName()+"==="+name);
13                     }
14                 }

    4. 使用属性注解
        使用属性注解,可以为bean配置属性的注入过程,省去了在配置文件中进行注入配置的过程,更加便捷。
        
        a. 在配置文件中开启属性注解功能

          <?xml version="1.0" encoding="UTF-8"?>
            <beans xmlns="http://www.springframework.org/schema/beans"
                xmlns:context="http://www.springframework.org/schema/context"
                xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                xsi:schemaLocation="http://www.springframework.org/schema/beans
                http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
                http://www.springframework.org/schema/context
                http://www.springframework.org/schema/context/spring-context-3.2.xsd
                ">
                <!-- 开启属性注解 -->
                <context:annotation-config></context:annotation-config>
            </beans>

b. 使用属性注解注入bean类型数据:
            在bean中的属性上通过如下注解声明属性注入
                @Autowired
            也可以使用@Qualifier(value="dog1")注解,明确的指定,要注入哪个id的bean
            
            代码:

    package cn.tedu.beans;

                import org.springframework.beans.factory.BeanNameAware;
                import org.springframework.beans.factory.annotation.Autowired;
                import org.springframework.beans.factory.annotation.Qualifier;
                import org.springframework.stereotype.Component;

                public class Person implements BeanNameAware{
                    @Autowired
                    private Dog dog;
                    @Autowired
                    private Cat cat;

                    public Dog getDog() {
                        return dog;
                    }
                    public void setDogx(Dog dog) {
                        this.dog = dog;
                    }
                    public Cat getCat() {
                        return cat;
                    }
                    public void setCat(Cat cat) {
                        this.cat = cat;
                    }
                    @Override
                    public String toString() {
                        return "Person [dog=" + dog + ", cat=" + cat + "]";
                    }

                    @Override
                    public void setBeanName(String name) {
                        System.out.println("=============="+this.getClass().getName()+"===="+name);
                    }

                }

c. 属性注入bean类型数据的原理:
            当spring容器解析xml时,发现开启了属性注解,则会在创建bean时,检测属性上是否存在@Autowired注解,如果发现该注解,则会通过当前属性的名称寻找是否存在该id的bean,如果存在则注入进来,如果不存在,再检查是否存在和当前属性类型相同的bean,如果由则注入进来,如果都没有则抛出异常.
            
            **也可以使用@Resource(name="id")指定注入给定id的bean,但是这种方式不建议大家使用。
            
        d. spring内置支持注入类型的注解方式的注入 - 非集合类型
            spring中可以通过注解方式 注册bean,并可以通过@Autowired实现属性的自动注入,但注入的都是自定义的bean类型,如果类中包含例如 int long String等spring内置可注入的类型时,又该如何注入呢? 可以使用@Value注解来实现注入。

 1 package cn.tedu.beans;
 2
 3                 import org.springframework.beans.factory.BeanNameAware;
 4                 import org.springframework.beans.factory.annotation.Autowired;
 5                 import org.springframework.beans.factory.annotation.Value;
 6                 import org.springframework.stereotype.Component;
 7
 8                 @Component("per")
 9                 public class Person implements BeanNameAware{
10                     @Value("999")
11                     private int id;
12
13                     @Value("zs")
14                     private String name;
15
16                     @Autowired
17                     private Dog dog;
18
19                     @Autowired
20                     private Cat cat;
21
22                     public Dog getDog() {
23                         return dog;
24                     }
25                     public void setDogx(Dog dog) {
26                         this.dog = dog;
27                     }
28                     public Cat getCat() {
29                         return cat;
30                     }
31                     public void setCat(Cat cat) {
32                         this.cat = cat;
33                     }
34
35                     @Override
36                     public String toString() {
37                         return "Person [id=" + id + ", name=" + name + ", dog=" + dog
38                                 + ", cat=" + cat + "]";
39                     }
40                     @Override
41                     public void setBeanName(String name) {
42                         System.out.println("==="+this.getClass().getName()+"==="+name);
43                     }
44
45                 }

这种方式可以实现spring内置类型的注入,但是这种方式将注入的值写死在了代码中,后续如果希望改变注入的初始值,必须来修改源代码,此时可以将这些值配置到一个properties配置文件中,再在spring中进行引入。
                
            
                
                
                
            
        e. spring内置支持注入类型的注解方式的注入 - 集合类型
            需要将集合类型的数据配置到spring配置文件中,再通过@Value引入
            配置过程:
                将spring-util-3.2.xsd交给MyEclipse管理
                在当前spring容器的配置文件中导入util名称空间
                再通过适当的util标签注册数据
            案例:

  1     <?xml version="1.0" encoding="UTF-8"?>
  2                 <beans xmlns="http://www.springframework.org/schema/beans"
  3                     xmlns:context="http://www.springframework.org/schema/context"
  4                     xmlns:util="http://www.springframework.org/schema/util"
  5                     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  6                     xsi:schemaLocation="
  7                     http://www.springframework.org/schema/beans
  8                     http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
  9                     http://www.springframework.org/schema/context
 10                     http://www.springframework.org/schema/context/spring-context-3.2.xsd
 11                     http://www.springframework.org/schema/util
 12                     http://www.springframework.org/schema/util/spring-util-3.2.xsd
 13                     ">
 14                     <!-- 开启属性注解 -->
 15                     <context:annotation-config></context:annotation-config>
 16                     <context:component-scan base-package="cn.tedu.beans"></context:component-scan>
 17                     <context:property-placeholder location="classpath:/person-data.properties"/>
 18
 19                     <util:list id="l1">
 20                         <value>北京</value>
 21                         <value>上海</value>
 22                         <value>广州</value>
 23                         <value>深证</value>
 24                     </util:list>
 25
 26                     <util:set id="s1">
 27                         <value>法师</value>
 28                         <value>射手</value>
 29                         <value>打野</value>
 30                         <value>战士</value>
 31                         <value>打野</value>
 32                         <value>坦克</value>
 33                         <value>打野</value>
 34                     </util:set>
 35
 36                     <util:map id="m1">
 37                         <entry key="k1" value="v1"></entry>
 38                         <entry key="k2" value="v2"></entry>
 39                         <entry key="k3" value="v3"></entry>
 40                         <entry key="k1" value="v4"></entry>
 41                     </util:map>
 42                 </beans>
 43
 44             再在类的属性中通过@Value注入赋值
 45                 package cn.tedu.beans;
 46
 47                 import java.util.List;
 48                 import java.util.Map;
 49                 import java.util.Set;
 50
 51                 import org.springframework.beans.factory.BeanNameAware;
 52                 import org.springframework.beans.factory.annotation.Autowired;
 53                 import org.springframework.beans.factory.annotation.Value;
 54                 import org.springframework.stereotype.Component;
 55
 56                 @Component("per")
 57                 public class Person implements BeanNameAware{
 58                     @Value("${id}")
 59                     private int id;
 60
 61                     @Value("${name}")
 62                     private String name;
 63
 64                     @Value("#{@l1}")
 65                     private List<String> addr;
 66
 67                     @Value("#{@s1}")
 68                     private Set<String> jobs;
 69
 70                     @Value("#{@m1}")
 71                     private Map<String,String> map;
 72
 73                     @Autowired
 74                     private Dog dog;
 75
 76                     @Autowired
 77                     private Cat cat;
 78
 79                     public Dog getDog() {
 80                         return dog;
 81                     }
 82                     public void setDogx(Dog dog) {
 83                         this.dog = dog;
 84                     }
 85                     public Cat getCat() {
 86                         return cat;
 87                     }
 88                     public void setCat(Cat cat) {
 89                         this.cat = cat;
 90                     }
 91
 92                     public void setBeanName(String name) {
 93                         System.out.println("=============="+this.getClass().getName()+"===="+name);
 94                     }
 95                     @Override
 96                     public String toString() {
 97                         return "Person [id=" + id + ", name=" + name + ", addr=" + addr
 98                                 + ", jobs=" + jobs + ", map=" + map + ", dog=" + dog + ", cat="
 99                                 + cat + "]";
100                     }
101                 }
102     

    5. 其他注解
        a. @Scope(value="prototype")
            配置修饰的类的bean是单例还是多例,如果不配置默认为单例
            案例:

 1                 package cn.tedu.beans;
 2
 3                 import org.springframework.context.annotation.Scope;
 4                 import org.springframework.stereotype.Component;
 5
 6                 @Component
 7                 @Scope("prototype")
 8                 public class Dog {
 9
10                 }

b. @Lazy
            配置修饰的类的bean采用懒加载机制
            案例:

 1                 package cn.tedu.beans;
 2
 3                 import org.springframework.context.annotation.Lazy;
 4                 import org.springframework.context.annotation.Scope;
 5                 import org.springframework.stereotype.Component;
 6
 7                 @Component
 8                 @Lazy
 9                 public class Dog {
10                     public Dog() {
11                         System.out.println("Dog...被创建出来了...");
12                     }
13                 }

c. @PostConstruct
            在bean对应的类中 修饰某个方法 将该方法声明为初始化方法,对象创建之后立即执行。
        d. @PreDestroy
            在bean对应的类中 修饰某个方法 将该方法声明为销毁的方法,对象销毁之前调用的方法。
            案例:

 1   package cn.tedu.beans;
 2
 3                 import javax.annotation.PostConstruct;
 4                 import javax.annotation.PreDestroy;
 5
 6                 import org.springframework.stereotype.Component;
 7
 8                 @Component
 9                 public class Dog {
10                     public Dog() {
11                         System.out.println("Dog...被创建出来了...");
12                     }
13
14                     @PostConstruct
15                     public void init(){
16                         System.out.println("Dog的初始化方法。。。");
17                     }
18
19                     @PreDestroy
20                     public void destory(){
21                         System.out.println("Dog的销毁方法。。。");
22                     }
23                 }

e. @Controller @Service @Repository @Component
            这四个注解的功能是完全相同的,都是用来修饰类,将类声明为Spring管理的bean的。
            其中@Component一般认为是通用的注解
            而@Controller用在软件分层中的控制层,一般用在web层
            而@Service用在软件分层中的业务访问层,一般用在service层
            而@Repository用在软件分层中的数据访问层,一般用在dao层

原文地址:https://www.cnblogs.com/nanlinghan/p/9926154.html

时间: 2024-08-09 08:41:16

Spring知识点总结(三)之注解方式实现IOC和DI的相关文章

Spring 注解方式 实现 IOC 和 DI

注:以下所有测试案例(最后一个除外)的测试代码都是同一个: package cn.tedu.test; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import cn.tedu.beans.Person; public class IOC

你可能使用了Spring最不推荐的注解方式

前言 使用Spring框架最核心的两个功能就是IOC和AOP.IOC也就是控制反转,我们将类的实例化.依赖关系等都交由Spring来处理,以达到解耦合.利用复用.利于测试.设计出更优良程序的目的.而对用户来说,操作最对的便是注解.在Spring中提供了三类注解方式,下面我们就逐一分析.最后,你会发现,你最常用.看起来最方便的形式确实最不推荐的一种形式. 常见的注入方式 Field注入 @Controller public class FooController { @Autowired // @

spring的bean管理(注解方式)

1.Spring的Bean管理的中常用的注解 @Component:组件.(作用在类上) public interface UserDao {     public void sayHello(); }   @Component(value="userDao")     public class UserDaoImpl implements UserDao {   @Override public void sayHello() {     System.out.println(&qu

Spring常用的三种注入方式

好文要收藏,摘自:https://blog.csdn.net/a909301740/article/details/78379720 Spring通过DI(依赖注入)实现IOC(控制反转),常用的注入方式主要有三种:构造方法注入,setter注入,基于注解的注入. 构造方法注入先简单了解一下测试项目的结构,用maven构建的,四个包: entity:存储实体,里面只有一个User类dao:数据访问,一个接口,两个实现类service:服务层,一个接口,一个实现类,实现类依赖于IUserDaote

spring 声明式事务管理注解方式实现

使用注解实现Spring的声明式事务管理,更加简单! 步骤: 1) 必须引入Aop相关的jar文件 2) bean.xml中指定注解方式实现声明式事务管理以及应用的事务管理器类 3)在需要添加事务控制的地方,写上: @Transactional @Transactional注解: 1)应用事务的注解 2)定义到方法上: 当前方法应用spring的声明式事务 3)定义到类上:   当前类的所有的方法都应用Spring声明式事务管理; 4)定义到父类上: 当执行父类的方法时候应用事务. 案例: 1.

Spring MVC 数据验证——validate注解方式

1.说明 学习注解方式之前,应该先学习一下编码方式的spring注入.这样便于理解验证框架的工作原理.在出错的时候,也能更好的解决问题.所以本次博客教程也是基于编码方式,只是在原来的基础加上注解方式. 2.配置信息 web.xml不需要改变的 hello-servlet.xml将原来的加载方式,改为自动加入有hibernate和Spring提供的validate的默认类,配置如下: <?xml version="1.0" encoding="UTF-8"?&g

【Spring】—AOP之AspectJ注解方式实现声明式事务管理

前言 这回来说下注解方式的声明式事务管理. 正文 Demo 1.引入相关的jar包这里写图片描述 2.引入AOP约束<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/con

「spring」定时任务(纯注解方式)

[问题现象] 需要通过纯注解方式启动定时任务,网上搜索到的定时任务大部分都是配置+注解. [问题解决] /** * 定时任务:打印CPU使用率 */@Component@EnableSchedulingpublic class PrintCpuWorker {    @Scheduled(cron="0/10 * *  * * ? ") // 每10秒一次    public void print() {        System.out.println("PrintCpu

Spring Aop的三个注解:@Around,@Before,@After

最近抽时间看了一些aop.好像翻译叫做切片技术.大概也能说明白是什么意思. 其中,有三个注解需要注意,分别是@Around,@Before,@After. 其中 @Around进行切片捕捉,可以捕捉到joinpoint(理解成切片对象方法). 即对方法A进行切片,则A被调用时,执行@Around.@Around可以调用 joinPoint.proceed()实际执行切片对象方法. @Before在切片方法对象实际调用前执行. @After方法在@Around方法之后调用. 注意,如果在Aroun