目录
一、HelloWorld
Spring是一个框架
Spring官网:稳定版是 spring6.0.8
现在很多框架的下载推荐使用maven的方式
Spring是什么?
1、Spring是一个开源框架,是可以看见源代码的,Spring的源代码非常优秀
2、Spring是为简化企业级应用开发而生,比如使用声明式事务非常轻松,以前需要繁琐的配置,复杂的代码才能够实现
3、Spring是一个IOC(DI)和 AOP 容器框架,最核心的两个功能
IOC:反转控制 DI:依赖注入
具体描述Spring
轻量级:Spring是非侵入性的-基于Spring开发的应用中的对象可以不依赖于Spring的API
spring是轻量级的,并不是说jar包有多大,主要是说spring是非侵入性的
我们用spring的时候,不需要实现spring给我们提供的任何接口,不需要去继承它的任何父类,然后我们就可以用spring给我们提供的功能,有点润物细无声的那种感觉
依赖注入(DI---dependency injection、IOC)
面向切面编程(AOP---aspect oriented programming)
容器:Spring是一个容器,因为它包含并且管理应用对象的生命周期
框架:Spring实现了使用简单的组件配置组合成一个复杂的应用,在Spring中可以使用XML和Java注解组合这些对象
一站式:在 IOC 和 AOP 的基础上可以整合各种企业应用的开源框架(整合MyBatis等等)和优秀的第三方类库(实际上 Spring自身也提供了展现层的 SpringMVC 和持久层的 Spring JDBC)
Spring模块
最底层是核心容器
Beans:在核心容器里面可以配置bean
Context:上下文
SpEL:Spring的EL表达式
AOP、Aspect:面向切面编程
声明式事务,整合mybatis
Imstrumentation:整合
Messaging:消息
web模块可以用到Spring提供的springmvc,可以整合其他框架
==============================================
HelloWorld 测试
第一步:新建项目,导入maven依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.nanjing</groupId>
<artifactId>spring-1</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<!-- https://mvnrepository.com/artifact/commons-logging/commons-logging -->
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-beans -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>4.0.0.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.0.0.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-core -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.0.0.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-expression -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
<version>4.0.0.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.mchange/c3p0 -->
<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.5.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
</dependency>
</dependencies>
</project>
第二步:新建HelloWorld.java文件
public class HelloWorld {
private String name;
public void setName(String name) {
System.out.println("setName: " + name);
this.name = name;
}
public void hello(){
System.out.println("hello: "+name);
}
/**
* 在Java中的每个类都至少有一个构造方法,如果在一个类中没有定义构造方法,系统会自动为这个类创建一个默认的构造方法
* 这个默认的构造方法没有参数,在其方法体中没有任何代码,即什么也不做
*/
public HelloWorld() {
System.out.println("HelloWorld's 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">
<!-- 配置bean
class:bean的全类名,通过反射的方式在IOC容器中创建bean,所以要求Bean中必须有无参的构造器
id:标识容器中的bean,id唯一
-->
<bean id="helloWorld" class="com.nanjing.spring.bean.HelloWorld">
<property name="name" value="江苏大剧院"></property>
</bean>
</beans>
第四步:新建Main.java文件
public class Main {
public static void main(String[] args) {
/**
// 创建HelloWorld的一个对象
HelloWorld helloWorld = new HelloWorld();
//为name 属性赋值
helloWorld.setName("nanjing");
*/
//1、创建spring的IOC容器对象
//在创建容器的时候,它会调用构造器对我在配置文件里面配置的那个bean进行初始化,同时会调用set方法对那个属性进行赋值
ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml");
//2、从IOC容器中获取Bean实例
HelloWorld helloWorld=(HelloWorld) ctx.getBean("helloWorld");
//3、调用hello 方法
helloWorld.hello();
}
}
二、IOC&DI概述
IOC(Inversion of Control):其思想是反转资源获取的方向。传统的资源查找方式要求组件向容器发起请求查找资源,作为回应,容器适时的返回资源。
而应用了IOC之后,则是容器主动地将资源推送给它所管理的组件,组件所要做的仅是选择一种合适的方式来接受资源,这种行为也被称为查找的被动形式
DI(Dependency Injection)-- IOC的另一种表述方式:即组件以一些预定义好的方式(例如:setter方法)接受来自如容器的资源注入,相对于IOC而言,这种方式更直接
通俗点讲:
以前买菜,需要到菜市场买,现在只要在院子里放一个小框,菜就会自动的给到你,反转资源获取的方向
实例讲解
传统的方式如右上案例
IOC容器如右下案例:B与A之间建立一种关联关系,容器自动的把关联关系建立好了,通过set方法把A对象的引用赋值给B的成员变量a
IOC的前生
我有一个需求,这个接口是ReportGenerator(报表生成器)会生成两种方式,一种是pdf,另一种是html方式
现在我有一个报表服务类ReportService需要用到这个报表生成器,有可能用到的是pdf方式,有可能html方式
service需要画出三条线,既需要知道这个接口类型,也需要知道你具体有哪些实现类,有可能我还需要知道如何创建实现类的对象,这种是耦合度最高的一种方式
我们需要知道这个接口和实现类的具体细节
原始时代,需要一把斧子,不但需要知道斧子的形状,还需要知道手工地打一把斧子,这个要求是很高的
在封建社会,我需要一把斧子,可以去铁匠铺,给他银子,做一把斧子,这个时候耦合度就降低了,service层只需要画出两条线,一条线是我肯定需要知道接口类型
,同时需要指向这个工厂就行了,这个工厂负责帮我生成这个接口的实现类,代码复杂了,分工更加明确了,项目容易扩展,更加灵活
按需分配,我需要什么东西,政府就会把我需要材料给我,service只需要画出一条线,由容器把我需要的接口的实现类直接注入给我就行了
反转资源的控制方向
三、配置 Bean
1、第一步:
<!-- 配置bean
class:bean的全类名,通过反射的方式在IOC容器中创建bean,所以要求Bean中必须有无参的构造器
id:标识容器中的bean,id唯一
-->
<!-- 全类名应该是用反射的方式由spring帮我们创建这么一个对象 id是标识这个对象的,需要一个无参构造器
name对应的应该是set方法,用setter来定义的javabean这一风格的属性名-->
<bean id="helloWorld" class="com.nanjing.spring.bean.HelloWorld">
<property name="name" value="江苏大剧院"></property>
</bean>
2、第二步:
//1、创建spring的IOC容器对象
//ApplicationContext代表的就是spring里面的IOC容器,这是一个接口
//ClassPathXmlApplicationContext代表的是配置文件在类路径下,是ApplicationContext的一个实现类
//在创建容器的时候,它会调用构造器对我在配置文件里面配置的那个bean进行初始化,同时会调用set方法对那个属性进行赋值
ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml");
3、第三步:
//2、从IOC容器中获取Bean实例
//利用id定位到IOC容器中的bean
HelloWorld helloWorld=(HelloWorld) ctx.getBean("helloWorld");
//利用类型返回IOC容器中的Bean,但要求IOC容器中必须只能有一个该类型的Bean
//HelloWorld helloWorld=(HelloWorld) ctx.getBean("helloWorld");
System.out.println(helloWorld);
4、第四步:
<!-- 配置bean
class:bean的全类名,通过反射的方式在IOC容器中创建bean,所以要求Bean中必须有无参的构造器
id:标识容器中的bean,id唯一
-->
<!-- 全类名应该是用反射的方式由spring帮我们创建这么一个对象 id是标识这个对象的,需要一个无参构造器
name对应的应该是set方法,用setter来定义的javabean这一风格的属性名-->
<bean id="helloWorld" class="com.nanjing.spring.bean.HelloWorld">
<property name="name" value="江苏大剧院"></property>
</bean>
<!--通过构造方法来配置bean的属性-->
<!--如何区分重载的方法-->
<bean id="car" class="com.nanjing.spring.bean.Car">
<constructor-arg value="Audi" index="0"></constructor-arg>
<constructor-arg value="ShangHai" index="1"></constructor-arg>
<constructor-arg value="300000" type="double"></constructor-arg>
</bean>
<!--使用构造器注入属性值可以指定参数的位置和参数的类型!以区分重载的构造器!-->
<bean id="car2" class="com.nanjing.spring.bean.Car">
<constructor-arg value="Baoma" type="java.lang.String"></constructor-arg>
<!--如果字面值包含特殊字符可以使用<![CDATA[]]>包裹起来-->
<!--属性值也可以使用value子节点进行设置-->
<constructor-arg type="java.lang.String">
<value><![CDATA[<Shanghai^>]]></value>
</constructor-arg>
<constructor-arg type="int">
<value>250</value>
</constructor-arg>
</bean>
四、属性配置细节
applicationContext.xml很重要,精华
<!--使用构造器注入属性值可以指定参数的位置和参数的类型!以区分重载的构造器!-->
<bean id="car2" class="com.nanjing.spring.bean.Car">
<constructor-arg value="Baoma" type="java.lang.String"></constructor-arg>
<!--如果字面值包含特殊字符可以使用<![CDATA[]]>包裹起来-->
<!--属性值也可以使用value子节点进行设置-->
<constructor-arg type="java.lang.String">
<value><![CDATA[<Shanghai^>]]></value>
</constructor-arg>
<constructor-arg type="int">
<value>250</value>
</constructor-arg>
</bean>
<bean id="person" class="com.nanjing.spring.bean.Person">
<property name="name" value="Tom"></property>
<property name="age" value="24"></property>
<!--可以使用property的ref属性建立bean之间的引用关系-->
<!-- <property name="car" ref="car2"></property>-->
<!--内部bean,不能被外部引用,只能在内部使用-->
<property name="car">
<bean class="com.nanjing.spring.bean.Car">
<constructor-arg value="Ford"></constructor-arg>
<constructor-arg value="Changan"></constructor-arg>
<constructor-arg value="240" type="int"></constructor-arg>
</bean>
</property>
</bean>
<bean id="person2" class="com.nanjing.spring.bean.Person">
<constructor-arg value="Jerry"></constructor-arg>
<constructor-arg value="25"></constructor-arg>
<!-- <constructor-arg ref="car2"></constructor-arg>-->
<!--测试赋值null-->
<!-- <constructor-arg><null/></constructor-arg>-->
<!--为级联属性赋值,注意:属性需要先初始化后才可以为级联属性赋值,否则会有异常,和struts2不同-->
<constructor-arg ref="car"></constructor-arg>
<property name="car.maxSpeed" value="240"></property>
</bean>
<!--测试如何配置集合属性-->
<bean id="person3" class="com.nanjing.spring.bean.collections.Person">
<property name="name" value="Mike"></property>
<property name="age" value="27"></property>
<property name="cars">
<!--使用list节点为List类型的属性赋值-->
<list>
<ref bean="car"/>
<ref bean="car2"/>
<bean class="com.nanjing.spring.bean.Car">
<constructor-arg value="Ford"></constructor-arg>
<constructor-arg value="Changan"></constructor-arg>
<constructor-arg value="240" type="int"></constructor-arg>
</bean>
</list>
</property>
</bean>
<!--配置Map属性值-->
<bean id="newPerson" class="com.nanjing.spring.bean.collections.NewPerson">
<property name="name" value="Rose"></property>
<property name="age" value="28"></property>
<property name="cars">
<!--使用map节点及map的entry子节点配置Map类型的成员变量-->
<map>
<entry key="AA" value-ref="car"></entry>
<entry key="BB" value-ref="car2"></entry>
</map>
</property>
</bean>
<!--配置Properties属性值-->
<bean id="dataSource" class="com.nanjing.spring.bean.collections.DataSource">
<property name="properties">
<!--使用props和prop子节点来为Propertiess属性赋值-->
<props>
<prop key="user">root</prop>
<prop key="password">123456</prop>
<prop key="jdbcUrl">jdbc:mysql:///test</prop>
<prop key="driverClass">com.mysql.jdbc.Driver</prop>
</props>
</property>
</bean>
<!--配置单例的集合bean,以供多个bean进行引用,需要导入util命名空间-->
<util:list id="cars">
<ref bean="car"/>
<ref bean="car2"/>
</util:list>
<bean id="person4" class="com.nanjing.spring.bean.collections.Person">
<property name="name" value="Jack"></property>
<property name="age" value="28"></property>
<property name="cars" ref="cars"></property>
</bean>
<!--通过p命名空间为bean的属性赋值,需要先导入p命名空间,相对于传统的配置方式更加的简洁-->
<bean id="person5" class="com.nanjing.spring.bean.collections.Person" p:age="30"
p:name="Queen" p:cars-ref="cars">
</bean>
五、自动装配(重点面试会问)
beans-autowire.xml文件
<!-- <bean id="address2" class="com.nanjing.spring.beans.autowire.Address"-->
<!-- p:city="BeiJing" p:street="HuiLongGuan"></bean>-->
<bean id="address2" class="com.nanjing.spring.bean.autowire.Address"
p:city="NanJing" p:street="ZhongShan"></bean>
<bean id="car" class="com.nanjing.spring.bean.autowire.Car"
p:brand="Audi" p:price="300000"></bean>
<!--可以使用autowire属性指定自动装配的方式,
byName 根据bean的名字和当前bean的setter 风格的属性名进行自动装配,若有匹配的,则进行自动装配,若没有匹配的,则不装配
byType 根据bean的类型和当前bean的属性的类型进行自动装配,若IOC容器中有1个以上的类型匹配的bean,则抛异常
-->
<bean id="person" class="com.nanjing.spring.bean.autowire.Person"
p:name="Tom" autowire="byType"></bean>
<!-- <bean id="person" class="com.nanjing.spring.bean.autowire.Person"-->
<!-- p:name="Tom" p:address-ref="address" p:car-ref="car"></bean>-->
六、Bean之间的关系
继承与依赖
beans-relation.xml文件
<!--抽象bean:bean的abstract属性为true的bean,这样的bean不能被IOC容器实例化,只用来被继承配置
若某一个bean的class属性没有指定,则该bean必须是一个抽象bean-->
<bean id="address" class="com.nanjing.spring.bean.autowire.Address"
p:city="BeiJing^" p:street="WuDaoKou" abstract="true"></bean>
<!--bean配置的继承:使用bean的parent属性指定继承哪个bean的配置-->
<bean id="address2" class="com.nanjing.spring.bean.autowire.Address"
p:city="BeiJing" p:street="DaZhongSi" parent="address"></bean>
<bean id="car" class="com.nanjing.spring.bean.autowire.Car"
p:brand="Audi" p:price="300000"></bean>
<!--要求在配置Person时,必须有一个关联的car! 换句话说person这个bean 依赖于Car 这个 bean-->
<bean id="person" class="com.nanjing.spring.bean.autowire.Person"
p:name="Tom" p:address-ref="address2" depends-on="car"></bean>
七、Bean的作用域(面试会问)
beans-scope.xml文件
<!--
使用bean 的scope 属性来配置bean的作用域
singleton:默认值,容器初始化时创建bean实例,在整个容器的生命周期内只创建这一个bean,单例的
prototype:原型的,容器初始化时不创建bean的实例,而在每次请求时都创建一个新的bean实例,并返回
-->
<bean id="car" class="com.nanjing.spring.bean.autowire.Car" scope="prototype">
<property name="brand" value="Audi"></property>
<property name="price" value="300000"></property>
</bean>
Main.java文件----测试
package com.nanjing.spring.bean.scope;
import com.nanjing.spring.bean.autowire.Car;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Main {
public static void main(String[] args) {
ApplicationContext ctx=new ClassPathXmlApplicationContext("beans-scope.xml");
Car car=(Car) ctx.getBean("car");
Car car2=(Car) ctx.getBean("car");
System.out.println(car == car2);
}
}
八、使用外部属性文件
beans-properties.xml文件
<!--导入属性文件-->
<context:property-placeholder location="classpath:db.properties"/>
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<!--使用外部化属性文件的属性-->
<property name="user" value="${user}"></property>
<property name="password" value="${password}"></property>
<property name="driverClass" value="${driverClass}"></property>
<property name="jdbcUrl" value="${jdbcUrl}"></property>
</bean>
db.properties文件
user=root
password=123456
driverClass=com.mysql.jdbc.Driver
jdbcUrl=jdbc:mysql://localhost:3306/test
Main.java文件
public class Main {
public static void main(String[] args) throws SQLException {
ApplicationContext ctx=new ClassPathXmlApplicationContext("beans-properties.xml");
DataSource dataSource=(DataSource) ctx.getBean("dataSource");
System.out.println(dataSource.getConnection());
}
}
九、SpEL
十、管理 Bean 的生命周期
第一步:Car.java文件
public class Car {
public Car() {
System.out.println("Car's Constructor...");
}
private String brand;
public void setBrand(String brand) {
System.out.println("setBrand...");
this.brand = brand;
}
public void init(){
System.out.println("init...");
}
public void destroy(){
System.out.println("destroy...");
}
@Override
public String toString() {
return "Car{" +
"brand='" + brand + '\'' +
'}';
}
}
第二步:beans-cycle.xml文件
<bean id="car" class="com.nanjing.spring.bean.cycle.Car"
init-method="init" destroy-method="destroy">
<property name="brand" value="Audi"></property>
</bean>
第三步:Main.java文件
public class Main {
public static void main(String[] args) {
ClassPathXmlApplicationContext ctx=new ClassPathXmlApplicationContext("beans-cycle.xml");
Car car=(Car) ctx.getBean("car");
System.out.println(car);
//关闭IOC容器
ctx.close();
}
}
第四步:MyBeanPostProcessor.java文件
public class MyBeanPostProcessor implements BeanPostProcessor {
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("postProcessBeforeInitialization: "+bean+", "+beanName);
if("car".equals(beanName)){
//...
}
return bean;
}
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("postProcessAfterInitialization: "+bean+", "+beanName);
Car car=new Car();
car.setBrand("Ford");
return car;
}
}
第五步:beans-cycle.xml文件
<bean id="car" class="com.nanjing.spring.bean.cycle.Car"
init-method="init" destroy-method="destroy">
<property name="brand" value="Audi"></property>
</bean>
<!--
实现BeanPostProcessor 接口,并具体提供
Object postProcessBeforeInitialization(Object bean, String beanName):init-method 之前被调用
Object postProcessAfterInitialization(Object bean, String beanName):init-method 之后被调用
的实现
bean:bean实例本身
beanName: IOC容器配置的bean的名字
返回值:是实际上返回给用户的那个Bean,注意:可以在以上两个方法中修改返回的bean,甚至返回一个新的bean
-->
<!--配置bean的后置处理器,不需要配置id,IOC 容器自动识别是一个BeanPostProcessor-->
<bean class="com.nanjing.spring.bean.cycle.MyBeanPostProcessor"></bean>
十一、通过工厂方法配置 Bean
第一步:InstanceCarFactory.java文件
/**
* 静态工厂方法:直接调用某一个类的静态方法就可以返回Bean的实例
*/
public class StaticCarFactory {
//静态属性
private static Map<String,Car> cars=new HashMap<String,Car>();
static {
cars.put("Audi",new Car("Audi",300000));
cars.put("Ford",new Car("Ford",400000));
}
//静态工厂方法
public static Car getCar(String name){
return cars.get(name);
}
}
第二步:beans-factory.xml文件
<!--通过静态工厂方法来配置bean,注意不是配置静态工厂方法实例,而是配置bean实例-->
<!--class属性:指向静态工厂方法的全类名
factory-method:指向静态工厂方法的名字
constructor-arg:如果工厂方法需要传入参数,则使用constructor-arg来配置参数
-->
<bean id="car1"
class="com.nanjing.spring.bean.factory.StaticCarFactory" factory-method="getCar">
<constructor-arg value="Audi"></constructor-arg>
</bean>
第三步:测试类 Main.java文件
ApplicationContext ctx=new ClassPathXmlApplicationContext("beans-factory.xml");
Car car1=(Car) ctx.getBean("car1");
System.out.println(car1);
Car car2=(Car) ctx.getBean("car2");
System.out.println(car2);
第四步:InstanceCarFactory.java文件
/**
* 实例工厂方法:实例工厂的方法,即现需要创建工厂本身,再调用工厂的实例方法来返回bean的实例
*/
public class InstanceCarFactory {
private Map<String,Car> cars=null;
public InstanceCarFactory() {
cars=new HashMap<String, Car>();
cars.put("Audi",new Car("Audi",300000));
cars.put("Ford",new Car("Ford",400000));
}
public Car getCar(String brand){
return cars.get(brand);
}
}
第五步:
<!--配置工厂的实例-->
<bean id="carFactory" class="com.nanjing.spring.bean.factory.InstanceCarFactory"></bean>
<!--通过实例工厂方法来配置bean-->
<!--
factory-bean 属性:指向实例工厂方法的bean
factory-method: 指向实例工厂方法的名字
constructor-arg:如果工厂方法需要传入参数,则使用constructor-arg来配置参数
-->
<bean id="car2" factory-bean="carFactory" factory-method="getCar">
<constructor-arg value="Ford"></constructor-arg>
</bean>
十二、通过 FactoryBean 配置 Bean
第一步:CarFactoryBean.java 文件
//自定义的FactoryBean 需要实现FactoryBean 接口
public class CarFactoryBean implements FactoryBean<Car> {
private String brand;
public void setBrand(String brand) {
this.brand = brand;
}
//返回bean的对象
public Car getObject() throws Exception {
return new Car(brand,500000);
}
/**
* 返回的bean的类型
* @return
*/
public Class<?> getObjectType() {
return Car.class;
}
public boolean isSingleton() {
return true;
}
}
第二步:beans-factory.xml文件
<!--
通过FactoryBean 来配置Bean的实例
class:指向FactoryBean 的全类名
property:配置FactoryBean的属性
但实际返回的实例却是FactoryBean 的getObject()方法返回的实例!
-->
<bean id="car" class="com.nanjing.spring.bean.factorybean.CarFactoryBean">
<property name="brand" value="BMW"></property>
</bean>
十三、通过注解配置 Bean(1)
第一步:TestObject.java 文件
@Component
public class TestObject {
}
第二步:UserController.java文件
@Controller
public class UserController {
public void execute(){
System.out.println("UserController execute...");
}
}
第三步:UserService.java文件
@Service
public class UserService {
public void add(){
System.out.println("UserService add...");
}
}
第四步:UserRepository.java文件
public interface UserRepository {
void save();
}
第五步:UserRepositoryImpl.java文件
@Repository("userRepository")
public class UserRepositoryImpl implements UserRepository{
public void save() {
System.out.println("UserRepository Save...");
}
}
第六步:beans-annotation.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">
<!--指定Spring IOC容器扫描的包-->
<!--可以通过resource-pattern 指定扫描的资源-->
<!--
<context:component-scan
base-package="com.nanjing.spring.bean.annotation"
resource-pattern="repository/*.class"></context:component-scan> -->
<!-- context:exclude-filter 子节点指定排除哪些指定表达式的组件-->
<!-- context:include-filter 子节点指定包含哪些表达式的组件,该子节点需要 use-default-filters 配合使用-->
<context:component-scan
base-package="com.nanjing.spring.bean.annotation">
<!--
<context:exclude-filter type="annotation"
expression="org.springframework.stereotype.Repository"/>
-->
<!--
<context:include-filter type="annotation"
expression="org.springframework.stereotype.Repository"/>
-->
<!--
<context:exclude-filter type="assignable"
expression="com.nanjing.spring.beans.annotation.repository.UserRepository"/>
-->
<!-- <context:include-filter type="assignable"-->
<!-- expression="com.nanjing.spring.beans.annotation.repository.UserRepository"/>-->
</context:component-scan>
</beans>
第七步:Main.java文件
public class Main {
public static void main(String[] args) {
ApplicationContext ctx=new ClassPathXmlApplicationContext("beans-annotation.xml");
TestObject to=(TestObject) ctx.getBean("testObject");
System.out.println(to);
UserController userController=(UserController) ctx.getBean("userController");
System.out.println(userController);
userController.execute();
UserService userService=(UserService) ctx.getBean("userService");
System.out.println(userService);
UserRepository userRepository=(UserRepository) ctx.getBean("userRepository");
System.out.println(userRepository);
}
}
十四、通过注解配置 Bean(2)
@Autowired
private UserService userService;
如果IOC容器里面有好几个类型相匹配的Bean,怎么办?
第一种使用 @Qualifier
@Autowired
@Qualifier("userRepositoryImpl")
private UserRepository userRepository;
第二种
@Repository("userRepository")
public class UserRepositoryImpl implements UserRepository{
十五、泛型依赖注入
泛型依赖注入(UML图)
两个基类BaseService带泛型的,BaseRpository带泛型的
BaseService和BaseRpository之间有一种引用关系,以便可以调用BaseRpository已经定义好的方法
我在BaserService里面有一个成员变量,是BaseRpository这种类型的,
BaseService可能会有很多实现类,BaseRpository可能会有很多实现类
UserService,在继承BaseService的时候,我需要提供这个泛型T,比如这个泛型T是User
UserService和UserRpository之间会自动的建立引用关系,这就是所谓的泛型依赖注入
=====================================
第一步:BaseService.java文件
public class BaseService<T> {
@Autowired
protected BaseRepository<T> repository;
public void add(){
System.out.println("add...");
System.out.println(repository);
}
}
第二步:BaseRepository.java文件
public class BaseRepository<T> {
}
第三步:UserService.java文件
@Service
public class UserService extends BaseService<User>{
}
第四步:UserRepository.java文件
@Repository
public class UserRepository extends BaseRepository<User>{
}
第五步:beans-generic-di.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="com.nanjing.spring.bean.generic.di"></context:component-scan>
</beans>
第六步:Main.java文件
public class Main {
public static void main(String[] args) {
ApplicationContext ctx=new ClassPathXmlApplicationContext("beans-generic-di.xml");
UserService userService=(UserService) ctx.getBean("userService");
userService.add();
}
}
输出结果: