之前我们的bean都配置在XML里,并且通过bean的property标签来指定依赖关系,如果项目很大,那岂不是要配置很多这样的property标签?Spring提供了注解的方式来解决这个问题

 

@Autowired

  在需要注入的bean的setter方法上加这个注解,就不需要指定property标签了,因为Spring会通过byType的方式去寻找对应类型的bean自动的注入,如果找到了多个同类型的bean,就会报异常

尚学堂Spring****(四):使用Annotation

尚学堂Spring****(四):使用Annotation尚学堂Spring****(四):使用Annotation
package com.bjsxt.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;

import com.bjsxt.dao.UserDAO;
import com.bjsxt.model.User;



public class UserService {
    
    private UserDAO userDAO;  
    
    public void init() {
        System.out.println("init");
    }
    
    public void add(User user) {
        userDAO.save(user);
    }
    public UserDAO getUserDAO() {
        return userDAO;
    }
    
    @Autowired
    public void setUserDAO( UserDAO userDAO) {
        this.userDAO = userDAO;
    }
    

    
    public void destroy() {
        System.out.println("destroy");
    }
}
加上@AutoWired注解的UserService
尚学堂Spring****(四):使用Annotation尚学堂Spring****(四):使用Annotation
package com.bjsxt.service;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.bjsxt.model.User;

//Dependency Injection
//Inverse of Control
public class UserServiceTest {

    @Test
    public void testAdd() throws Exception {
        ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
        
        
        UserService service = (UserService)ctx.getBean("userService");
        service.add(new User());
        
        ctx.destroy();
        
    }

}
单元测试

  运行,会报错,因为发现了u和u2两个可以注入的bean,去掉一个,运行成功

 

@Qualifier

  针对上面的问题,我们可以使用@Qualifier注解,这个注解是通过byName的方式,也就是可以指定id,这个注解需要加在setter方法的参数的最前面,有一个参数表示依赖的bean的id

尚学堂Spring****(四):使用Annotation尚学堂Spring****(四):使用Annotation
package com.bjsxt.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;

import com.bjsxt.dao.UserDAO;
import com.bjsxt.model.User;



public class UserService {
    
    private UserDAO userDAO;  
    
    public void init() {
        System.out.println("init");
    }
    
    public void add(User user) {
        userDAO.save(user);
    }
    public UserDAO getUserDAO() {
        return userDAO;
    }
    
    
    public void setUserDAO(@Qualifier("u") UserDAO userDAO) {
        this.userDAO = userDAO;
    }
    

    
    public void destroy() {
        System.out.println("destroy");
    }
}
加上@Qualifier注解的UserService

  这样运行就不会报错了,因为会直接找到id为u的bean注入到UserService的userDAO属性

 

@Resource

  这个注解遵循JSR-250标准,属于J2EE的注解,所以引入新的包“common-annotation.jar”。同样在setter方法上使用该注解,其他部分同上。注意该注解默认使用的是byName的方式,如果没有指定该注解的name属性值,会默认的寻找以setter方法参数的名称为id的bean,例如本例中setter方法的参数名是“userDAO”,就会在配置文件中寻找id为“userDAO”的bean,如果没有找到,就按照byType的方式,如果又发现了两个符合类型的bean,就报异常

  先看一个报错的例子

尚学堂Spring****(四):使用Annotation尚学堂Spring****(四):使用Annotation
<?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-2.5.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-2.5.xsd">
    <context:annotation-config />
  <bean id="u" class="com.bjsxt.dao.impl.UserDAOImpl">
  </bean>
  <bean id="u2" class="com.bjsxt.dao.impl.UserDAOImpl">
  </bean>
    
  <bean id="userService" class="com.bjsxt.service.UserService" >
      
  </bean>
  

</beans>
配置文件
尚学堂Spring****(四):使用Annotation尚学堂Spring****(四):使用Annotation
package com.bjsxt.service;
import javax.annotation.Resource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;

import com.bjsxt.dao.UserDAO;
import com.bjsxt.model.User;



public class UserService {
    
    private UserDAO userDAO;  
    
    public void init() {
        System.out.println("init");
    }
    
    public void add(User user) {
        userDAO.save(user);
    }
    public UserDAO getUserDAO() {
        return userDAO;
    }
    
    @Resource
    public void setUserDAO( UserDAO userDAO) {
        this.userDAO = userDAO;
    }
    

    
    public void destroy() {
        System.out.println("destroy");
    }
}
    
使用@Resource注解的UserService
尚学堂Spring****(四):使用Annotation尚学堂Spring****(四):使用Annotation
package com.bjsxt.service;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.bjsxt.model.User;

//Dependency Injection
//Inverse of Control
public class UserServiceTest {

    @Test
    public void testAdd() throws Exception {
        ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
        
        
        UserService service = (UserService)ctx.getBean("userService");
        service.add(new User());
        
        ctx.destroy();
        
    }

}
单元测试

尚学堂Spring****(四):使用Annotation

  看到了吧,默认按照byName,本来想找id为“userDAO”的bean,结果配置文件中没有,就转为按照byType的方式,结果找到了两个符合类型的bean,id分别为"u"和“u2”。解决办法是给注解加上name="u"来指定一个想要的bean,或者不加name属性,直接在配置文件中指定一个id为"userDAO"bean

 

