Spring注解 Spring除了默认的使用xml配置文件的方式实现配置之外,也支持使用注解方式实现配置,这种方式效率更高,配置信息清晰,代码在哪对应的配置就在哪,方便开发阶段修改,推荐使用。 所谓注解就是给程序看的提示信息,很多时候都用来作为轻量级配置的方式。 关于注解的知识点,参看java基础课程中java基础加强部分的内容。
Spring注解方式实现IOC
a.导入开发包
b.编写配置文件
<?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模版,方便后续自动生成。 c.开启包扫描 在配置文件中,开启包扫描,指定spring自动扫描哪些个包下的类。只有在指定的扫描包下的类上的IOC注解才会生效。
<?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>d.使用注释注册bean 在配置的包中的类上使用 @Component注解,则这个类会自动被注册为bean,使用当前类的class为< bean>的class,通常情况下使用类名首字母小写为< bean>id。
案例:
package cn.tedu.beans; import org.springframework.stereotype.Component; @Component public class Person{ }e.bean的id 通常情况下注解注册bean使用类名首字母小写为bean的id,但是如果类名的第二个字母为大写则首字母保留原样.
cn.tedu.beans.Person --> <bean id="person" class="cn.tedu.beans.Person"/> 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属性,明确的指定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工厂。 a.配置工厂类 工厂类必须放在包扫描目录下,且被@Component注解修饰 b.配置工厂类中生产bean的方法 工厂中生产bean的方法要被@Bean修饰 则此方法会被SpringIOC调用,并将返回的对象注册为Spring的bean,默认自动推断id,也可以通过value属性手工指定id。 @Component public class Pesron5Factory { @Bean("per5") public Person5 getInstance(){ return new Person5("xx"); } } Spring注解方式实现DI a.导入开发包b.编写配置文件,并导入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 "> </beans>c.配置开启注解实现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> </beans>d.注解方式注入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中进行引入。
e.注解方式注入spring内置支持的类型数据 - 集合类型 引入util名称空间,通过适当的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 "> <!-- 开启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> </beans>再在类的属性中通过@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 + "]"; } }f.使用注解注入自定义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,而不会进行基于类型的匹配。
**也可以使用@Resource(name=“id”)指定注入给定id的bean,但是这种方式不建议大家使用。
其他注解 a.@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 { }b.@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.."); } }c.@PostConstruct 在bean对应的类中 修饰某个方法 将该方法声明为初始化方法,对象创建之后立即执行。
d.@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的销毁方法。。。"); } }e.@Controller @Service @Repository @Component 这四个注解的功能是完全相同的,都是用来修饰类,将类声明为Spring管理的bean的。 其中@Component一般认为是通用的注解 而@Controller用在软件分层中的控制层,一般用在web层 而@Service用在软件分层中的业务访问层,一般用在service层 而@Repository用在软件分层中的数据访问层,一般用在dao层
