GVKun编程网logo

Spring @Autowired用法(spring中@autowired作用)

12

在这里,我们将给大家分享关于Spring@Autowired用法的知识,让您更了解spring中@autowired作用的本质,同时也会涉及到如何更有效地@Autowired用法详解、Shiro+St

在这里,我们将给大家分享关于Spring @Autowired用法的知识,让您更了解spring中@autowired作用的本质,同时也会涉及到如何更有效地@Autowired用法详解、Shiro+Struts2+Spring3 加上 @RequiresPermissions 后 @Autowired 失效、Spring - @Autowired 与 @Resource、spring @Autowired map的内容。

本文目录一览:

Spring @Autowired用法(spring中@autowired作用)

Spring @Autowired用法(spring中@autowired作用)

在Spring会连接的类中使用@Autowired的优缺点是什么?

只是为了澄清一下,我是在专门讨论@Autowired注释,而不是XML的自动装配。

我可能只是不了解它,但是对我来说,这几乎就像是一种反模式-你的类开始意识到它们与DI框架相关联,而不仅仅是POJO。也许我是受惩罚的嘴,但我喜欢为bean提供外部XML配置,而且我喜欢使用显式的接线,因此我确切知道在哪里接线。

答案1

小编典典

很长时间以来,我认为拥有像我们所有人过去使用的xml文件一样的“集中式,声明式配置”是有价值的。然后我意识到文件中的大多数内容都不是配置 -开发后从未在任何地方进行过更改。然后我意识到,“集中”只有在非常小的系统价值-只有在小型系统会你永远能够神交配置文件作为一个整体。当相同的“接线”大部分被代码中的依赖项复制时,从整体上理解接线的真正价值是什么?因此,我唯一保留的是元数据(注释),它仍然是声明性的。这些永远不会在运行时更改,也永远不会 有人会即时更改的“配置”数据-所以我认为将其保存在代码中很好。

我会尽量使用全自动布线。我喜欢它。除非有枪口威胁,否则我不会回到老式的spring。@Autowired随着时间的流逝,我完全喜欢的理由已经改变。

现在,我认为使用自动装配的最重要原因是系统中要跟踪的抽象较少。“ bean名称”实际上已经消失了。事实证明,由于xml,bean名称仅存在。因此,完整的抽象间接层(将bean名称“ foo”连接到bean“ bar”的地方)消失了。现在,我将“ Foo”接口直接连接到我的bean中,并通过运行时配置文件选择实现。这使我可以在跟踪依赖关系和实现时使用代码。当我在代码中看到自动装配的依赖项时,只需在IDE中按“转到实现”键,就会出现已知实现的列表。在大多数情况下,只有一个实现,而我直接进入课堂。能够’ 正在使用什么实现(我声称与xml连线相反的事实更接近真相-有趣的是你的观点如何改变!)

现在你可以说这只是一个非常简单的层,但是我们添加到系统中的每个抽象层都会增加复杂性。我真的不认为xml可以为我使用过的任何系统增加任何实际价值。

我曾经使用过的大多数系统只有一个生产运行时环境的配置。可能还有其他测试配置等等。

我想说的是,自动装配是spring的红宝石:它包含了这样一种观念,即大多数用例都遵循一种正常且通用的使用模式。使用XML配置,你可以允许 /可能不希望使用大量一致/不一致的配置。我已经看到太多的xml配置因不一致而泛滥成灾-它会与代码一起重构吗?以为没有。这些变化是有原因的吗?通常不会。

我们几乎没有在配置中使用限定符,而是找到了解决这些情况的其他方法。这是我们遇到的一个明显的“缺点”:我们已经略微更改了编码方式,以使其与自动装配的交互更加顺畅:客户存储库不再实现通用Repository<Customer>接口,而是使接口CustomerRepository可扩展Repository<Customer>。有时在子类化方面还有一两个窍门。但这通常只是为我们指明了更强类型化的方向,我发现这几乎总是一个更好的解决方案。

