Spring学习记录

Java类定义配置

@Configuration //标记为配置类
@ComponentScan //标记为扫描当前包及子包所有标记为@Component的类
@ComponentScan(basePackageClasses = {接口.class,...}) //标记为扫描当前包及子包所有标记为@Component的类
@ComponentScan(basePackages = {包名,包名,...}) //标记为扫描当前包及子包所有标记为@Component的类

定义组件

@Component //标记为组件类
@Autowired //标记为自动导入
@Autowired(required=false) //标记为可选导入

自动装配歧义性

@Primary //标记为优先选择
@Qualifier //标记这个组件的别名或选择某个别名的组件作为导入对象
@Resource //

分层架构中定义组件

@Controller //标记为控制层组件,是@Component的即意化名称
@Service //标记为服务层组件,是@Component的即意化名称
@Repository //标记为数据层组件,是@Component的即意化名称

Spring测试环境,未能按照视频中的方式成功运行过,先记录着

@RunWith
@ContextConfiguration

使用xml启用组件扫描

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

显示装配情景

1.当某些情景下有些类无法进行自动装配时,可在 <span style="color:#B3AD28">@Configuration</span> 标记类中添加<span style="color:#FFAA33">public</span> 方法且在方法上添加 <span style="color:#B3AD28">@Bean</span>标记,这个时候Spring在进行扫描到 <span style="color:#B3AD28">@Configuration</span>类时便会在其中查找 <span style="color:#B3AD28">@Bean</span>标记进行容器托管 2.在多个非关联类中进行托管后在建立关联关系的时候可以通过某一个类的构造函数进行注入如:

@Configuration
public class Configs{
    @Bean //某些无法隐式自动注入的类进行托管
    public A getA(){
        return new A();
    }
    
    @Bean
    public B getB(){
        return new B(getA());//调用多次?,在spring中只会创建一次
    }
}
  • <strong style="color:#FF0000 ">or</strong>
@Configuration
public class Configs{
    @Bean //某些无法隐式自动注入的类进行托管
    public A getA(){
        return new A();
    }
    
    @Bean
    public B getB(A a){
        return new B(a);//调用多次?,在spring中只会创建一次
    }
}

处理自动装配歧义性

  • 首选bean
    • 在声明类的时候使用<span style="color:#B3AD28">@Primary</span>且在相同接口的实现类上只能定义一个
  • 使用限定符
    • 在声明的时候和装配的时候分别使用<span style="color:#B3AD28">@Qualifier</span>
  • 使用限定符和bean id
    • 在声明的时候指定bean的id(默认的id是首字母小写的类名)
    • 在装配的时候使用<span style="color:#B3AD28">@Qualifier</span>
    @Configuration
    public class Configs{
        @Bean
        @Qualifier("b")
        public A getBImplA(){
            return new B();//返回一个实现A接口的B类对象
        }
    
        @Bean
        @Qualifier("c")
        public A getCImplA(){
            return new C();//返回一个实现A接口的C类对象
        }
    
        @Bean
        public S getS(@Qualifier("b")A a){//注入A接口类型时指定了b这个别名的实现类
            return new S(a);
        }
    }
    
    • 如果在代码中不使用<span style="color:#B3AD28">@Qualifier</span>则可在形参上指定为<span style="color:#B3AD28">@Qualifier( <span style="color:#33CCFF">"getBImplA"</span> )</span>方法的名字即可

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">
    <!--id对bean的唯一性标记,字符间不得有空格-->
    <bean id="compactDisc" class="china.wuhan.soundsystem.CompactDisc"/>
    <!--name同样标记,但name可以用空格设定多个别名-->
    <bean name="compactDisc01 compactDisc02" class="china.wuhan.soundsystem.CompactDisc"/>
</beans>

<span style="color:#DDAA00">bean</span>标签属性中id与name同样标记名字,但id只能有一个且全局也只能有一个,而name可以设定多个名字,全局不允许有多个同时标记

使用XML进行构造函数的自动注入

package china.wuhan.soundsystem;

public class CompactDisc {
    public CompactDisc() {
        System.out.println("CompactDisc 构造函数..." + this.toString());
    }

    public void play(){
        System.out.println("播放CD音乐..." + this.toString());
    }
}
package china.wuhan.soundsystem;

public class CDPlay {

    private CompactDisc cd;

    public CDPlay() {
        System.out.println("CDPlay的无参构造..." + this.toString());
    }

    public CDPlay(CompactDisc cd) {
        this.cd = cd;
        System.out.println("CDPlay的有参构造..." + this.toString());
    }

    public void play(){
        cd.play();
    }
}
package china.wuhan.soundsystem;

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class App {
    public static void main(String[] args) {
        System.out.println("App running...");
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        CDPlay cdplay = (CDPlay)context.getBean("cdplay");
        cdplay.play();
    }
}
<?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="compactDisc" class="china.wuhan.soundsystem.CompactDisc"/>
    <bean id="cdplay" class="china.wuhan.soundsystem.CDPlay">
        <constructor-arg ref="compactDisc"/>
    </bean>
</beans>
  • 在针对构造函数多个入参进行注入时可以使用index属性或c名字空间
public class CompactDisc {
    public CompactDisc(String title,String name) {
        System.out.println("title " + title);
        System.out.println("name " + name);
        System.out.println("CompactDisc 构造函数..." + this.toString());
    }
}
<bean name="compactDisc" class="china.wuhan.soundsystem.CompactDisc">
    <constructor-arg index="0" value="Hello"></constructor-arg>
    <constructor-arg index="1" value="World"></constructor-arg>
</bean>
<bean name="compactDisc"
          class="china.wuhan.soundsystem.CompactDisc"
          c:title="Hello"
          c:name="World"/>
  • 上述呈现的两种均可,当然还有其它方法就不列举了,在使用c:名字空间时需要添加限定
xmlns:c="http://www.springframework.org/schema/c"
<bean id="cdplayer2" class="scorpius.soundsystem.CDPlayer" c:cd-ref="cd2"/>
c:  //表示使用c名字空间
cd  //作用在构造函数入参的变量名上,名字与构造函数入参的变量名一致
-ref //表示引用方式

如果构造函数中入参存在List,Map,Set等

  • List

  • 简单类型

<constructor-arg name="参数名字">
    <list>
        <value>1</value>
        <value>2</value>
        <value>3</value>
        ...
    </list>
</constructor-arg>
  • 对象类型
<constructor-arg name="参数名字">
    <list>
        <ref bean="bean ID"/>
        ...
    </list>
</constructor-arg>
  • Set
<constructor-arg name="参数名字">
    <set>
        <value>1</value>
        <value>2</value>
        <value>3</value>
        ...
    </set>
</constructor-arg>
  • Map
<constructor-arg name="参数名字">
    <map>
        <entry key="键名" value-ref="值"/>
        <entry key="键名" value-ref="值"/>
        <entry key="键名" value-ref="值"/>
        ...
    </map>
</constructor-arg>

map中每一个元素都是一个entry节点,节点属性中key表示键,value表示普通类型的值,value-ref表示对象类型的值

  • Array

  • 如果入参是数组类型,则使用如下方式

<constructor-arg name="参数名字">
    <array>
        <value>1</value>
        <value>2</value>
        <value>3</value>
        ...
    </array>
</constructor-arg>
<constructor-arg name="参数名字">
    <array>
        <ref bean="bean ID"/>
        ...
    </array>
</constructor-arg>

如果是数组是普通类型则使用array中的value节点即可,如果是复杂类型则使用<ref>节点,并且使用bean属性关联beanID

属性注入

  • 有些时候,我们并不需要从构造函数注入,而是从set方法来注入,哪么就可以使用属性注入,属性注入与上不同的在于,构造函数注入需要的是入参的变量名与配置的bean中的constructor-arg中的name要保持一致性,而属性注入则是要求set方法的名字在去掉set后首字母小写后的名字必须与配置中的property节点name属性的值一致
public class Music {
    private String title;
    private Integer length;
    
    ...
    public void setTitle(String title) {
        this.title = title;
    }
    public void setLength(Integer length) {
        this.length = length;
    }
    ...
}
<bean id="music" class="scorpius.soundsystem.Music">
    <property name="title" value="音乐一"/>
    <property name="length" value="360"/>
</bean>
  • 注入对象数组
<bean id="cd" class="scorpius.soundsystem.CD">
    <property name="name" value="磁盘一"/>
    <property name="artist" value="演唱者"/>
    <property name="musics">
        <array value-type="scorpius.soundsystem.Music">
            <ref bean="music"/>
        </array>
    </property>
</bean>
  • p:命名空间

除了上述的用节点注入之外还可以使用p名字空间注入,与c:构造名字空间一样,p:属性名字空间与之有着相同的用法,可相参考使用

  • util:命名空间

util:命名空间相对上面来说要复杂

<util:list id="自定义空间名">
    <ref bean="对象beanId"
</util:list>

<bean   id="cd" 
        class="scorpius.soundsystem.CD" 
        p:name="属性name的注入值" 
        p:artist="属性artist的注入值" 
        p:musics-ref="自定义空间名"/>

总结

  • 依赖构造器

    • 注入方法有两种
      • constructor-arg节点
      • c:命名空间
    • name表示的是入参的变量名
  • 依赖set函数

    • 注入方法有两种
      • property节点
      • p:命名空间
    • name表示的是set函数去掉set前缀后首字母小写的名字
  • 带ref的表示的是对象引用

  • util:命名空间相当于bean的创建与定义

bean节点scope属性

  • scope作用域
    • sinleton 单例[默认]
      • 整个应用程序中,只创建bean的一个实例
    • prototype 原型
      • 每次注入或通过spring上下文获取的时候,都会创建一个新的bean
      • 只有在获取对象时才会创建对象
    • session 会话
      • 在Web应用中,为每个会话创建一个bean实例
    • request 请求
      • 在Web应用中,为每个请求创建一个bean实例
  • @Scope注解与其作用一致

延迟加载

  • lazy-init
    • true 启用延迟加载,也就是说只要要获取时才会创建对象
    • fase
  • @Lazy效果一致

初始化/销毁

  • init-method 等同于 @PostConstruct注解
    • 对象创建时会被调用的方法
  • destroy-method 等同于 @PreDestroy注解
    • 对象删除时会被调用的方法

工厂方法创建对象

package scorpus;

public class Person {
    public Person() {
        System.out.println("Person...");
    }
}
package scorpus;

public class PersonFactory {
    public static Person createFactory(){
        System.out.println("静态工厂方法...");
        return new Person();
    }

    public Person getPersion(){
        System.out.println("实例工厂方法...");
        return new Person();
    }
}
<bean id="persion1" class="scorpus.PersonFactory" factory-method="createFactory"/>
    
<bean id="persionFactory" class="scorpus.PersonFactory"/>
<bean id="persion2" factory-bean="persionFactory" factory-method="getPersion"/>
  • 感谢:千峰机构的免费视频,着实解惑不少
  • 所有记录均在OpenJDK12上运行过,可以放心参考

转载于:https://my.oschina.net/mistylinux/blog/3026554

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值