Java Web Spring框架学习(二)

本文接着上次的文章记录我的Spring学习过程:点击打开链接

为一个bean注入值除了可以用property标签,还可以用constructor-arg标签进行配置,要求在相应的类中有相应的构造函数,举id为something的例子。

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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd" >
    <bean id="app" class="Tools.app"></bean>
    <bean id="mybean" class="Tools.Mybean" >
        <property name="name" value="hjy"></property>
        <property name="age" value="19"></property>
        <property name="id" value="1008611"></property>
        <property name="something" ref="something"></property>
    </bean>
    <bean id="something" class="Tools.sth">
        <constructor-arg name="name" value="xxx"/>
        <constructor-arg name="type" value="xxx"/>
    </bean>
</beans>
sth.java:

package Tools;

public class sth {
    public String name;
    public String type;
    sth(String name,String type)
    {
        this.name=name;
        this.type=type;
    }
    public void setName(String name) {
        this.name = name;
    }
    public void setType(String type) {
        this.type = type;
    }
}

bean子标签property标签的属性ref表示引用,ref+bean的id,表示对一个bean的引用,用于一个类的数据中存在另一个类的实例化对象时使用
说一下bean的自动装填,在beans属性中有一个default-autowire,下面是他可以填的值

Bean的自动装配(Autowiring)

1.No:不做任何操作(默认)
2.byname:根据属性名自动装配。此选项将检查容器并根据名字查找与属性完全一致的bean,并将其与属性自动装配
3.byType:如果容器中存在一个与指定属性类型相同的bean,那么将与该属性自动装配;如果存在多个该类型的bean,那么抛出异常,并指出不能使用byType方式进行自动装配;如果没有找到相匹配的bean,则什么事都不发生
4.Constructor:与byType方式类似,不同之处在于它应用于构造器参数。如果容器中没有找到与构造器参数类型一致的bean,那么抛出异常

Bean的自动装配:在beans标签配置属性 default-autowire="no/byName/byType/constructor" 
作用为:省去了在Spring的xml中配置property标签和constructor-arg标签,只需要配置bean标签即可
PS:byName和byType为设值注入,constructor为构造注入;
byName要求bean标签的id属性需要和成员变量的名称一致,
byType和constructor则跟id无关

No为默认值,不会自动装填,byname属性会遍历该容器所有的bean,按照类中实例的名字来匹配容器中id相同的bean填进去,byType会匹配容器中class和需要实例化的对象的class相同的bean填进去,constructor需要该类有相应的构造函数,这个我一开始没看懂也是实践的出来的

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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd" default-autowire="constructor">
    <bean id="app" class="Tools.app"></bean>
    <bean id="mybean" class="Tools.Mybean" >
        <property name="name" value="hjy"></property>
        <property name="age" value="19"></property>
        <property name="id" value="1008611"></property>
    </bean>
    <bean id="something" class="Tools.sth">
        <property name="name" value="water"></property>
        <property name="type" value="liquid"></property>
    </bean>
</beans>
Mybean.java:

package Tools;

