-
classpath扫描与组件管理
@Componmet是通用注解,可用于任何bean,是@Respository、@Service、@Controller的父注解,后三个注解更具有针对性。
- @Respository通常用于DAO,即持久层
- @Service通常用于Service,即业务层
- @Controller通常用于Controller,即控制层
Spring还可以自定义注解,利用元注解(元数据注解),比如@service注解的定义中用到了@Componmet,同时元注解还可以定义其他属性,例如:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Scope("session")
public @interface SessionScope {
ScopedProxyMode proxyMode() default ScopedProxyMode.DEFAULT;
}
-
类的自动检测与注册
1)配置文件中配置
要使用自动注解,首先在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">
</beans>
①<context:annotation-config />
这个标签处理@autowired之类的注解(AutowiredAnnotationBeanPostProcessor、RequiredAnnotationBeanPostProcessor、CommonAnnotationBeanPostProcessor以及PersistenceAnnotationBeanPostProcessor四个类) 前提是注解作用的类已经被注册到spring容器里。
②<context:component-scan base-package="com.xx.xx" />
除了包含annotation-config的作用外,还能自动扫描和注册base-package下有@component、@Respository、@Service、@Controller之类注解的类,将其作为bean注册到spring容器里,此配置包含annotation-config,使用此配置可以不在使用annotation-config。
a、使用过滤器自定义扫描
<?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">
<!--忽略所有@Repository注解使用Stub下的注解代替-->
<context:component-scan base-package="test">
<context:include-filter type="regex" expression=".*Stub.*Repository"></context:exclude-filter>
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Repository"></context:exclude-filter>
</context:component-scan>
</beans>
b、禁用自动注册与发现
use-default-filters="false"
2)使用注解标注
被@Respository、@Service、@Controller、@Controller等注解标注的类,spring会自动检测到bean并自动注册到ApplicationContext中。
①bean名称生成规则
扫描过程中组件被自动检测,那么bean名称由BeanNameGenerator生成(@Respository、@Service、@Controller、@Controller都有属性用于显性设置beanName),如果注解处线性设置name,那么注册到上下文中的beanName以显示设置为主,如果未设置,spring会将被注解标注的类名首字母小写作为bean在上下文中的名称。
②可自定义bean命名规则,需实现BeanNameGenerator接口,并一定要包含一个无参的构造函数,同时在xml文件中配置name-generator。
<context:component-scan base-package="test" name-generator="">
</context:component-scan>
-
作用域(scope)
默认情况下spring组件是singleton模式,我们可以通过@Scope注解来自定义设置作用域类型(例如:@Scope("prototype"))。也可以自定义scope策略,实现ScopeMetadataResolver接口并创建无参构造函数。
<context:component-scan base-package="test" scope-resolver="">
</context:component-scan>
-
@Required注解
- 该注解适用于bean属性的setter方法。
- 表示受影响的bean属性必须在配置时被赋值。
-
@Autowired注解
@Autowired根据类型进行自动装配的。如果当spring上下文中存在不止一个同类型的bean时,会抛出异常,可以使用@Qualifier来指定名称。
@Autowired是由SpringBeanPostProcessor处理的,所以不能在自己的BeanPostProcessor或BeanFactoryPostPorcessor类型应用这些注解,这些类型必须通过使用XML或者@Bean注解加载。
①setter、构造、属性注入
此注解可用于setter方法、构造器、成员变量上,默认情况下如果找不到bean,会抛出异常,可以通过使用@Autowired(required=false)来避免。在使用@Autowired注解时,需要注意,每个类只有一个构造器允许被标记为@Autowired(required=true),如果要使用多个,可以使用@Required来代替。
@Service
public class InjectionServiceImpl implements InjectionService {
//@Autowired属性注入
private InjectionDAO injectionDAO;
//构造注入
@Autowired
public InjectionServiceImpl(InjectionDAO injectionDAO){
this.injectionDAO = injectionDAO;
}
//@Autowired setter方法注入
public void setInjectionDAO(InjectionDAO injectionDAO) {
this.injectionDAO = injectionDAO;
}
public void say() {
injectionDAO.doSomeThing();
System.out.println("这里是Service方法.....");
}
}
②解析依赖性接口
可以使用@Autowired解析依赖性接口,例如:BeanFactory、ApplicationContext、ResourceLoader等
@Component
public class MoviceRecommender {
@Autowired
private ApplicationContext context;
public void analysisContext() {
System.out.println("内容 : " + context.getId());
}
}
③注入某类型的数组(List、Set等)和Map(key必须时String类型)
注入某类型的数组或Map时,spring会自动将数据组的类型注入,需要注意的时Map类型注入时,key必须时string类型,同时@order注解对map类型注入无效;
public interface BeanInterface {}
@Order(2)
@Component
public class BeanImpl1 implements BeanInterface {}
@Order(1)
@Component
public class BeanImpl2 implements BeanInterface {}
@Component
public class MutilBean{
@Autowired
private List<BeanInterface> list;
@Autowired
private Map<String,BeanInterface> map;
public void say(){
if (list != null){
for (BeanInterface bean : list){
System.out.println(bean.getClass().getSimpleName());
}
}else{
System.out.println("list is null");
}
if(map != null){
for (Map.Entry<String,BeanInterface> bean : map.entrySet() ){
System.out.println(bean.getKey() +" "+bean.getValue());
}
}else{
System.out.println("map is null");
}
}
}
-
@Qualifier注解
如果spring上下文中存在多类型,无法使用@Autowired进行注入时,可以通过时用@Qualifier来标注具体注入的bean名称,@Qualifier除了在成员变量、构造器、setter方法上使用外,还可以使用在类型参数中,例如:
public void say(@Qualifier("name1") String name){}
@Resource也可以通过名称注入,适用于成员变量、只有一个参数的setter方法,所以在使用构造器或多参setter方法时,最好使用@Qualifier和@Autowired。
-
基于java的容器注解
1)@Bean注解
用于配置和初始化SpringIOC容器管理的新对象的方法类似于XML中<bean id="beanScope" class="com.base.java.test.BeanScope" ></bean>
配置,通常与@configuration配合使用,如何@Bean不指定名称,系统会按照@Bean所在的方法名标记为name。@Bean也可以指定initMethod和destroyMethod。默认情况下@Bean默认情况下是单例的,可以使用@Scope来改变。
public class StringStore {
public void init(){
System.out.println("init...");
}
public void destory(){
System.out.println("destory...");
}
}
@Configuration
public class StoreConfig {
@Bean(name="store",initMethod = "init",destroyMethod = "destory")
public StringStore getStringStore(){
return new StringStore();
}
}
2)@Value和@ImportResource注解
这两个注解作用是引入配置资源文件,例如:
①创建资源文件名称db.properties,信息为:
jdbc.url=172.0.0.1
jdbc.driver=com.mysql.jdbc.Driver
jdbc.userName=root
jdbc.password=1234
②在配置文件中设置信息文件名context-db.xml,
<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:property-placeholder location="db.properties"></context:property-placeholder>
</beans>
③创建Java类
public class MyDriverManager {
public MyDriverManager(String url,String driver,String userName,String password){
System.out.println("url : " +url);
System.out.println("driver : " + driver);
System.out.println("userName : " + userName);
System.out.println("password : " + password);
}
}
@Configuration
@ImportResource("classpath:context-db.xml")
public class DBStore {
@Value("${jdbc.url}")
private String url;
@Value("${jdbc.driver}")
private String driver;
@Value("${jdbc.userName}")
private String userName;
@Value("${jdbc.password}")
private String password;
@Bean
public MyDriverManager myDriverManager(){//未指定名称,默认按方法名称注册
return new MyDriverManager(url,driver,userName,password);
}
}
使用applicationContext.getBean("myDriverManager")或注解获取信息。
此方式的xml配置方式如下:
<beans>
<context:annotation-config/>
<context:property-placeholder location="classpath:db.properties"/>
<bean class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.userName}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
</beans>
-
基于泛型的自动装配(spring4.x以后支持)
本部分摘录:https://blog.csdn.net/u010837612/article/details/45582043
public class User {
}
public class Role {
}
public class BaseRepository<T> {
public void add(){
System.out.println("Repository add");
}
}
public class BaseService<T> {
@Autowired
private BaseRepository<T> repository;
public void add(){
repository.add();
}
}
@Repository
public class UserReponsitory extends BaseRepository<User> {
}
@Service
public class UserService extends BaseService<User> {
}
@Repository
public class RoleReponsitory extends BaseRepository<Role> {
}
@Service
public class RoleService extends BaseService<Role> {
}
public class Main {
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("spring-generic.xml");
UserService userService = (UserService) ctx.getBean("userService");
userService.add();
}
}
Spring会根据泛型类型自动区分BaseService属于RoleService还是UserService,UserService的父类和UserReponsitory的父类产生联系,那么通过泛型,UserService和UserReponsitory也产生联系。此种方式适用于将重复的代码封装起来通过继承来简化代码,对代码进行复用。
-
@Resource注解
Spring还支持使用JSR-250@Resource注解,此注解可标记成员变量和setter方法,在Java EE5和6之后支持,由spring的CommonAnnotationBeanPostProcess这个类发现并处理的。这个还可以处理@PostConstruct(初始化)和@PreDestory(销毁)这两个注解。
@Resource注解可以指定name属性@Resource(name=""),如果不指定,对于成员变量spring会以变量名称解析,对于setter方法,spring会以方法名解析。
@Repository
public class JsrDao {
public void save(){
System.out.println("jsr dao save()..");
}
}
@Service
public class JsrService{
@Resource
private JsrDao jsrDao;
public void save(){
jsrDao.save();
}
@PostConstruct
public void init(){
System.out.println("init");
}
@PreDestroy
public void destory(){
System.out.println("destory");
}
}
-
JSR330标准注解
Spring3.0开始支持JSR330标准注解,扫描方式于spring注解一致,使用JSR330标准注解依赖javax.inject包。
①@Inject注解
这个注解等效于@Autowired,可适用于类、成员变量、方法、构造器。
②@Named注解
@Name注解与@Component注解是等效的,不同的是此注解可用于参数指定具体名称。
private JsrDao jsrDao;
@Inject
public void setJsrDao(@Named("jsrDao") JsrDao jsrDao){
this.jsrDao = jsrDao;
}