注:以下所有测试案例(最后一个除外)的测试代码都是同一个:

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 IOCTest01 { @Test
public void test1(){
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
Person p = (Person) context.getBean("per");
System.out.println(p);
}
}

1.注解的概念

所谓注解就是给程序看的提示信息,很多时候都用来作为轻量级配置的方式。

关于注解的知识点,参看java基础课程中java基础加强部分的内容。

2.Spring中的注解

Spring除了默认的使用xml配置文件的方式实现配置之外,也支持使用注解方式实现配置,这种方式效率更高,配置信息清晰,修改更方便,推荐使用。

引入context名称空间:

在MyEclipse中导入spring-context-3.2.xsd约束文件,要求Spring来管理。

在applicationContext.xml文件中,引入该schema文件:

<?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"
> </beans>

**可以将以上头信息加入MyEclipse模版,方便后续自动生成。

3.使用类注解

使用Spring的类注解可以通过注解注册类为bean,省去了配置文件中的<bean>配置。

a.开启包扫描

在spring的配置文件中,开启包扫描,指定spring自动扫描哪些个包下的类。

<context:component-scan base-package="cn.tedu.beans"></context:component-scan>

案例:

<?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

案例:

package cn.tedu.beans;

import org.springframework.beans.factory.BeanNameAware;
import org.springframework.stereotype.Component; @Component("per")
public class Person implements BeanNameAware{ @Override
public void setBeanName(String name) { System.out.println("==="+this.getClass().getName()+"==="+name);
}
}

执行结果:

===cn.tedu.beans.Person===per
cn.tedu.beans.Dog@6f9ee23

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:component-scan base-package="cn.tedu.beans"></context:component-scan> <!-- 开启属性注解 -->
<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; public class Person implements BeanNameAware{
@Autowired
private Dog dog;
@Autowired
private Cat cat; public Dog getDog() {
return dog;
} public void setDog(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.属性注入类型数据的原理

当spring容器解析xml时,发现开启了属性注解,则会在创建bean时,检测属性上是否存在@Autowired注解,如果发现该注解,则会通过当前属性的名称寻找是否存在该id的bean,如果存在则注入进来,如果不存在,再检查是否存在和当前属性类型相同的bean,如果由则注入进来,如果都没有则抛出异常.

**也可以使用@Resource(name="id")指定注入给定id的bean,但是这种方式不建议大家使用。

d.spring内置支持注入类型的注解方式的注入 - 非集合类型

实例1:

spring中可以通过注解方式 注册bean,并可以通过@Autowired实现属性的自动注入,但注入的都是自定义的bean类型,如果类中包含例如 int long String等spring内置可注入的类型时,又该如何注入呢? 可以使用@Value注解来实现注入。

代码:

package cn.tedu.beans;

import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component; @Component("per")
public class Person implements BeanNameAware{
@Value("999")
private int id; @Value("zs")
private String name; @Autowired
private Dog dog; @Autowired
private Cat cat; public Dog getDog() {
return dog;
} public void setDog(Dog dog) {
this.dog = dog;
} public Cat getCat() {
return cat;
} public void setCat(Cat cat) {
this.cat = cat;
} @Override
public String toString() {
return "Person [id=" + id + ", name=" + name + ", dog=" + dog
+ ", cat=" + cat + "]";
} @Override
public void setBeanName(String name) { System.out.println("==="+this.getClass().getName()+"==="+name);
}
}

执行结果:

===cn.tedu.beans.Person===per
Person [id=999, name=zs, dog=cn.tedu.beans.Dog@5e6214f5, cat=cn.tedu.beans.Cat@794e113b]

这种方式可以实现spring内置类型的注入,但是这种方式将注入的值写死在了代码中,后续如果希望改变注入的初始值,必须来修改源代码。

实例2:

将需要配置的值放置到一个properties配置文件中,再在Spring中进行引入。

代码:

<?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> <!-- 开启属性注解 -->
<context:annotation-config></context:annotation-config> <!-- 配置文件引入 -->
<context:property-placeholder location="classpath:/person-data.properties"/> </beans>
package cn.tedu.beans;

import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component; @Component("per")
public class Person implements BeanNameAware{
@Value("${id}")
private int id; @Value("${name}")
private String name; @Autowired
private Dog dog; @Autowired
private Cat cat; public Dog getDog() {
return dog;
} public void setDog(Dog dog) {
this.dog = dog;
} public Cat getCat() {
return cat;
} public void setCat(Cat cat) {
this.cat = cat;
} @Override
public String toString() {
return "Person [id=" + id + ", name=" + name + ", dog=" + dog
+ ", cat=" + cat + "]";
} @Override
public void setBeanName(String name) { System.out.println("==="+this.getClass().getName()+"==="+name);
}
}

执行结果:

===cn.tedu.beans.Person===per
Person [id=888, name=zsf, dog=cn.tedu.beans.Dog@6293df2c, cat=cn.tedu.beans.Cat@5a20f443]

e.spring内置支持注入类型的注解方式的注入 - 集合类型

需要将集合类型的数据配置到spring配置文件中,再通过@Value引入

配置过程:

1.将spring-util-3.2.xsd交给MyEclipse管理

2.在当前spring容器的配置文件中导入util名称空间

3.再通过适当的util标签注册数据

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:util="http://www.springframework.org/schema/util"
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
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util-3.2.xsd"
> <!-- 开启包扫描 -->
<context:component-scan base-package="cn.tedu.beans"></context:component-scan> <!-- 开启属性注解 -->
<context:annotation-config></context:annotation-config> <!-- 配置文件引入 -->
<context:property-placeholder location="classpath:/person-data.properties"/> <util:list id="l1">
<value>北京</value>
<value>上海</value>
<value>广州</value>
<value>深圳</value>
</util:list> <util:set id="s1">
<value>射手</value>
<value>法师</value>
<value>打野</value>
<value>战士</value>
<value>坦克</value>
<value>打野</value>
</util:set> <util:map id="m1">
<entry key="k1" value="v1"></entry>
<entry key="k2" value="v2"></entry>
<entry key="k3" value="v3"></entry>
<entry key="k1" value="v1"></entry>
</util:map>
</beans>

再在类的属性中通过@Value注入赋值

package cn.tedu.beans;

import java.util.List;
import java.util.Map;
import java.util.Set; import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component; @Component("per")
public class Person implements BeanNameAware{
@Value("${id}")
private int id; @Value("${name}")
private String name; @Value("#{@l1}")
private List<String> addr; @Value("#{@s1}")
private Set<String> jobs; @Value("#{@m1}")
private Map<String,String> map; @Autowired
private Dog dog; @Autowired
private Cat cat; public Dog getDog() {
return dog;
}
public void setDog(Dog dog) {
this.dog = dog;
}
public Cat getCat() {
return cat;
}
public void setCat(Cat cat) {
this.cat = cat;
} @Override
public String toString() {
return "Person [id=" + id + ", name=" + name + ", addr=" + addr
+ ", jobs=" + jobs + ", map=" + map + ", dog=" + dog + ", cat="
+ cat + "]";
} @Override
public void setBeanName(String name) { System.out.println("==="+this.getClass().getName()+"==="+name);
}
}

执行结果:

===cn.tedu.beans.Person===per
Person [id=888, name=zsf,
addr=[北京, 上海, 广州, 深圳], jobs=[射手, 法师, 打野, 战士, 坦克], map={k1=v1, k2=v2, k3=v3},
dog=cn.tedu.beans.Dog@47f08ed8, cat=cn.tedu.beans.Cat@2322bce]

5.其他注解

a.@Scope(value="prototype")

配置修饰的类的bean是单例还是多例,如果不配置默认为单例

案例:

package cn.tedu.beans;

import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component; @Component
@Scope("prototype")
public class Dog { }

b.@Lazy

配置修饰的类的bean采用懒加载机制

案例:

package cn.tedu.beans;

import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component; @Component
@Lazy
public class Dog {
public Dog(){
System.out.println("Dog被创建出来了。。。");
}
}

运行结果:

Dog被创建出来了。。。
===cn.tedu.beans.Person===per
Person [id=888, name=zsf,
addr=[北京, 上海, 广州, 深圳], jobs=[射手, 法师, 打野, 战士, 坦克], map={k1=v1, k2=v2, k3=v3},
dog=cn.tedu.beans.Dog@77546dbc, cat=cn.tedu.beans.Cat@47f08ed8]

c.@PostConstruct

在bean对应的类中 修饰某个方法 将该方法声明为初始化方法,对象创建之后立即执行。

d.@PreDestory

在bean对应的类中 修饰某个方法 将该方法声明为销毁的方法,对象销毁之前调用的方法。

案例:

package cn.tedu.beans;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy; import org.springframework.stereotype.Component; @Component
public class Dog {
public Dog() {
System.out.println("Dog...被创建出来了...");
} @PostConstruct
public void init(){
System.out.println("Dog的初始化方法。。。");
} @PreDestroy
public void destory(){
System.out.println("Dog的销毁方法。。。");
}
}

测试:

package cn.tedu.test;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext; import cn.tedu.beans.Dog;
import cn.tedu.beans.Person; public class IOCTest01 { @Test
public void test1(){
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
Dog dog = (Dog) context.getBean("dog");
System.out.println(dog);
context.close();
}
}

运行结果:

e.@Controller @Service @Repository @Component

这四个注解的功能是完全相同的,都是用来修饰类,将类声明为Spring管理的bean的。

其中@Component一般认为是通用的注解

而@Controller用在软件分层中的控制层,一般用在web层

而@Service用在软件分层中的业务访问层,一般用在service层

而@Repository用在软件分层中的数据访问层,一般用在dao层

Spring 注解方式 实现 IOC 和 DI的更多相关文章

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

        1. 注解概念        所谓注解就是给程序看的提示信息,很多时候都用来作为轻量级配置的方式.        关于注解的知识点,参看java基础课程中java基础加强部分的内容.    2 ...

  2. 【Spring】XML方式实现(无参构造 有参构造)和注解方式实现 IoC

    文章目录 Spring IoC的实现方式 XML方式实现 通过无参构造方法来创建 1.编写一个User实体类 2.编写我们的spring文件 3.测试类 UserTest.java 4.测试结果 通过 ...

  3. Spring 使用纯注解方式完成IoC

    目录 创建一个简单的Person类 使用xml方式配置Spring容器并获取bean的过程 创建xml配置文件 进行测试 使用纯注解方式配置Spring容器并获取bean的过程 创建spring配置类 ...

  4. Spring入门一:IOC、DI、AOP基本思想

    Spring框架是一个集众多涉及模式于一身的开源的.轻量级的项目管理框架,致力于javaee轻量级解决方案.相对于原来学过的框架而言,spring框架和之前学习的struts2.mybatis框架有了 ...

  5. spring注解方式在一个普通的java类里面注入dao

    spring注解方式在一个普通的java类里面注入dao @Repositorypublic class BaseDaoImpl implements BaseDao {这是我的dao如果在servi ...

  6. (转)使用Spring注解方式管理事务与传播行为详解

    http://blog.csdn.net/yerenyuan_pku/article/details/52885041 使用Spring注解方式管理事务 前面讲解了怎么使用@Transactional ...

  7. Spring总结四:IOC和DI 注解方式

    首先我们要了解注解和xml配置的区别: 作用一样,但是注解写在Bean的上方来代替我们之前在xml文件中所做的bean配置,也就是说我们使用了注解的方式,就不用再xml里面进行配置了,相对来说注解方式 ...

  8. Spring中注解方式实现IOC和AOP

    1.IOC注解 1.1 IOC和DI的注解  IOC: @Component:实现Bean组件的定义 @Repository:用于标注DAO类,功能与@Component作用相当 @Service:用 ...

  9. Spring MVC -- Spring框架入门(IoC和DI)

    Spring MVC是Spring框架中用于Web应用开发的一个模块.Spring MVC的MVC是Model-View-Controller的缩写.它是一个广泛应用于图像化用户交互开发中的设计模式, ...

随机推荐

  1. python安装大型包时出现错误Unable to find vcvarsall.bat

    在windows平台上,据说是安装cpython编写的包时会出现Unable to find vcvarsall.bat这种错误,缺失编译C的环境或组件吧,所以这个包就安装不成功,这个时候简单的方法就 ...

  2. <NET CLR via c# 第4版>笔记 第15章 枚举类型和位标志

    15.1 枚举类型 枚举定义的符号是常量值. C#编译器编译时,会用数值替换符号,不再引用定义了符号的枚举类型.可能会出现一些版本问题. Enum.IsDefined(Type enumType, o ...

  3. header 输出原始的php报头文件

    header() 函数向客户端发送原始的 HTTP 报头. 认识到一点很重要,即必须在任何实际的输出被发送之前调用 header() 函数 (在 PHP 4 以及更高的版本中,您可以使用输出缓存来解决 ...

  4. eclipse运行报java.lang.OutOfMemoryError: PermGen space解决方法

    一.在window下eclipse里面Server挂的是tomcat6,一开始还是以为,tomcat配置的问题,后面发现,配置了tomcat里面的catalina.bat文件,加入 set JAVA_ ...

  5. 重构Tips

    一,重新组织函数1.首先找出局部变量和参数. 1>任何不会被修改的变量都可以当作参数传入.2.去掉临时变量Replace Temp with Query.用查询函数代替临时变量3.Extract ...

  6. SIM800C 使用基站定位

    /******************************************************************************* * SIM800C 使用基站定位 * ...

  7. opencv-python教程学习系列8-opencv图像算术运算

    前言 opencv-python教程学习系列记录学习python-opencv过程的点滴,本文主要介绍图像的算术运算,坚持学习,共同进步. 系列教程参照OpenCV-Python中文教程: 系统环境 ...

  8. 游标 cursor

    * mongo shell下支持JS代码,可以通过JS获取游标,进而获取数据操作结果. var cursor = db.class1.find() cursor.next() 获取下一条结果 curs ...

  9. ubuntu git生成ssh key (公钥私钥)配置github或者码云

    Git是分布式的代码管理工具,远程的代码管理是基于SSH的,所以要使用远程的Git则需要SSH的配置. github的SSH配置如下: 设置Git的user name和email: git confi ...

  10. 20155304 2016-2017-2 《Java程序设计》第九周学习总结

    20155304 2016-2017-2 <Java程序设计>第九周学习总结 教材学习内容总结 JDBC简介 撰写应用程序是利用通信协议对数据库进行指令交换,以进行数据的增删查找 JDBC ...