但是,是的,你绑定的是大多数spring都采用的特定DI风格。我们甚至不再为依赖项设置公共设置器(因此,你可以说我们在封装/信息隐藏部门中为+1)。我们的系统中仍然有一些xml,但是xml基本上只包含异常。完全自动装配与xml很好地集成在一起。

现在我们唯一需要的是将@Component@Autowired其余的都包含在JSR中(如JSR-250),因此我们不必与spring捆绑在一起。这就是过去发生的事情的方式(这些java.util.concurrent东西浮现在脑海中),所以如果再次发生这种情况,我不会感到完全惊讶。

@Autowired用法详解

@Autowired用法详解

  • @Autowired 注释,它可以对类成员变量、方法及构造函数进行标注,完成自动装配的工作。 通过 @Autowired的使用来消除 set ,get方法。在使用@Autowired之前,我们对一个bean配置起属性时,是这用用的

    <property name="属性名" value=" 属性值"/>

    通过这种方式来,配置比较繁琐,而且代码比较多。在Spring 2.5 引入了 @Autowired 注释

     

    下面用案例来具体说明

    UserRepository.java

    1 package com.proc.bean.repository;
    2 
    3 public interface UserRepository {
    4     
    5     void save();
    6 }

    这里定义了一个UserRepository接口,其中定义了一个save方法

     

    UserRepositoryImps.java

    复制代码
    1 package com.proc.bean.repository;
     2 
     3 import org.springframework.stereotype.Repository;
     4 
     5 @Repository("userRepository")
     6 public class UserRepositoryImps implements UserRepository{
     7 
     8     @Override
     9     public void save() {
    10         System.out.println("UserRepositoryImps save");
    11     }
    12 }
    复制代码

    定义一个UserRepository接口的实现类,并实现save方法,在这里指定了该bean在IoC中标识符名称为userRepository

     

    UserService.java

    复制代码
    1 package com.proc.bean.service;
     2 
     3 import org.springframework.beans.factory.annotation.Autowired;
     4 import org.springframework.stereotype.Service;
     5 
     6 import com.proc.bean.repository.UserRepository;
     7 
     8 @Service
     9 public class UserService {
    10 
    11     @Autowired
    12     private UserRepository userRepository;
    13     
    14     public void save(){
    15         userRepository.save();
    16     }
    17 }
    复制代码

    这里需要一个UserRepository类型的属性,通过@Autowired自动装配方式,从IoC容器中去查找到,并返回给该属性

     

    applicationContext.xml配置

    <context:component-scan base-package="com.proc.bean" />

     

    测试代码:

    1 ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml");
    2 
    3 UserService userService=(UserService) ctx.getBean("userService");
    4 userService.save();

    输出结果:UserRepositoryImps save

     

    那么使用@Autowired的原理是什么?

      其实在启动spring IoC时,容器自动装载了一个AutowiredAnnotationBeanPostProcessor后置处理器,当容器扫描到@Autowied、@Resource或@Inject时,就会在IoC容器自动查找需要的bean,并装配给该对象的属性

    <bean/>

      

     注意事项:

      在使用@Autowired时,首先在容器中查询对应类型的bean

        如果查询结果刚好为一个,就将该bean装配给@Autowired指定的数据

        如果查询的结果不止一个,那么@Autowired会根据名称来查找。

        如果查询的结果为空,那么会抛出异常。解决方法时,使用required=false

     

    举例说明:

     在上面例子中,我们在定一个类来实现UserRepository接口

    复制代码
    package com.proc.bean.repository;
    
    import org.springframework.stereotype.Repository;
    
    @Repository
    public class UserJdbcImps implements UserRepository {
    
        @Override
        public void save() {
            System.out.println("UserJdbcImps save");
        }
    }
    复制代码

      这时在启动容器后,在容器中有两个UserRepository类型的实例,一个名称为userRepository,另一个为userJdbcImps。在UserService中

    @Autowired
    private UserRepository userRepository;

      输出结果:UserRepositoryImps save

      这里由于查询到有两个该类型的实例,那么采用名称匹配方式,在容器中查找名称为userRepository的实例,并自动装配给该参数。

     

      如果这里想要装载userJdbcImps的实例,除了将字段userRepository名称改成userJdbcImps外,可以提供了一个@Qualifier标记,来指定需要装配bean的名称,代码这样写

    1 @Autowired
    2 @Qualifier("userJdbcImps")
    3 private UserRepository userRepository;

    输出结果:UserJdbcImps save

 