@Component

  上面的一些注解尽管已经很方便了,但是配置文件里还是要写很多需要被用来注入的bean标签,有没有办法可以让我们连bean标签都不用写呢,答案是肯定的,使用@Component注解就可以做到,我们首先需要在配置文件中加上一句<context:component-scan base-package="com.bjsxt"/>,这句代码的意思就是说:配置文件里面的bean都不用写了,你直接去com.bjsxt下面所有的包里面去扫描加了@componet注解的类作为需要的bean来注入

尚学堂Spring****(四):使用Annotation尚学堂Spring****(四):使用Annotation
<?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-2.5.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-2.5.xsd">
    <context:annotation-config />
    <context:component-scan base-package="com.bjsxt"/>
        
  <bean id="userService" class="com.bjsxt.service.UserService" >
      
  </bean>
  
</beans>
配置文件

  已经不用写被用来注入的bean标签了,在setter方法加了@Resource注解的基础上,我们需要在被用来注入的类上加上@Component注解

尚学堂Spring****(四):使用Annotation尚学堂Spring****(四):使用Annotation
package com.bjsxt.dao.impl;

import org.springframework.stereotype.Component;
import org.springframework.stereotype.Controller;

import com.bjsxt.dao.UserDAO;
import com.bjsxt.model.User;

@Component("u") 
public class UserDAOImpl implements UserDAO {

    public void save(User user) {
        //Hibernate
        //JDBC
        //XML
        //NetWork
        System.out.println("user saved!");
    }

}
UserDAO的实现类UserDAOImpl
尚学堂Spring****(四):使用Annotation尚学堂Spring****(四):使用Annotation
package com.bjsxt.service;
import javax.annotation.Resource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;

import com.bjsxt.dao.UserDAO;
import com.bjsxt.model.User;


/*@Component("userService")*/
public class UserService {
    
    private UserDAO userDAO;  
    
    public void init() {
        System.out.println("init");
    }
    
    public void add(User user) {
        userDAO.save(user);
    }
    public UserDAO getUserDAO() {
        return userDAO;
    }
    
    @Resource(name="u")
    public void setUserDAO( UserDAO userDAO) {
        this.userDAO = userDAO;
    }
    

    
    public void destroy() {
        System.out.println("destroy");
    }
}
UserService
尚学堂Spring****(四):使用Annotation尚学堂Spring****(四):使用Annotation
package com.bjsxt.service;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.bjsxt.model.User;

//Dependency Injection
//Inverse of Control
public class UserServiceTest {

    @Test 
    public void testAdd() throws Exception {
        ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
        
        UserService service = (UserService)ctx.getBean("userService");
        service.add(new User());
        
        ctx.destroy();
        
    }

}
单元测试

  @Resource和@Component都可以指定一个name来相互对应,这样就可以准确知道setter方法的参数具体需要那个被用来注入的类了

  另外我们发现配置文件中还有一个名为“userService”的bean,因为测试代码中调用了getbean("userservice")这个方法,如果把bean标签去掉就找不到了,会报错,我们可以在该bean对应的类上加上@Component标签,并指定名称"userservice”,这样就可以直接把配置文件中的bean去掉了

尚学堂Spring****(四):使用Annotation尚学堂Spring****(四):使用Annotation
<?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-2.5.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-2.5.xsd">
    <context:annotation-config />
    <context:component-scan base-package="com.bjsxt"/>
        
  
</beans>
修改后的配置文件
尚学堂Spring****(四):使用Annotation尚学堂Spring****(四):使用Annotation
package com.bjsxt.service;
import javax.annotation.Resource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;

import com.bjsxt.dao.UserDAO;
import com.bjsxt.model.User;


@Component("userService")
public class UserService {
    
    private UserDAO userDAO;  
    
    public void init() {
        System.out.println("init");
    }
    
    public void add(User user) {
        userDAO.save(user);
    }
    public UserDAO getUserDAO() {
        return userDAO;
    }
    
    @Resource(name="u")
    public void setUserDAO( UserDAO userDAO) {
        this.userDAO = userDAO;
    }
    

    
    public void destroy() {
        System.out.println("destroy");
    }
}
加上@Component的UserService

 项目组织如图:

尚学堂Spring****(四):使用Annotation

  注:在spring2.5中,@Component,@Repository,@Controller,@Service的作用是一样的,不过在后续版本中就不一定了

 最后,再说三个注解

 @Scope:参数可以指定为“singleton”或“prototype”,和之前讲的一样,指定bean的生存范围,直接加在类名上就可以了

 @PostConstruct:代表之前bean中的init-method,加在方法上就可以了

 @PreDestroy:代表之前bean中destroy-method,加在方法上就可以了

相关文章:

  • 2021-06-12
  • 2021-09-25
  • 2021-07-02
  • 2022-02-17
  • 2021-10-20
  • 2021-06-06
  • 2021-09-11
  • 2021-06-24
猜你喜欢
  • 2021-05-20
  • 2022-02-05
  • 2021-07-10
  • 2022-12-23
  • 2022-12-23
  • 2021-05-09
  • 2021-10-05
相关资源
相似解决方案