Spring注解
Spring除了默认的使用xml配置文件的方式实现配置之外,也支持使用注解方式实现配置,这种方式效率更高,配置信息清晰,代码在哪对应的配置就在哪,方便开发阶段修改,推荐使用。
所谓注解就是给程序看的提示信息,很多时候都用来作为轻量级配置的方式。
关于注解的知识点,参看java基础课程中java基础加强部分的内容。
Spring注解方式实现IOC
导入开发包
计算机生成了可选文字:V Referenced Libraries 》 0 》 0 》 0 》 0 》 0 》 0
commons-logging-I .0.4.Jar spring-beans-4.3.25.RELEASE.Jar
spring-context4.3.25.RELEASE.Jar spring-context-support-4.3 需 要 比 之 前
spring-core4.3.25.RELEASE 多 导 入 一 spring-expression4.3.25.R 个 aop 包
spring-test4.3.25.RELEASE 刂 , nn . 3 0 -4.3.25.RELEASE 1 3 r
编写配置文件,并导入context约束
<?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
">
**可以将以上头信息加入MyEclipse模版,方便后续自动生成。
开启包扫描
在配置文件中,开启包扫描,指定spring自动扫描哪些个包下的类。只有在指定的扫描包下的类上的IOC注解才会生效。
<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>
-->
使用注解注册bean
在配置的包中的类上使用@Component注解,则这个类会自动被注册为bean,使用当前类的class为的class,通常情况下使用类名首字母小写为id。
案例:
package cn.tedu.beans;
import org.springframework.stereotype.Component;
@Component
public class Person{
}
bean的id
通常情况下注解注册bean使用类名首字母小写为bean的id,但是如果类名的第二个字母为大写则首字母保留原样.
1
2
3
cn.tedu.beans.Person -->
cn.tedu.beans.PErson -->
cn.tedu.beans.NBA -->
也可以通过在@Component中配置value属性,明确的指定bean的id
案例:
**可以使bean类实现BeanNameAware接口,并实现其中的setBeanName方法,spring容器会在初始化bean时,调用此方法告知当前bean的id。通过这个方式可以获取bean的id信息。
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;
@Component(“per”)
public class Person implements BeanNameAware{
@Override
public void setBeanName(String name) {
System.out.println("==="+this.getClass().getName()+"==="+name);
}
}
Spring注解方式实现IOC - 工厂注册bean
Spring默认通过反射创建bean,如果某些bean没有无参构造器或创建过程非常复杂,则无法通过简单的反射创建bean,此时可以通过指定创建bean的工厂,令SpringIOC通过工厂来创建bean,从而进行注册。
可以通过配置文件方式配置bean工厂,同样也可以通过注解配置bean工厂。
配置工厂类
工厂类必须放在包扫描目录下,且被@Component注解修饰
配置工厂类中生产bean的方法
工厂中生产bean的方法要被@Bean修饰
则此方法会被SpringIOC调用,并将返回的对象注册为Spring的bean,默认自动推断id,也可以通过value属性手工指定id。
@Component
public class Pesron5Factory {
@Bean("per5")
public Person5 getInstance(){
return new Person5("xx");
}
}
Spring注解方式实现DI
导入开发包
计算机生成了可选文字:V Referenced Libraries 》 0 》 0 》 0 》 0 》 0 》 0
commons-logging-I .0.4.Jar spring-beans-4.3.25.RELEASE.Jar
spring-context4.3.25.RELEASE.Jar spring-context-support-4.3 需 要 比 之 前
spring-core4.3.25.RELEASE 多 导 入 一 spring-expression4.3.25.R 个 aop 包
spring-test4.3.25.RELEASE 刂 , nn . 3 0 -4.3.25.RELEASE 1 3 r
编写配置文件,并导入context约束
<?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
">
配置开启注解实现DI选项
<?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
">
<!-- 开启IOC包扫描 -->
<context:component-scan base-package="cn.tedu.domain"/>
<!-- 开启注解配置DI -->
<context:annotation-config></context:annotation-config>
注解方式注入spring内置支持的类型数据 - 非集合类型
spring中可以通过@Value注解来实现spring内置支持的类型的属性的注入。
package cn.tedu.domain;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component
public class Student {
@Value("zs")
private String name;
@Value("19")
private int age;
@Override
public String toString() {
return "Student [name=" + name + ", age=" + age + "]";
}
}
这种方式可以实现spring内置支持类型的注入,但是这种方式将注入的值写死在了代码中,后续如果希望改变注入的值,必须来修改源代码,此时可以将这些值配置到一个properties配置文件中,再在spring中进行引入。
计算机生成了可选文字:person -data.properties id = 888 name:zs
计算机生成了可选文字:〈 ?xml version: ’ ’ . e ” encoding: ” U 丆 F 一 8 ” ? 〉
彐 < b e a n s xmlns = ’ ’ h 亡 亡 : / / . org/schema/beans
xmlns : context: ’ ’ h 亡 亡 : / / 鼽 呲 . springframework . org/schema/context ’
xmlns : xsi: ’ ’ h 亡 亡 : / / . 3 . org/2Æ1/XMLSchema- instance
xsi : schemaLocation: ’ ’ h 亡 亡 : / / 鼽 . springframework . org/schema/beans
h 亡 亡 : / / ‘v’ . springframework . org/schema/beans/spring- beans-3.2 . xs 冒
h 亡 亡 : / / 鼽 ‘v’ . springframework . org/schema/context
h 亡 亡 : / / ‘v’ . springframework . org/schema/context/spring- 00n 亡 ex 亡 . . 2 .
k ! “ 开 启 属 性 注 解 “ 习
〈 c 0 n t e Xt : annotation- config) 〈 /context : annotation- config)
〈 C 0 n t e X t : component-scan base-package: "cn . tedu. beans ”〉 〈 /context : C 0
〈 C 0 n ex : p 0 p e y . p a C e 0
location: ’ ’ 0 乙 ass 0 亡 h :/person - 0 亡 0 . properties 〈 /beans
计算机生成了可选文字:ackage cn.tedu.beans;
impo rt 0 r g . springframework.beans .factory .BeanN. @Com/onent ( “per” )
public 1 a s s P e r s 0 n implement s BeanNameAwaref @value(’ idY’
p rIva e In 1 value( " ) p rIva e r 1 n g name; @Autowired p rivat e Dog dog;
@Autowired p rivat e Cat cat;
注解方式注入spring内置支持的类型数据 - 集合类型
引入util名称空间,通过适当的util标签注册数据
<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
">
<!-- 开启IOC包扫描 -->
<context:component-scan base-package="cn.tedu.domain"/>
<!-- 开启注解配置DI -->
<context:annotation-config></context:annotation-config>
<!-- 引入Properties文件 -->
<context:property-placeholder location="classpath:/stu.properties"/>
<!-- 配置集合数据 -->
<util:list id="l1">
<value>aaa</value>
<value>bbb</value>
<value>ccc</value>
</util:list>
<util:set id="s1">
<value>111</value>
<value>222</value>
<value>333</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>
</util:map>
<util:properties id="p1">
<prop key="p1">v1</prop>
<prop key="p2">v2</prop>
<prop key="p3">v3</prop>
</util:properties>
再在类的属性中通过@Value注入赋值
package cn.tedu.domain;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component
public class Student {
@Value("${name}")
private String name;
@Value("${age}")
private int age;
@Value("#{@l1}")
private List<String> list;
@Value("#{@s1}")
private Set<String> set;
@Value("#{@m1}")
private Map<String,String> map;
@Value("#{@p1}")
private Properties prop;
@Override
public String toString() {
return "Student [name=" + name + ", age=" + age + ", list=" + list
+ ", set=" + set + ", map=" + map + ", prop=" + prop + "]";
}
}
使用注解注入自定义bean类型数据:
在bean中的属性上通过@Autowired实现自定义bean类型的属性注入
代码:
package cn.tedu.domain;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component
public class Student {
@Autowired
private Dog dog;
@Autowired
private Cat cat;
@Override
public String toString() {
return "Student [dog="+ dog + ", cat=" + cat + "]";
}
}
当Spring容器解析到@Component注解时,创建当前类的bean在spring容器中进行管理,在创建bean的过程中发现了@Autowired注解,会根据当前bean类型,寻找在spring中是否存在该类型的bean,找到直接注入,如果找不到还会检查是否有子孙类、实现类存在,如果存在唯一的则自动注入,如果还是没有找到或找到多个无法注入,则还会按照属性名对应id去查找对应的bean,如果存在则注入,如果还是没有找到则抛出异常。
也可以额外配置@Qualifier(value=“dog1”)注解强制要求按照id寻找bean,则此时会直接使用给定的id寻找bean,而不会进行基于类型的匹配。
计算机生成了可选文字:发现@Autowired 开 始 注 入 自 定 义 bean 是否有@QuaIifier 否 按 照 类 型 匹 配
是 否 找 到 唯 一 的 bea n 否 按 照 id 匹 配 是 否 找 到 唯 一 的 bea n 否 抛 出 异 常 结 束 注 入 注 入
**也可以使用@Resource(name=“id”)指定注入给定id的bean,但是这种方式不建议大家使用。
其他注解
@Scope(value=“prototype”)
配置修饰的类的bean是单例还是多例,如果不配置默认为单例
案例:
package cn.tedu.domain;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
@Component
@Scope(“prototype”)
public class Teacher {
}
@Lazy
配置修饰的类的bean采用懒加载机制
案例:
package cn.tedu.domain;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;
@Component
@Lazy
public class Teacher {
public Teacher() {
System.out.println("teacher construct..");
}
}
@PostConstruct
在bean对应的类中 修饰某个方法 将该方法声明为初始化方法,对象创建之后立即执行。
@PreDestroy
在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的销毁方法。。。");
}
}
@Controller @Service @Repository @Component
这四个注解的功能是完全相同的,都是用来修饰类,将类声明为Spring管理的bean的。
其中@Component一般认为是通用的注解
而@Controller用在软件分层中的控制层,一般用在web层
而@Service用在软件分层中的业务访问层,一般用在service层
而@Repository用在软件分层中的数据访问层,一般用在dao层