public class Mybean{
    private String name;
    private int age;
    private int id;
    private sth something;
    Mybean(sth something)
    {
        this.something=something;
    }
    public void setSomething(sth something) {
        this.something = something;
    }
    public void setName(String name) {
        this.name = name;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public void setId(int id) {
        this.id = id;
    }
    public void Say(String s)
    {
        System.out.println(name+","+age+","+id+","+something.name+","+something.type+","+s);
    }
}
这样就可以通过构造器来自动找到type相同的bean装填进去

Resources (针对于资源文件的统一接口)

A、UrlResource:URL 对应的资源,根据一个 URL 地址即可获取
B、ClassPathResource:获取类路径下的资源
C、FileSystemResource:获取文件系统里面的资源
D、ServletContextResource:ServletContext 封装的资源,用于访问 ServletContext 环境下的资源
E、InputStreamResource:获取输入流封装的资源
F、ByteArrayResource:获取字节数组封装的资源

通过实现 ApplicationContextAware 接口中的方法 
setApplicationContext(ApplicationContext applicationContext)

Resource resource = applicationContext.getResource("xxx");

classpath:config.txt
file:C:\\config.txt
ftp:C:\\config.txt
http://www.baidu.com/more/

在Spring中可以使用一些注释来代替xml文件中的配置,可以避免xml文件过大,使得代码更简洁,可以省去很多set方法代码

<context:component-scan base-package="包名"/>在xml中beans标签之间加入这个可以自动扫描包下的注释生成bean

Spring中的注释:

可用于生成bean的标签:

@Controller :注解控制器类(控制层 MVC)

@Service :注解服务类(服务层)

@Repository :注解 DAO 类(持久层)

@Component :将普通的 bean 注解到 spring 容器中,相当于配置文件中的<bean id="xxx" class="xxx"/>(不推荐用)

@Configuration把一个类作为一个IoC容器,它的某个方法头上如果注册了@Bean,就会作为这个Spring容器中的Bean。

@Bean:初始化一个bean并注册到springIoc容器加以管理。结合@Configuration(类上)使用,@Bean注解初始化生成的bean,在不指定名称时,是该注解注解的成员方法的名字

eg:
@Bean
public A getA(){return new A();}//该bean在注册到SpringIoc容器里的名称是getA.
指定名称@Bean(name="xx")时,该bean在注册到SpringIoc容器里的名称是xx
@Bean(name="" initMethod="" destroyMethod=""),支持init和destroy,同xxx.xml配置文件效果相同。

几个常用的注释:

@Autowired:用于setter方法 ,成员变量,构造器上,会自动匹配相应的bean注入到成员中

@Required:用于setter方法,参数可以是false,表示不一定要注入值,那么该bean值就为null,一个类只能有一个true方法,为true时表示一定要找到bean并注入值,不常用,可以直接写在Autowired的参数里面

@Qualifier:放在Autowired注释下,加参数表示用特定的bean注入,适用于type一样但是有很多bean的情况

@Resource:和Autowired注释差不多的用法也是查找bean注入值,可以加name=“xxx”的参数相当于Qualifier注释,因为是java ee自带的建议多用这个减少对spring的依赖

@Scope:singleton,prototype表示单例和多例,放在可以生成bean的注释下面使用

@PostConstruct用于指定初始化方法(用在方法上)

@PreDestory用于指定销毁方法(用在方法上)

我写了个简单的小工程测试上面的一些标签:

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="Tools"/>
    <bean id="testA" class="Tools.mouse"></bean>
    <bean id="testB" class="Tools.mouse"></bean>
</beans>
接口类tool.java:

package Tools;

public interface tool {
    public void show();
}

一个类mouse.java:

package Tools;

import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;

public class mouse {
    public String name;
    mouse()
    {
        name="mouse";
    }
}


实现类:

computer.java:

package Tools;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;

@Service
public class computer implements tool {
    @Autowired
            @Qualifier("testA")
    mouse m;
    public void show()
    {
        System.out.println("computer!"+m.name);
    }
}
mobile.java:

package Tools;

import org.springframework.stereotype.Service;

@Service
public class mobile implements tool{
    public void show()
    {
        System.out.println("mobile!");
    }
}
获得context的类:

context.java:

package Tools;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.stereotype.Repository;
import org.springframework.stereotype.Service;

@Repository
public class context {
    public static ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml");
}

测试类:

mainTest.java:

package Tools;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.context.ApplicationContext;

public class mainTest {
    @Test
    public void someTest()
    {
        ApplicationContext con=context.context;
        tool thingA= (computer) con.getBean("computer");
        thingA.show();
        tool thingB=(mobile)con.getBean("mobile");
        thingB.show();
    }
}
输出结果:

computer!mouse
mobile!

因为在xml中注册了mouse类的bean有2个,@Autowired下如果不写Qualifier会报错,也可以直接用一个@Resource(name="testA")这种写法代替,用了注释确实是省去了一堆set方法

收藏两篇文章:

https://www.cnblogs.com/xiaoxi/p/5935009.html
https://www.cnblogs.com/xingzc/p/5777814.html

收集慕课网笔记:

Bean 的定义及作用域注解

A、@Controller :注解控制器类(控制层 MVC)
B、@Service :注解服务类(服务层)
C、@Repository :注解 DAO 类(持久层)
D、@Component :将普通的 bean 注解到 spring 容器中,相当于配置文件中的<bean id="xxx" class="xxx"/>

元注解(Meta-annotations)
元注解即是许多 Spring 提供的注解可以作为自己的代码,元注解是一个简单的注解,可以应用到另一个注解
除了 value() 元注解还可以有其他的属性,允许定制

类的自动监测及 Bean 的注册
Spring 可以自动检测类并注册 Bean 到 Applicationcontext 中

<context:annotation-config />
通过基于 xml 的 Spring 配置

为了能够自动检测到这些类并注册相应的 Bean ,需要
<context:component-scan base-package="xxx" />

<context:component-scan> 包含 <context:annotation-config>,通常使用前者后,就不需要再使用后者

使用过滤器进行自定义扫描

A、默认情况下,类被自动发现并注册 bean 的条件:使用 @Component @Repository @Service @controller 注解或者使用 @Component 的自定义注解

B、可以通过过滤器修改默认注解的行为

C、还可以使用 use-default-filters = "false" 禁用自动发现与注册


@Autowired注解
A、可以通过添加注解给需要该类型的数组的字段或者方法,以提供 ApplicationContext 中的所有特定类型的 Bean
B、可以用于装配 key 为 string 的 map
C、如果希望数组有序,可以让 Bean 实现 org.springframework.core.Ordered 接口或者使用 @Order 注解
可以使用@Autowaird注解那些众所周知的解析依赖性接口,
比如:BeanFactory,ApplicationContext,Environment,ReaourceLoader,ApplicationEventPublisher,and MessagSource
比如可以声明一个ApplicationContext的一个引用,并使用@Autowaird注解,就可以在当前类中得到IOC的上下文信息,并可以使用上下文信息

按类型自动装配可能有多个bean实例的情况,可以使用Spring的@Qualifier注解缩小范围或者指定唯一,也可以用于指定单独的构造器参数或方法参数,也可用于注解集合类型变量;
用法如下:
如果使用bean装配则不需要再Spring XML中配置,直接在bean类中使用 @Qualifier("beanName")
如果需要在Spring XML中配置,则在bean标签下添加<qualifier value="名称"></qualifier>,然后在bean类中使用@Qualifier("名称")
虽然@Resource和@Autowired都可以来完成注入依赖,但它们之间是有区 别的。首先来看一下:
 a。@Resource默认是按照名称来装配注入的,只有当找不到与名称匹配的bean才会按照类型来装配注入;
 b。@Autowired默认是按照类型装配注入的,如果想按照名称来转配注入,则需要结合@Qualifier一起使用;
 c。@Resource注解是又J2EE提供,而@Autowired是由spring提供,故减少系统对spring的依赖建议使用  
       @Resource的方式;

property文件是key-value键值对形式的文件,

加载资源文件:
<context:property-placeholder location="classpath:/com/acme/jdbc.propertied"/>

加载这个文件后,可以再当前文件中采用${jdbc.url}这种形式来使用配置文件中的内容.
例如:
<property name="url" value="${jdbc.url}"/>

如果使用注解则:
在类名前加上:
@Configuration
@ImportResource("classpath:/com/acme/propertied-config.xml")引入一个资源,对应一个xml文件中包含property_placeholder

在配置文件中使用username的时候需要注意:username输出有时会是登录用户的username,所以一般在配置文件中配置例如jdbc.username的形式以防止混淆.


Spring不但支持自己定义的@Autowired注解,还支持几个由JSR-250规范定义的注解,它们分别是@Resource、@PostConstruct以及@PreDestroy。
  @Resource的作用相当于@Autowired,只不过@Autowired按byType自动注入,而@Resource默认按 byName自动注入罢了。@Resource有两个属性是比较重要的,分是name和type,Spring将@Resource注解的name属性解析为bean的名字,而type属性则解析为bean的类型。所以如果使用name属性,则使用byName的自动注入策略,而使用type属性时则使用byType自动注入策略。如果既不指定name也不指定type属性,这时将通过反射机制使用byName自动注入策略。
  @Resource装配顺序
  1. 如果同时指定了name和type,则从Spring上下文中找到唯一匹配的bean进行装配,找不到则抛出异常
  2. 如果指定了name,则从上下文中查找名称(id)匹配的bean进行装配,找不到则抛出异常
  3. 如果指定了type,则从上下文中找到类型匹配的唯一bean进行装配,找不到或者找到多个,都会抛出异常
  4. 如果既没有指定name,又没有指定type,则自动按照byName方式进行装配;如果没有匹配,则回退为一个原始类型进行匹配,如果匹配则自动装配;



猜你喜欢

转载自blog.csdn.net/qq_37497322/article/details/79018176