转自:https://www.cnblogs.com/caoyc/p/5626365.html

Shiro+Struts2+Spring3 加上 @RequiresPermissions 后 @Autowired 失效

Shiro+Struts2+Spring3 加上 @RequiresPermissions 后 @Autowired 失效

今天一 iteye 网页在问答频道提问【Shiro+Struts2+Spring3 加上 @RequiresPermissions 后 @Autowired 失效】,记录一下。

 

问题:

 

@ParentPackage("all") 
@Namespace("/project") 
public class ProjectAction extends BaseAction { 
public final static Logger logger = LoggerFactory 
.getLogger(ProjectAction.class); 

@Autowired(required=true) 
private ProjectService projectService;

 如上代码 @Autowired 注入不了

 

 

分析:

1、首先从如上代码可以看出 走的是 struts2 注解,而且使用了 struts2 convention 插件,这个插件会扫描如下配置的 actionPackages 寻找 action

 

<filter> 
        <filter-name>struts2</filter-name> 
        <filter-classfilter-class>org.apache.struts2.dispatcher.filter.StrutsPrepareAndExecuteFilter</filter-class> 
        <init-param> 
<param-name>actionPackages</param-name> 
<param-value>cn.javass</param-value> 
</init-param>

 

 

2、但此时并没有把 action 交给 spring,

3、接下来,因为集成了 spring(有 struts2-spring-plugin),所以要使用 StrutsSpringObjectFactory 创建 bean,代码分析

 

@Override 
    public Object buildBean(String beanName, Map<String, Object> extraContext, boolean injectInternal) throws Exception { 
        Object o; 
        
        if (appContext.containsBean(beanName)) { 
            o = appContext.getBean(beanName); //拿不到bean 
        } else { 
            Class beanClazz = getClassInstance(beanName); 
            o = buildBean(beanClazz, extraContext); //所以创建了一个 
        } 
        if (injectInternal) { 
            injectInternalBeans(o); 
        } 
        return o; 
    }

 

/** 
     * @param clazz 
     * @param extraContext 
     * @throws Exception 
     */ 
    @Override 
    public Object buildBean(Class clazz, Map<String, Object> extraContext) throws Exception { 
        Object bean; 

        try { 
            // Decide to follow autowire strategy or use the legacy approach which mixes injection strategies 
            if (alwaysRespectAutowireStrategy) {//默认false 
                // Leave the creation up to Spring 
                bean = autoWiringFactory.createBean(clazz, autowireStrategy, false); 
                injectApplicationContext(bean); 
                return injectInternalBeans(bean); 
            } else { 
                bean = autoWiringFactory.autowire(clazz, AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR, false); //只走构造器注入 
                bean = autoWiringFactory.applyBeanPostProcessorsBeforeInitialization(bean, bean.getClass().getName()); 
                // We don''t need to call the init-method since one won''t be registered. 
                bean = autoWiringFactory.applyBeanPostProcessorsAfterInitialization(bean, bean.getClass().getName()); 
                return autoWireBean(bean, autoWiringFactory); 
            } 
        } catch (UnsatisfiedDependencyException e) { 
            if (LOG.isErrorEnabled()) 
                LOG.error("Error building bean", e); 
            // Fall back 
            return autoWireBean(super.buildBean(clazz, extraContext), autoWiringFactory); 
        } 
    }

 

