0


spring注入的几种方式(文件配置以及注解方式)

前言

spring利用IOC(控制反转)机制,将创建对象的权利交给了spring框架,从而降低程序的耦合。spring有文件配置和注解两种策略来实现Bean对象的创建和注入,这两种方式可以相互代替,后面将对应记录两种方式的使用。

一、文件配置的方式

1.在根目录创建配置文件

命名为

config.xml

,配置spring必要内容:

<beansxmlns="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"></beans>

2.通过构造方法注入

通过调用bean所属类的带参构造器为bean的属性注入值。这也就意味着,如果需要使用构造器注入,就得为类提供包含参数的构造方法。

  • id:注入的bean实例变量名
  • class:指定全限定类名
  • scope:指定作用范围,"prototype"多例,"singleton"单例(默认)
  • name:指定构造函数参数名
  • index:指定构造函数参数索引
  • type:通过参数类型指定参数
  • value:指定参数值(基本类型,String类型)
  • ref:指定参数值(Bean类型,在配置文件中配置过的bean)
<!--
使用<constructor-arg>标签指定构造函数的参数以及设定的参数值
基本类型和String类型使用value赋值,引用Bean类型使用ref
同时,参数除了使用name,也可以使用index、type来指定
--><beanid="car"class="XMLBean.Car"><constructor-argname="price"value="10000"></constructor-arg><constructor-argname="speed"value="80"></constructor-arg></bean><beanid="user"class="XMLBean.User"><constructor-argname="age"value="50"></constructor-arg><constructor-argname="car"ref="car"></constructor-arg><constructor-argname="name"value="周润发"></constructor-arg></bean>

3.通过set方法注入

如果需要使用set注入,那么必须要为属性提供set方法,Spring容器就是通过调用bean的set方法为属性注入值的。而在xml文件中,使用set注入的方式就是通过property标签,如下所示:

<beanid="car"class="XMLBean.Car"><propertyname="price"value="10000"></property><propertyname="speed"value="80"></property></bean><beanid="user"class="XMLBean.User"><propertyname="age"value="50"></property><propertyname="car"ref="car"></property><propertyname="name"value="周润发"></property></bean>

使用set注入一些复杂的数据类型/集合:

<!--注入集合数据/复杂数据类型:
    用于List结构集合的标签:
        List,set,array
    用于Map结构集合的标签:
        map,pro
    结构相同,标签可以互换
--><beanid="accountDao3"class="AccountDaoImpl3"><propertyname="strings"><array><value>AAA</value><value>BBB</value></array></property><propertyname="myList"><list><value>AAA</value><value>BBB</value></list></property><propertyname="myMap"><map><entrykey="AAA"value="aaa"></entry><entrykey="BBB"><value>bbb</value></entry></map></property><propertyname="myProperty"><props><propkey="AAA">aaa</prop><propkey="BBB">bbb</prop></props></property></bean>

3.使用静态工厂注入

静态工厂注入就是编写一个静态的工厂方法,这个工厂方法会返回我们需要的产品类,然后在配置文件中,指定使用这个工厂方法创建bean。首先需要一个静态工厂,如下所示:

publicclassStaticFactory{//生产一个汽车类publicstaticCargetCar(){returnnewCar(123,54321);}}

下面需要在xml中配置car这个bean,并指定它由工厂方法进行创建:

  • id:指定产品bean的变量名
  • class:指定工厂的全限定类名
  • factory-method指定工厂类生产产品的方法
<beanid="mycar"class="XMLBean.StaticFactory"factory-method="getCar"></bean><beanid="user"class="XMLBean.User"><propertyname="age"value="50"></property><propertyname="car"ref="mycar"></property><propertyname="name"value="周润发"></property></bean>

4.使用实例工厂注入

实例工厂与静态工厂类似,不同的是,静态工厂调用工厂方法不需要先创建工厂类的对象,因为静态方法可以直接通过类调用,所以在上面的配置文件中,并没有声明工厂类的bean。但是,实例工厂,需要有一个实例对象,才能调用它的工厂方法。先看看实例工厂的定义:

publicclassInstanceFactory{/**
     * 实例工厂方法,返回一个Car的实例对象
     */publicCargetCar(){returnnewCar(100,70000);}}

首先将实例化工厂Bean注入IOC容器中,之后注入产品bean,并指明工厂类和生产方法:

<beanid="instanceFactory"class="XMLBean.InstanceFactory"></bean><!--将实例化工厂bean注入--><!--注入产品bean,并指明工厂bean和生产方法--><beanid="mycar"factory-bean="instanceFactory"factory-method="getCar"></bean><beanid="user"class="XMLBean.User"><propertyname="age"value="50"></property><propertyname="car"ref="mycar"></property><propertyname="name"value="周润发"></property></bean>

测试实例

publicclassXmlBeanTest{@Testpublicvoidtest1(){ApplicationContext context =newClassPathXmlApplicationContext("config.xml");// 获取user这个beanUser user = context.getBean("user",User.class);// 输出产看结果System.out.println(user);}}

二、使用注解的方式

使用注解的好处:找到类就找到了bean注入的位置,不需要使用文件I/O,在大型系统中能够加快运行速度。
配置

bean.xml

文件:

<beansxmlns=http://www.springframework.org/schema/beansxmlns: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"><!--可以隐式地自动向Spring容器注册4个BeanPostProcessor,
    这样就可以使用@ Resource 、@ PostConstruct、@ PreDestroy、@PersistenceContext、
    @Autowired、@Required等注解了实现自动注入--><context:annotation-config/><!--扫描的包的位置--><context:component-scanbase-package="包名"></context:component-scan></beans>

注解分为3类:

1.用于创建对象的注解

和xml配置中编写一个

<bean>

标签实现功能一样

  • @Component(value=) 作用:将当前类对象存入spring容器中 属性:value:用于指定bean的id;不写时,默认为类名首字母小写
  • @Controller:一般用于表现层@Service:一般用于业务层@Repository:一般用于持久层 以上三个注解的作用和属性与Component是一模一样的。spring提供了三层注解,使对象更佳清晰。

将User类注入IOC容器中:

@Component(value ="user")//将User类放入IOC容器中publicclassUser{privateString name;privateint age;privateCar car;publicUser(){}publicUser(String name,int age,Car car){this.name = name;this.age = age;this.car = car;}publicStringgetName(){return name;}publicvoidsetName(String name){this.name = name;}publicintgetAge(){return age;}publicvoidsetAge(int age){this.age = age;}publicCargetCar(){return car;}publicvoidsetCar(Car car){this.car = car;}@OverridepublicStringtoString(){return"User{"+"name='"+ name +'\''+", age="+ age +", car="+ car +'}';}}

测试结果
可以看到@Component已经将User类注入,但是没有注入参数值。

publicclassAnnotationBeanTest{@Testpublicvoidtest2(){ApplicationContext context =newClassPathXmlApplicationContext("bean.xml");// 获取user这个beanUser user = context.getBean("user",User.class);// 输出产看结果System.out.println(user);}}

结果:
User{name='null', age=0, car=null}

2.用于注入数据的注解

和xml配置中

<bean>

标签下写一个

<property>

作用一样

@Autowired

作用: 按照类型自动注入,只要有唯一一个bean对象类型和注入类型匹配,就可以注入成功。ps: 如果ico容器中没有任何bean对象的类型和要注入的变量类型匹配,则报错;如果有多个类型匹配时,会先匹配相同类型名称,再匹配id——

@Repository(“id”)

出现位置: 可以是变量上,也可以是方法上
细节: 在使用注释注入时,可以没有set方法

@Component("car")//放入spring容器中publicclassCar{// 只包含基本数据类型的属性privateint speed;privatedouble price;publicCar(){}publicCar(int speed,double price){this.speed = speed;this.price = price;}publicintgetSpeed(){return speed;}publicvoidsetSpeed(int speed){this.speed = speed;}publicdoublegetPrice(){return price;}publicvoidsetPrice(double price){this.price = price;}@OverridepublicStringtoString(){return"Car{"+"speed="+ speed +", price="+ price +'}';}}
@Component(value ="user")//放入spring容器中publicclassUser{privateString name;privateint age;@Autowired//根据类型,自动找到IOC中的Car类型Bean注入privateCar car;publicUser(){}publicUser(String name,int age,Car car){this.name = name;this.age = age;this.car = car;}publicStringgetName(){return name;}publicvoidsetName(String name){this.name = name;}publicintgetAge(){return age;}publicvoidsetAge(int age){this.age = age;}publicCargetCar(){return car;}publicvoidsetCar(Car car){this.car = car;}@OverridepublicStringtoString(){return"User{"+"name='"+ name +'\''+", age="+ age +", car="+ car +'}';}}

测试:
可以发现car不在是null,而是已经有一个初始值。这说明@Autowired已经将IOC容器中的car注入给了私有变量car。

publicclassAnnotationBeanTest{@Testpublicvoidtest2(){ApplicationContext context =newClassPathXmlApplicationContext("bean.xml");// 获取user这个beanUser user = context.getBean("user",User.class);// 输出产看结果System.out.println(user);}}

结果:
User{name='null', age=0, car=Car{speed=0, price=0.0}}

小结
1.在成员变量上注入

@Autowired//会找到spring容器中匹配的bean赋值给carprivateCar car;

2.在构造函数上注入

@Autowired//有多个参数时,注解写参数前面publicUser(@Value("李连杰")String name,@Value("56")int age,@AutowiredCar car){//"李连杰"会注入给name//"56"会注入给age//查找合适bean注入给carthis.name = name;this.age = age;this.car = car;}

3.set注入

@Autowired//调用set函数,将适当的bean注入给this.carpublicvoidsetCar(Car car){this.car = car;}

@Qualifier

作用: 在按照类型注入的基础上再按照名称注入。他在给类成员注入时不能单独使用,但是在给方法参数注入时可以。

@Autowired@Qualifier("car")//给类成员变量注入时和@Autowired一起用privateCar car;

属性: value,用于指定bean的id

@Resourse

作用:直接参照bean的id注入,可以独立使用
属性: name:用于指定bean的id

@Resource(name ="car")privateCar car;

:以上

@Autowired

@Qualifier

@Resourse

三个注入只能注入其他bean类型的数据,而基本类型和String类型无法使用这些注解,另外,集合类型的注入只能用过xml的方式来实现

@value

作用:用于注入基本类型和String类型的数据
属性:value:用于指定数据的值,可以使用spring中的spEL(spring的el表达式)
spEL的写法:$(表达式)

在User类中注入String和int类型的值:

//在成员变量中注入@Value("成龙")privateString name;@Value("60")privateint age;
//set注入@Value("成龙")publicvoidsetName(String name){this.name = name;}@Value("60")publicvoidsetAge(int age){this.age = age;}

3.用于改变作用范围

<bean>

标签中适用scope属性实现功能一样

@Scope

作用:用于指定bean的范围
属性:value:常取值:singleton(单例,默认) 、prototype(多例)

4.和生命周期相关

@PreDestroy

作用:用于指定销毁方法

@PostConstruct

作用:用于指定初始化方法

5.使用配置注解代替xml配置文件

**

@Configuration

**
作用:指定当前类是一个配置类
细节:当名为Configuration类作为AnnotationConfigApplicationContext()参数时可以不添加@Configuration,否则必须要添加。

**

@ComponentScan

**
作用:通过此注解指定spring创建容器时要扫描的包
属性:value:它和basePackages的作用是一样的

**

@bean

**
作用:把当前方法的返回值作为bean对象存入spring的ioc容器中
属性:用于指定bean的id,不写时默认值是当前方法的名称
细节:当用注解配置方法时,如果方法有参数,spring框架会去容器中查找有没有可用的bean对象,查找的方式和@Autowired注解的作用是一样的

publicclassSpringConfiguration{@Bean("car")//表示将函数返回的对象放入spring容器中publicCarcreateCar(@Value("66")int speed,@Value("88888")double price){//通过注解注入参数returnnewCar(speed,price);}@Bean("user")//表示将函数返回的对象放入spring容器中publicUsercreateUser(@Value("陈浩南")String name,@Value("33")int age,@Qualifier(value ="car")Car car){returnnewUser(name,age,car);}}

注:有了配置类,之前Car和User类前的@Component注解可以删除了。相当于已经通过配置类将响应的Bean放入了spring容器中。

测试

publicclassAnnotationBeanTest{@Testpublicvoidtest2(){ApplicationContext context =newAnnotationConfigApplicationContext(SpringConfiguration.class);// 获取user这个beanUser user = context.getBean("user",User.class);// 输出产看结果System.out.println(user);}}

结果:
User{name='陈浩南', age=33, car=Car{speed=66, price=88888.0}}

**

@PropertySource

**
作用:用于指定properties文件的位置
属性:value:指定文件名的路径和名称;关键字:classpath表示在类路径下

//jdbc.properties文件:
jdbc.driver=com.mysql.jdbc.Driver 
jdbc.url=jdbc:mysql://localhost:3306/students
jdbc.username=root
jdbc.password=1234
@ComponentScan("com")@PropertySource("classpath:jdbcConfigeration.properties")publicclassSpringConfiguration{@Value("${jdbc.driver}")privateString driver;@Value("${jdbc.url}")privateString url;@Value("${user}")privateString uer;@Value("${password}")privateString password;@Bean//将一个DataSource对象放入ioc容器publicDataSourcecreateDatasource(){try{ComboPooledDataSource ds =newComboPooledDataSource();
            ds.setDriverClass(driver);
            ds.setJdbcUrl(url);
            ds.setUser(uer);
            ds.setPassword(password);System.out.println(driver+url+uer+password);return  ds;}catch(Exception e){thrownewRuntimeException(e);}}}

**

@Import

**
作用:用于导入其他配置类,在引入其他配置类时,可以不用再写@Configuration 注解(不省略也可)。当使用@Import注解之后,有@Import注解的就是父配置类,而导入的是子配置类
属性:value[config.Class…] 用于指定配置类的字节码

@Configuration@ComponentScan(basePackages ="com")@Import({JdbcConfig.class})//导入子配置类publicclassSpringConfiguration{//...}@Configuration@PropertySource("classpath:jdbc.properties")publicclassJdbcConfig{//...}

类对象配置总结:

  1. 创建一个config类,用@Configuration来注解
  2. 使用@ComponentScan(“包名”)来规定spring容器的扫描的包
  3. 使用@PropertySource("classpath: ")引入.properties配置文件(选用)
  4. 创建spring容器,以config.Class作为参数
  5. 用容器.getBean()获取bean类对象(提前用@bean或者三个创建对象的注解将对象放入IOC容器)
  6. 用@Value(“$()”)将.properties中的键值对成员变量进行注入
标签: spring java 后端

本文转载自: https://blog.csdn.net/ha_lee/article/details/125888583
版权归原作者 ha_lee 所有, 如有侵权,请联系我们删除。

“spring注入的几种方式(文件配置以及注解方式)”的评论:

还没有评论