Spring注解
传统的Spring做法是使用.xml文件来对bean进行注入或者是配置aop、事物,这么做有两个缺点:
- 如果所有的内容都配置在.xml文件中,那么.xml文件将会十分庞大;如果按需求分开.xml文件,那么.xml文件又会非常多。总之这将导致配置文件的可读性与可维护性变得很低。
- 在开发中在.java文件和.xml文件之间不断切换,是一件麻烦的事,同时这种思维上的不连贯也会降低开发的效率。
为了解决这两个问题,Spring引入了注解,通过”@XXX”的方式,让注解与Java Bean紧密结合,既大大减少了配置文件的体积,又增加了Java Bean的可读性与内聚性。
修改配置文件applicationContext.xml,开启注解扫描:
<?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:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 开启注解扫描 -->
<context:component-scan base-package="com.hu"></context:component-scan>
</beans>
修改实体类Person.java:
@Component
public class Person {
@Value("hu")
private String name;
@Value("22")
private int age;
@Value("男")
private char sex;
//构造方法、Setter、Getter和toString@ComponentScan
...
}
测试类Demo.java:
public class Demo {
public static void main(String[] args) {
ClassPathXmlApplicationContext context =
new ClassPathXmlApplicationContext("applicationContext.xml");
//通过context获取Person对象
Person person = (Person) context.getBean("person");
System.out.println(person);
context.close();
}
}
运行结果:

若在一个类上标注@Component注解,表示该类会作为一个bean,被加入到spring容器中。该类需要在配置文件中配置的扫描包下目录或子目录下(注解都需要被扫描到才能启用)。
使用注解 取代 xml配置文件
@Component
@Component
取代<bean class="">
@Component("id")
取代 <bean id="" class="">
@ComponentScan(“xxx”)
相当于配置文件中的<context:component-scan base-package="xxx" />
标签,该标签也需要被spring扫描到才能启用。若配置文件只扫描com.hu.pojo
包,而@ComponentScan
注解却在com.hu.demo
包下的类中,则该注解不会被启用。若配置文件只扫描com.hu.pojo
包,在该包下的类上标注@ComponentScan("com.hu.demo")
,则com.hu.demo
包下的注解都会被扫描加入到spring容器中。
@Configuration
该类等价 与XML中配置beans,相当于Ioc容器,它的某个方法头上如果注册了@Bean
,就会作为这个Spring容器中的Bean,与xml中配置的bean意思一样。
@Bean
@Bean是一个方法级别上的注解,主要用在@Configuration注解的类里,也可以用在@Component注解的类里。添加的bean的id为方法名。
依赖注入,给私有字段设值,也可以给setter方法设值
普通值:
@Value(“”)
可以直接使用@Value(“值”)给类的属性赋值。为了简化从properties里取配置,可以使用@Value, 可以properties文件中的配置值。
在Spring配置文件中引入properties文件有两种写法:
1、直接使用<context:property-placeholder>
标签,把xxx.properties文件路径写进去就可以了。
<context:property-placeholder location="classpath:xxx.properties"/>
用法是:${…} 。如果我要取url的数据,直接写成这样:${url}
2、配置成bean的形式。
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<!--可以配置多个资源文件 -->
<list>
<value>classpath:xxx.properties</value>
</list>
</property>
</bean>
引用值:
- 按照【类型】注入@Autowired
- 按照【名称】注入1@Autowired@Qualifier(“名称”)
- 按照【名称】注入2@Resource(“名称”)
作用域:
@Scope
配置bean的作用域。默认是单例模式,即@Scope(“singleton”)。
@Singleton
只要在类上加上这个注解,就可以实现一个单例类,不需要自己手动编写单例实现类。
生命周期:
Spring 容器中的 Bean 是有生命周期的,Spring 允许在 Bean 在初始化完成后以及 Bean 销毁前执行特定的操作,常用的设定方式有以下三种:
1.通过实现 InitializingBean
/DisposableBean
接口来定制初始化之后/销毁之前的操作方法;
2.通过 <bean>
元素的 init-method
/destroy-method
属性指定初始化之后 /销毁之前调用的操作方法;
3.在指定方法上加上@PostConstruct
或@PreDestroy
注解来制定该方法是在初始化之后还是销毁之前调用
但他们之前并不等价。即使3个方法都用上了,也有先后顺序.
Constructor > @PostConstruct >InitializingBean > init-method
@PostConstruct
在构造方法和init-method
方法(如果有的话)之间得到调用,且只会执行一次。初始化bean之前进行的操作,只能有一个方法可以用此注释进行注释,方法不能有参数,返回值必需是void,方法需要是非静态的。
@PreDestroy
注解的方法在destroy-method
方法调用后得到执行。销毁bean之前进行的操作,只能有一个方法可以用此注释进行注释,方法不能有参数,返回值必需是void,方法需要是非静态的。
@Autowired
Autowired默认先按byType,如果发现找到多个bean,则,又按照byName方式比对,如果还有多个,则报出异常。可以手动指定按byName方式注入,使用@Qualifier(“xxx”)。
当使用@Autowired注解的时候,其实默认就是@Autowired(required=true),表示注入的时候,该bean必须存在,否则就会注入失败。@Autowired(required=false):表示忽略当前要注入的bean,如果有直接注入,没有跳过,不会报错。
@Resource
默认按 byName自动注入,如果找不到再按byType找bean,如果还是找不到则抛异常,无论按byName还是byType如果找到多个,则抛异常。
可以手动指定bean,它有2个属性分别是name和type,使用name属性,则使用byName的自动注入,而使用type属性时则使用byType自动注入。@Resource(name=bean名字”)或@Resource(type=”bean的class”)
@Primary
自动装配时当出现多个Bean候选者时,被注解为@Primary
的Bean将作为首选者,否则将抛出异常。
在Spring容器中由于子类Bean和父类Bean是同一个Java类。若是通过@Autowired
(通过类型)注入,则会找到子类和父类多个bean,程序会默认使用父类bean。若在某个子类上标注@Primary
注解,则spring容器会优先提供该bean。
@Lazy
value 取值有 true 和 false 两个,默认值为 true。true 表示使用 延迟加载, false 表示不使用,false 纯属多余,如果不使用,不标注该注解就可以了。延迟加载的意思是,一开始并不加载该值,在用到该值时再去加载(若一些类的某些属性值在某些方法中并没有使用到,若加载进去就会浪费内存),延时加载在hibernate中比较常见。