 我们在 shiro 里使用如下代码 去代理 shiro 的代理:

 

<bean id="proxyCreator" class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"
          depends-on="lifecycleBeanPostProcessor">
        <property name="proxyTargetClass" value="true"/>
    </bean>

    <bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
        <property name="securityManager" ref="securityManager"/>
    </bean>

 

 

//StrutsSpringObjectFactory 的如下代码将执行处理器的预处理

bean = autoWiringFactory.applyBeanPostProcessorsBeforeInitialization(bean, bean.getClass().getName());

 

//DefaultAdvisorAutoProxyCreator 的 postProcessBeforeInstantiation:将去完成代理 bean 因此此时将返回代理 Bean

 

// 接着 StrutsSpringObjectFactory 的 autoWireBean (bean, autoWiringFactory); 进行注入 所以此时注入到的是代理对象,因此如果字段注入 将注入不了。

 

 

解决方案

 

1、不使用 actionPackages   而是 在类上加  @Controller @Scope 完全走 spring  

2、使用 setter 注入 而不是字段 如 

  private ProjectService projectService; 

 

  @Autowired(required=true) 

  public void setProjectService() { 

  } 

 

 

Spring - @Autowired 与 @Resource

Spring - @Autowired 与 @Resource

1、@Autowired 与 @Resource 都可以用来装配 bean. 都可以写在字段上,或写在 setter 方法上。 

2、@Autowired 默认按类型装配(这个注解属于 Spring),默认情况下必须要求依赖对象必须存在,
如果要允许 null 值,可以设置它的 required 属性为 false,如:@Autowired (required=false) ,
如果我们想使用名称装配可以结合 @Qualifier 注解进行使用,
如下: 
@Autowired() @Qualifier("baseDao")     
private BaseDao baseDao;

 3、@Resource(这个注解属于 J2EE 的),默认安照名称进行装配,名称可以通过 name 属性进行指定, 
如果没有指定 name 属性,当注解写在字段上时,默认取字段名进行按照名称查找,
如果注解写在 setter 方法上默认取属性名进行装配。 
当找不到与名称匹配的 bean 时才按照类型进行装配。
但是需要注意的是,如果 name 属性一旦指定,就只会按照名称进行装配。
如下: 
@Resource(name="baseDao")     
private BaseDao baseDao;    

推荐使用 @Resource 注解在字段上,因为这个注解是属于 J2EE 的,可以减少了与 Spring 的耦合。

spring @Autowired map

spring @Autowired map

 注入map,平常一般不会这么做,今天在写一个demo时,有如下一段注入代码:

map bean 的创建

@Bean(name="userMap")
public Map<Long, User> userMap() {
    return new ConcurrentHashMap<Long, User>();
}
// 注入
@Autowired
@Qualifier("userMap")
private Map<Long, User> userMap;

怕出错,我还特意加了Qualifier限定符,但是spring 容器就起不来了,异常如下,大概意思就是map的key要是String类型才行:

Caused by: org.springframework.beans.FatalBeanException: Key type [class java.lang.Long] of map [java.util.Map] must be assignable to [java.lang.String]

原因如下:org.springframework.beans.factory.support.DefaultListableBeanFactory中的一段代码

Class<?> keyType = descriptor.getMapKeyType();
            if (keyType == null || !String.class.isAssignableFrom(keyType)) {
                if (descriptor.isRequired()) {
                    throw new FatalBeanException("Key type [" + keyType + "] of map [" + type.getName() +
                            "] must be assignable to [java.lang.String]");
                }
                return null;
            }


用set 方法也不行。但是使用如下方法却奏效了:

@Resource(name = "userMap")
private Map<Long, User> userMap;



关于Spring @Autowired用法spring中@autowired作用的问题就给大家分享到这里,感谢你花时间阅读本站内容,更多关于@Autowired用法详解、Shiro+Struts2+Spring3 加上 @RequiresPermissions 后 @Autowired 失效、Spring - @Autowired 与 @Resource、spring @Autowired map等相关知识的信息别忘了在本站进行查找喔。

本文标签: