五篇教你掌握spring之三:详解Spring的bean以及注解开发

本文阅读 6 分钟
首页 代码,Java 正文

各种复杂类型的依赖注入

我们采用一个类的大杂烩的形式,新建一个Student

package com.lwh.pojo;

import java.util.*;

public class Student { 
    private String name;
    private Address address;
    private String[] books;
    private List<String> hobbys;
    private Map<String,String> card;
    private Set<String> games;
    private String wife;
    private Properties info;
    //省略tostring,和get,set方法
}

新建一个beans,其中的接受到在注释中写的很清楚,就不再做文字说明

<?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-4.1.xsd">

    <!-- bean这个标签就代表实例化了一个对象,id代表实例化的名字,class代表实例化类的路径 property标签代表设置参数,要求实例化的对象里必须有set方法,否则报错, 其中有俩个属性 ref代表传入的对象(写已经注册的bean的id) value代表传入的值,例如说对象中有一个属性是String类型的,就直接传入值即可 -->
    <bean id="address" class="com.lwh.pojo.Address"/>
    <bean id="student" class="com.lwh.pojo.Student">
        <!--第一种,普通值注入-->
        <property name="name" value="芜湖"/>

        <!--第二种,引用类型注入-->
        <property name="address" ref="address"/>

        <!--第三种,数组类型注入,array就是数组的意思-->
        <property name="books">
            <array>
                <value>水浒</value>
                <value>三国</value>
                <value>红楼</value>
            </array>
        </property>

        <!--第四种,list类型注入,相当于很多个普通值,就用value标签-->
        <property name="hobbys">
            <list>
                <value>看书</value>
                <value>打豆豆</value>
            </list>
        </property>

        <!--第五种,List注入,map中装的是键值对,第一个是键key,值是第二个-->
        <property name="card">
            <map>
                <entry key="学号" value="20190105865"/>
                <entry key="学籍号" value="213254654651"/>
            </map>
        </property>

        <!--第六种,set注入-->
        <property name="games">
            <set>
                <value>LOL</value>
                <value>dota</value>
            </set>
        </property>

        <!--第七种,空值注入-->
        <property name="wife">
            <null/>
        </property>

        <!--第八种,Properties值注入,类似于数据库连接的Properties-->
        <property name="info">
            <props>
                <prop key="driver">com.mysql.jdbc</prop>
                <prop key="username">root</prop>
                <prop key="password">123456</prop>
            </props>
        </property>
    </bean>

</beans>

拓展之P空间和C空间注入

新建一个User类

package com.lwh.pojo;

public class User { 
    private String name;
    private int age;

    public User() { 
    }

    public User(String name, int age) { 
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() { 
        return "User{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    public String getName() { 
        return name;
    }

    public void setName(String name) { 
        this.name = name;
    }

    public int getAge() { 
        return age;
    }

    public void setAge(int age) { 
        this.age = age;
    }
}

增加beans.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:p="http://www.springframework.org/schema/p" xmlns:c="http://www.springframework.org/schema/c" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd">

    <!--p命名空间注入,需要在beans中引入p,就相当于property-->
    <bean id="user" class="com.lwh.pojo.User" p:name="芜湖" p:age="19"/>

    <!--c空间注入,相当于通过构造器注入:construct-args-->
    <bean id="user2" class="com.lwh.pojo.User" c:name="芜湖" p:age="19"/>
</beans>

Bean的作用域

  • singleton(单例模式) 这是spring的默认机制,无论到哪个dao里创建user,拿到的都是用一个user,也就是一旦创建就只有一个 <bean id="user" class="com.lwh.pojo.User" p:name="芜湖" p:age="19" scope="singleton"/>
  • prototype(原型模式) 每一次去getBean的时候都创建一个新的对象 <bean id="user" class="com.lwh.pojo.User" p:name="芜湖" p:age="19" scope="prototype"/>
  • request
  • session
  • application
  • webscoket

Bean的装配

三种装配方式

  • 在XML中显示配置
  • 在java中显示配置
  • 隐式的自动装配bean

测试环境,pojo中有PC,People,Phone,资源文件是beans.xml

PC:

package com.lwh.pojo;

public class PC { 
    public void test(){ 
        System.out.println("我的个人电脑!");
    }
}

People:

package com.lwh.pojo;

public class People { 
    private String own;

    public String getOwn() { 
        return own;
    }

    public void setOwn(String own) { 
        this.own = own;
    }

    private Phone phone;
    private PC pc;

    public Phone getPhone() { 
        return phone;
    }

    public void setPhone(Phone phone) { 
        this.phone = phone;
    }

    public PC getPc() { 
        return pc;
    }

    public void setPc(PC pc) { 
        this.pc = pc;
    }
}

Phone:

package com.lwh.pojo;

public class Phone { 
    public void test(){ 
        System.out.println("我的手机!");
    }
}

beans.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-4.1.xsd">
    <bean id="pc" class="com.lwh.pojo.PC"/>
    <bean id="phone" class="com.lwh.pojo.Phone"/>

    <bean id="people" class="com.lwh.pojo.People" autowire="byName">
        <property name="own" value="芜湖"/>
    </bean>
</beans>

test:

import com.lwh.pojo.People;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Mytest { 
    public static void main(String[] args) { 
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        People people = context.getBean("people", People.class);
        people.getPc().test();
        people.getPhone().test();
    }
}

隐式自动装配:

byName就是寻找上下文中,people的set方法后面紧跟着的对象名,例如setPc,那么就会去寻找上下文中是否有叫pc的对象(也就是beanid叫pc的对象),有就自动装配,没有就报空指针异常,如果我讲第一个bean的id改为“pc123454”,那么就会出错

byType就是寻找上下文中,people中与对象类型相同的bean,与id无关,例如,我将第一个bean的id删除,也可以成功,将id改为“pc213234”也能装配成功,但是上下文中不能同时存在要自动装配的对象类型相同的bean,例如如果使用byType自动装配,就不能出现两个pc对象(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" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd">
    <bean class="com.lwh.pojo.PC"/>
    <bean id="phone" class="com.lwh.pojo.Phone"/>

    <bean id="people" class="com.lwh.pojo.People" autowire="byType">
        <property name="own" value="芜湖"/>
    </bean>
</beans>

注解自动装配

需要加入其它约束,结构如下:

<?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-4.1.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd">

    <context:annotation-config/>
</beans>
  • @Autowired 直接在属性上使用,也可以在set方法上使用,如果使用注解自动装配,我们可以不编写Set方法,前提是你这个自动装配的属性在IOC容器中要存在,切符合名字byname(也就是和使用byname装配的前提一致)
package com.lwh.pojo;

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

public class People { 
   private String own;
   @Autowired
   private Phone phone;
   @Autowired
   private PC pc;

   public String getOwn() { 
       return own;
   }

   public void setOwn(String own) { 
       this.own = own;
   }

   
   public Phone getPhone() { 
       return phone;
   }


   public PC getPc() { 
       return pc;
   }

}
@Autowired(value=false)//代表可以将属性设置为null

那么如果我想创建多个相同类型的bean,但是还想要people自动装配怎么办?

  • @Qualifier 这个注解可以指定id装配 @Autowired
    @Qualifier(value = "pc1234")

private PC pc; 然后在beans中有 <bean id="pc1234" class="com.lwh.pojo.PC"/>
<bean id="pc123" class="com.lwh.pojo.PC"/>

  • @Resource
    - 都可以与Autowired一样用于属性字段上自动装配 - @Autowired通过byType的方法实现 - @Resource默认通过byname的方式实现,如果找不到就使用byType如果两个都找不到就报错

使用注解开发

bean的注解注入

@Component注解

  • beans.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-4.1.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd">

    <!--代表去扫描com.lwh.pojo下的类-->
    <context:component-scan base-package="com.lwh.pojo"/>
    <context:annotation-config/>

</beans>
  • 类中加入注解
package com.lwh.pojo;

import org.springframework.stereotype.Component;

//这个注解就相当于<bean id="user" class="com.lwh.pojo.User/>
@Component
public class User { 
    public String name="芜湖";
}

属性的注解注入

@Value(可以用在属性或者set方法上)

package com.lwh.pojo;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

//这个注解就相当于<bean id="user" class="com.lwh.pojo.User/>
@Component
public class User { 
    @Value("芜湖")//设置属性值
    public String name;
}

衍生注解

@Component有几个衍生注解,会按照mvc三层架构分层

  • dao【@Repository】
  • service【@Service】
  • controller【@Controller】

其实本质都是一样的,都是代表某个类去注册到Spring中,装配Bean

自动装配置

  • @Autowired
  • @Qualifier
  • @Resource

作用域

package com.lwh.pojo;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

//这个注解就相当于<bean id="user" class="com.lwh.pojo.User/>
@Component
@Scope("prototype")//原型模式,从bean容器中取一次就new一个新的对象
public class User { 
    @Value("芜湖")//设置属性值
    public String name;
}

JavaConfig注解开发

采用纯java代码的形式配置spring,不再使用xml形式,新建一个子项目,代码结构如下:

img

config.java:

加入@Configuration注解,代表这是一个java代码的config注册类,再注册一个bean,采用@Bean注解,

package com.lwh.config;

import com.lwh.pojo.User;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan("com.lwh.pojo")//就相当于扫描实体类
public class Config { 

    //以下语句就相当于<bean id="getUser" class="com.lwh.pojo.User"/>
    //bean的id就是方法名,大小写区分
    @Bean
    public User getUser(){ 
        return new User();
    }
}

User.java

采用@Component自动准备bean,然后再往set方法上注入name值为“芜湖”

package com.lwh.pojo;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component
public class User{ 
    private String name;

    @Override
    public String toString() { 
        return "User{" +
                "name='" + name + '\'' +
                '}';
    }

    public String getName() { 
        return name;
    }

    @Value("芜湖")
    public void setName(String name) { 
        this.name = name;
    }
}

Test.java

import com.lwh.config.Config;
import com.lwh.pojo.User;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class Test { 
    public static void main(String[] args) { 
        //注意!这里使用AnnotationConfigApplicationContext
        ApplicationContext context = new AnnotationConfigApplicationContext(Config.class);
        User user = context.getBean("getUser", User.class);
        System.out.println(user.getName() );
    }
}
本文为互联网自动采集或经作者授权后发布,本文观点不代表立场,若侵权下架请联系我们删帖处理!文章出自:https://blog.csdn.net/m0_46435741/article/details/119277341
-- 展开阅读全文 --
Redis底层数据结构--跳跃表
« 上一篇 04-28
BUUCTF Web [强网杯 2019]随便注
下一篇 » 06-24

发表评论

成为第一个评论的人

热门文章

标签TAG

最近回复