• 尚学堂Spring视频教程(四):使用Annotation


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

    @Autowired

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

    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
    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

    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,就报异常

      先看一个报错的例子

    <?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>
    配置文件
    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
    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();
            
        }
    
    }
    单元测试

      看到了吧,默认按照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来注入

    <?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注解

    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
    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
    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去掉了

    <?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>
    修改后的配置文件
    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

     项目组织如图:

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

     最后,再说三个注解

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

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

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

  • 相关阅读:
    Android Volley入门到精通:定制自己的Request
    Android高效加载大图、多图解决方案,有效避免程序OOM
    Android Volley入门到精通:使用Volley加载网络图片
    Android Volley入门到精通:初识Volley的基本用法
    彻底理解ThreadLocal
    Android中Parcelable接口用法
    Handler详解系列(四)——利用Handler在主线程与子线程之间互发消息,handler详解
    Storm流处理项目案例
    021 使用join()将数组转变为字符串
    020 $.each的使用
  • 原文地址:https://www.cnblogs.com/SamFlynn/p/4598666.html
Copyright © 2020-2023  润新知