Spring是一个开源框架,它由[Rod Johnson](https://baike.baidu.com/item/Rod Johnson)创建。它是为了解决企业应用开发的复杂性而创建的。Spring使用基本的JavaBean来完成以前只可能由EJB完成的事情。然而,Spring的用途不仅限于服务器端的开发。从简单性、可测试性和松耦合的角度而言,任何Java应用都可以从Spring中受益。
◆目的:解决企业应用开发的复杂性
◆功能:使用基本的JavaBean代替EJB,并提供了更多的企业应用功能
◆范围:任何Java应用
Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架。
Spring 框架是一个分层架构,由 7 个定义良好的模块组成。Spring 模块构建在核心容器之上,核心容器定义了创建、配置和管理 bean 的方式.
每个模块的功能如下:
BeanFactory
,它是工厂模式的实现。BeanFactory
使用控制反转 (IOC) 模式将应用程序的配置和依赖性规范与实际的应用程序代码分开。创建maven项目
添加maven依赖
在自己创建的maven项目pom.xml文件中添加依赖:
<dependencies>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-contextartifactId>
<version>5.1.5.RELEASEversion>
dependency>
dependencies>
**Ioc—Inversion of Control,即“控制反转”,不是什么技术,而是一种设计思想。**在Java开发中,**Ioc意味着将你设计好的对象交给容器控制,而不是传统的在你的对象内部直接控制。**如何理解好Ioc呢?理解好Ioc的关键是要明确“谁控制谁,控制什么,为何是反转(有反转就应该有正转了),哪些方面反转了”,请看下面分析:
●谁控制谁,控制什么:传统Java SE程序设计,我们直接在对象内部通过new进行创建对象,是程序主动去创建依赖对象;而IoC是有专门一个容器来创建这些对象,即由Ioc容器来控制对 象的创建;谁控制谁?当然是IoC 容器控制了对象;控制什么?那就是主要控制了外部资源获取(也包括文件等)。
●反转?,哪些方面反转了?:有反转就有正转,传统应用程序是由我们自己在对象中主动控制去直接获取依赖对象,也就是正转;而反转则是由容器来帮忙创建及注入依赖对象;为何是反转?因为由容器帮我们查找及注入依赖对象,对象只是被动的接受依赖对象,所以是反转;哪些方面反转了?依赖对象的获取被反转了。
IOC 少不了IOC容器,也就是实例化抽象的地方。
ClassPathXmlApplicationContext
在class路径下加载 classpath:***.xml(类路径加载)
是spring读取xml最常用的类。而我们一般操作的是她的接口ApplicationContext。
使用方法:
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
Student ss = ctx.getBean(Student.class);
System.out.println(ss);
AnnotationConfigApplicationContext
用于基于注解的配置
FileSystemXmlApplicationContext
文件系统路径加载
XmlWebApplicationContext
专门为web应用准备的,从相对于Web根目录的路径中装载配置文件完成初始化
1.路径前缀
//1.前缀classpath:表示的是项目的classpath下相对路径
ApplicationContext appCt = new ClassPathXmlApplicationContext("classpath:student.spring.xml");
//2.没有前缀:默认为项目的classpath下相对路径
ApplicationContext appCt = new ClassPathXmlApplicationContext("student.spring.xml");
2.路径中的通配符
//使用通配符加载所有符合要求的文件
ApplicationContext appCt = new ClassPathXmlApplicationContext("*.spring.xml");
优点:xml配置方式对代码没有任何侵入性,更改配置无需重新编译
缺点:配置相对于注解多、工程量大
<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
https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="student" class="com.lanou3g.spring.Student">
bean>
beans>
注:id属性代表该bean在Spring容器中的唯一标识
class属性指定该bean的类型,需要指定类的全名
<beans>
<import resource="student_beans.xml"/>
<import resource="resources/auto_inject.xml"/>
<import resource="/resources/Source.xml"/>
<bean id="stu1" class="com.lanou3g.spring.studentDaoImpl1"/>
<bean id="stu2" class="com.lanou3g.spring.studentDaoImpl2"/>
beans>
优点:在Java类中已经包含很多上下文信息,所有在Java类上直接加注解可以省略很多属性,配置简单。
缺点:对代码有侵入性,如果改了是基于注解的配置信息,就需要重新编译、打包
第一种:在xml配置文件中通过context命名空间中的annotation-config标签或component-scan标签开启注解配置
<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
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">
<context:annotation-config/>
<context:component-scan base-package="com.lanou3g.spring" />
beans>
第二种:通过注解的方式开启注解配置支持
@Configuration //用`@Configuration`注解标注的类就相当于一个xml配置文件
@ComponentScan("com.lanou3g.spring")
public class App {
@Bean
public StudentDao studentDao() {
return new StudentDao();
}
public static void main(String[] args) {
// 如果在非web工程中使用这种方式开启注解支持,需要使用下面的方式初始化ioc容器,否则@ComponentScan注解会被忽略
ConfigurableApplicationContext ctx = new AnnotationConfigApplicationContext(App.class);
}
}
根据依赖的类型自动注入。该注解可以用于标注在 属性、setter方法、构造方法、或带参数的普通方法之上。Spring会将符合的参数自动注入到属性、或方法参数中。
注:如果注入的属性是一个单值类型,但Spring上下文中有多个匹配类型的候选Bean,那将会直接报错,因为Spring不知道该用哪个注入
根据依赖bean的名称自动注入。除了可以通过Spring特有的@Autowired注解进行依赖注入外,Spring也支持原生JSR-250中的 @Resource注解。
public class SimpleMovieLister {
private MovieFinder movieFinder;
@Resource(name="myMovieFinder")
public void setMovieFinder(MovieFinder movieFinder) {
this.movieFinder = movieFinder;
}
}
@Resource注解的name属性不是必须的,如果不指定,那默认的名称将取决于变量名称、setter方法的名称(取决于注解在变量上还是setter方法上)
@Resource注解还有个好处,如果按名称无法找到一个匹配bean的时候,它会自动按照类型查找注入。
用于标注在setter方法之上,表示此属性必须要注入。如果容器初始化该bean时没有合适的值注入到该属性则直接抛出异常。
在spring5.1之后弃用,因为必须要注入的属性,我们可以通过构造参数来注入。
当我们通过@Autowired注解来注入属性或者参数时,如果遇到上面说的单值属性有多个匹配类型候选bean,如果其中一个候选Bean上配置了@Primary注解或者在xml配置中设置了primary=“true”,那将不会报错,Spring会优先将带primary标记的候选bean注入(当然,如果有多个带primary标记的匹配类型还是会报错滴)。
该注解可以让我们通过名称在多个候选bean中进一步限定。
public class Student {
@Autowired
@Qualifier("main")
private People peo;
}
通过@Qualifier限定构造参数注入
public class Student {
private People peo;
private PeopleDao peoDao;
@Autowired
public void prepare(@Qualifier("main") MovieCatalog movieCatalog,
CustomerPreferenceDao customerPreferenceDao) {
this.movieCatalog = movieCatalog;
this.customerPreferenceDao = customerPreferenceDao;
}
}
给bean添加qualifier标识符
在xml中我们可以通过子标签来给一个bean添加标识符, 以供注入时@Qualifier使用。如果不显示指定标识符,spring会用id、name代替。
<bean class="example.SimpleMovieCatalog">
<qualifier value="main"/>
bean>
如果bean是通过注解的方式配置的,我们可以这样做
@Component
@Qualifier("Action") // 给bean添加qualifier标识符
public class studentimpl implements Student {
}
@Component注解是一个通用注解,代表一个组件,可以用来标识所有希望让Spring管理的bean。
@Bean
注解允许我们通过注解的方式定义在Java代码中定义bean的配置元数据,相当于xml配置文件中的
@Configuration注解的类相当于xml配置文件中的
@Scope注解可以限定通过注解配置的bean的作用域。适用于通过@Component(或其派生注解)、@Bean注解配置的bean。@Scope注解的默认值是singleton(单例)
@Configuration
public class MyConf{
@Bean
@Scope("prototype")
public Encryptor encryptor() {
}
}
@Qualifier注解可以限定通过注解配置的bean的qualifier标识符。适用于通过@Component
(或其派生注解)、@Bean注解配置的bean。 相当于xml配置的的子标签
通过注解的方式导入其他注解配置
示例:
@Import({MyConf.class})//导入MyConf类配置,MyConf类用@Configuration注解
@Configuration
public class Application {
@Bean
public StudentService studentService() {
return new StudentServiceImpl();
}
}
@Configuration
public class MyConf {
@Bean
public StudentDao studentDao() {
return new StudentDaoImpl();
}
}
通过注解的方式引入xml配置
示例:
@Configuration
@ImportResource("classpath:/com/acme/properties-config.xml")
public class AppConfig {
@Value("${jdbc.url}")
private String url;
@Value("${jdbc.username}")
private String username;
@Value("${jdbc.password}")
private String password;
@Bean
public DataSource dataSource() {
return new DriverManagerDataSource(url, username, password);
}
}
xml配置文件
<beans>
<context:property-placeholder location="classpath:jdbc.properties"/>
beans>
jdbc.properties文件
jdbc.url=jdbc:hsqldb:hsql://localhost/xdb
jdbc.username=sa
jdbc.password=sa
main方法调用:
public static void main(String[] args) {
ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
TransferService transferService = ctx.getBean(TransferService.class);
}
此注解用于加载properties文件到环境中,然后我们就可以通过env获取properties文件中定义的属性
使用示例:
@Configuration
@PropertySource("classpath:app.properties")
public class AppConfig {
@Autowired
Environment env;
@Bean
public TestBean testBean() {
TestBean testBean = new TestBean();
testBean.setName(env.getProperty("testbean.name"));
return testBean;
}
}
@Inject 注解作用和Spring的@Autowired注解效果一致
@Name注解有两个作用。 当用作方法的参数时和Spring的@Qualifier注解效果类似;而用作类上面的注解时作用和Spring的@Component注解类似
xml配置方式和注解方式各有优缺点,两者相互混合使用,更方便管理
Spring提供注解的方式虽说简单但并不是为了要完全取代xml配置方式 ,两者各有适用场景,比如数据源的配置, 就不适合通过注解来配置。否则数据源配置一发生变化就得改代码。
混合实例:
1.在xml中配置数据源
jdbc.properties
jdbc.url=jdbc:mysql://localhost:3306/test?charsetEncoding=utf8
jdbc.driver=com.mysql.jdbc.Driver
jdbc.user=root
jdbc.password=root
<beans>
<context:component-scan base-package="com.lanou3g.spring"/>
<context:property-placeholder location="classpath:jdbc.properties"/>
<beanv id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="url" value="${jdbc.url}"/>
<property name="url" value="${jdbc.driver}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
bean>
beans>
2.通过注解配置bean和依赖注入
@Configuration //相当于用注解配置了一个xml配置文件(相当于xml中的)
public class App {
@Autowired// 按照类型来自动注入属性
private DataSource dataSource;
@Bean
public AccountRepository accountRepository() {
return new JdbcAccountRepository(dataSource);
}
@Bean
public TransferService transferService() {
return new TransferService(accountRepository());
}
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:system-test-config.xml");
TransferService transferService = ctx.getBean(TransferService.class);
}
}
1.xml中导入其他xml配置
<beans>
<import resource="student_beans.xml"/>
<import resource="resources/auto_inject.xml"/>
<import resource="/resources/Source.xml"/>
<bean id="stu1" class="com.lanou3g.spring.studentDaoImpl1"/>
<bean id="stu2" class="com.lanou3g.spring.studentDaoImpl2"/>
beans>
2.注解方式导入
在这可新建一个类用于演示,用@Configuration注解此类
@Configuration
public class MyConf {
@Bean("sb")//相当于
// @Bean//
public People smallPeople(){
return new studentImpl2();
}
}
@Configuration
@Import(MyConf.class)
@ImportResource("applicationContext.xml")//导入xml配置
/*@ComponentScan(basePackages = "com.lanou3g.spring")*/
/*@Component("app")*/
public class App
{
AnnotationConfigApplicationContext ctx=new AnnotationConfigApplicationContext(App.class);
ctx.registerShutdownHook();
People people=ctx.getBean("sb",People.class);
System.out.println(people);
}
注解导入xml配置
也就是用@Configuration注解的类导入xml配置
@Configuration
@ImportResource("classpath:/com/lanou3g.spring/properties-config.xml")//导入xml配置
public class AppConfig {
@Value("${jdbc.url}")
private String url;
@Value("${jdbc.username}")
private String username;
@Value("${jdbc.password}")
private String password;
@Bean
public DataSource dataSource() {
return new DriverManagerDataSource(url, username, password);
}
}
1.singleton
<bean id="messageDao" class="com.lanou3g.spring.dao.MessageDaoImpl2" scope="singleton" />
2.prototype
<bean id="messageDao" class="com.lanou3g.spring.dao.MessageDaoImpl2" scope="prototype" />
通过init-method、destroy-method指定bean的生命周期方法
init-method:bean的初始化,指定初始化回调方法,在实例化 bean 时,立即调用该方法
destroy-method:bean的销毁,销毁回调方法,只有从容器中移除 bean 之后,才能调用该方法。
我们希望在bean被初始化的时候,就初始化某些资源。为了达到这样的目的,我们可以给类添加初始化方法;又希望在bean被销毁的时候,就释放或关闭某些资源。为了达到这样的目的,我们可以给类添加指定的销毁方法。
public class MessageDaoImpl{
public void myInit() {
System.out.println("MessageDaoImpl init");
}
public void myDestroy() {
System.out.println("MessageDaoImpl destroy");
}
}
xml配置
<bean id="md" class="com.lanou3g.spring.dao.MessageDaoImpl"
init-method="myInit" destroy-method="myDestroy"
/>
测试类调用
/**
* 练习IOC容器中bean的生命周期
*/
public void testLifeCycle(ApplicationContext ctx) {
MessageDaoImpl messageDao = ctx.getBean("md", MessageDaoImpl.class);
System.out.println(messageDao);
}
这种实例化的方式可能在我们平时的开发中用到的是最多的,因为在xml文件中配置简单并且也不需要额外的工厂类来实现。
xml配置
<bean id="student" class="cn.mytest.service.impl.Student">bean>
id是对象的名称,class是要实例化的类,然后再通过正常的方式进调用实例化的类即可
Java代码
public void App(){
//加载spring配置文件
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
//调用getBean方法取得被实例化的对象。
Student lazyStudent = ctx.getBean(Student.class);
System.out.println("名称:" + lazyStudent.getSname());
System.out.println("爱称:" + lazyStudent.getNickName());
lazyStudent.getFruit().eatFruit();
}
注:采用这种实例化方式要注意的是:要实例化的类中如果有构造器的话,一定要有一个无参的构造器。
想通过这种方式进行实例化就要具备两个条件:1、要有工厂类及其工厂方法;2、工厂方法是静态的。首先创建工程类及其静态方法:
package com.lanou3g.spring.bean;
import com.lanou3g.spring.simple.Apple;
import com.lanou3g.spring.simple.Banana;
import com.lanou3g.spring.simple.Fruit;
/**
* 水果工厂
* 练习静态工厂方法创建bean
*/
public class FruitFactory {
/**
* 静态工厂方法
* @param name
* @return
*/
public static Fruit produceFruit(String name) {
switch (name) {
case "apple":
return new Apple();
case "banana":
return new Banana();
default:
return null;
}
}
}
xml配置文件创建静态工厂bean
<bean id="big_apple" class="com.lanou3g.spring.bean.FruitFactory" factory-method="produceFruit">
<constructor-arg name="name" value="banana" />
bean>
id是实例化的对象的名称,class是工厂类,也就实现实例化类的静态方法所属的类,factory-method是实现实例化类的静态方法。然后按照正常的调用方法去调用即可:
public void App(){
//加载spring配置文件
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
//调用getBean方法取得被实例化的对象。
//通过静态工厂方法来初始化bean
Object obj = ctx.getBean("big_apple");
System.out.println(obj);
}
使用该实例化方式工厂方法不需要是静态的,但是在spring的配置文件中需要配置更多的内容,,首先创建工厂类及工厂方法:
package com.lanou3g.spring.bean;
import com.lanou3g.spring.simple.Apple;
import com.lanou3g.spring.simple.Banana;
import com.lanou3g.spring.simple.Fruit;
public class FruitFactory {
/**
* (非静态)普通工厂方法
* @param name
* @return
*/
public Fruit produceFruitByInstrance(String name) {
switch (name) {
case "apple":
return new Apple();
case "banana":
return new Banana();
default:
return null;
}
}
}
然后再去配置spring配置文件
<bean id="fruitFactory" class="com.lanou3g.spring.bean.FruitFactory" />
<bean id="big_banana" factory-bean="fruitFactory" factory-method="produceFruitByInstrance">
<constructor-arg name="name" value="banana" />
bean>
这里需要配置两个bean,第一个bean使用的构造器方法实例化工厂类,第二个bean中的id是实例化对象的名称,factory-bean对应的被实例化的工厂类的对象名称,也就是第一个bean的id,factory-method是非静态工厂方法。
对一个bean命名除了使用id属性命名外,还有name属性命名。
name属性和id属性的区别:
id用来标识bean,是唯一的,且只有一个,不能用特殊字符:×#@等 ,不能用数字开头;name可以给一个bean指定多个名称,并可能与其他的bean重名,name 可以用特殊字符,并且一个bean可以用多个名称:如name=“stuImpl_1,stuImpl_2,stuImpl_3”,用逗号隔开。通过id和name都可以取出该Bean.
实例:
在 applicationContext.xml中配置name属性
<bean id="people" name="stuImpl_1,stuImpl_2,stuImpl_3" class="com.lanou3g.spring.impl.studentImpl2"/>
在java类里面获取applicationContext.xml中配置的name属性stuImpl_1,stuImpl_2,stuImpl_3
studentImpl2 stu= ctx.getBean("stuImpl_1",studentImpl2.class);
System.out.println(stu.queryStudent());
AnnotationConfigApplicationContext ctx=new AnnotationConfigApplicationContext(App.class);
ctx.registerShutdownHook();
什么是懒加载?
用lazy-init。告诉spring容器是否以懒加载的方式创造对象。用的时候才加载构造,不用的时候不加载;
取值:true(懒,真正调用到的时候再加载)、false(非懒,已启动spring容器就创建对象)、default(懒)
怎么用?
在这我先建一个测试类LazyLiuCheng
package com.lanou3g.spring.bean;
public class LazyLiuCheng {
public void init(){
System.out.println("liucheng init");
}
}
在xml配置文件中LazyLiuCheng的bean,b并设置lazy-init的值为true,即懒加载(调用时加载)
<bean id="lazyBean" class="com.lanou3g.spring.bean.LazyLiuCheng" init-method="init" lazy-init="true"/>
在java 类main方法中调用加载
LazyLiuCheng lazy=ctx.getBean( LazyLiuCheng.class);
System.out.println(lazy);
//运行结果:liucheng init
// com.lanou3g.spring.bean.LazyLiuCheng@3571b748
若java类中未调用加载
不会显示上述运行结果
若xml配置文件中lazy-init未设置或为false,即非懒加载,不过是否调用加载,容器启动的时候立刻创建对象。
什么是DI(依赖注入)?
依赖注入(Dependency Injection)是Spring框架的核心之一。
所谓依赖注入,是指程序运行过程中,如果需要调用另一个对象协助时,无须在代码中创建被调用者,而是依赖于外部的注入。Spring的依赖注入对调用者和被调用者几乎没有任何要求,完全支持对POJO之间依赖关系的管理。
常用依赖注入有以下几个方向:
构造方法注入、setter注入、自动装配、方法注入
有参注入
实体类Student
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class student {
private String sname;
private String gender;
public student(String sname, String gender) {
this.sname = sname;
this.gender=gender;
}
xml配置
<bean id="stu" class="com.lanou3g.spring.Student"> <constructor-arg name="sname" value="哈哈" />
<constructor-arg name="age" value="22" />
bean>
无参注入
<bean id="stu" class="com.lanou3g.spring.Student" />
主要通过在xml配置文件中创建bean时加上标签,通过标签配置注入一个匿名内部bean。
具体实现如下:
<bean id="stu1" class="com.lanou3g.spring.bean.Student">
<property name="fruit">
<bean class="com.lanou3g.spring.simple.Apple" />
property>
bean>
Student stu = ctx.getBean("stu1", Student.class);
stu.getFruit().eatFruit();
//运行结果:eating Banana
我们在java中常用的集合有List、Set、Map和Properties,
Spring为集合提供了对应的标签:
注入 list元素
注入 set元素
注入 map元素
注入 properties 元素
在xml配置文件中注入集合类型参数
<bean id="myCollection" class="com.lanou3g.spring.bean.InjectionSet" >
<property name="hobbies">
<list>
<value>玩游戏value>
<value>看书value>
<value>写代码value>
list>
property>
<property name="sex">
<set>
<value>男value>
<value>女value>
<value>不男不女value>
set>
property>
<property name="gameTitles">
<map>
<entry key="LOL" value="嘴强王者">entry>
<entry key="王者农药" value="甩锅大神">entry>
<entry key="和平精英">
<null />
entry>
map>
property>
<property name="nickName">
<props>
<prop key="张三">33prop>
<prop key="李四">44prop>
props>
property>
bean>
在App.java类中测试
InjectionSet set = ctx.getBean(InjectionSet.class);
// 获取注入的list属性
List<Object> hobbies = set.getHobbies();
for(Object hobby : hobbies) {
System.out.println("类型:" + hobby.getClass()+", 值:" + hobby);
}
// 获取注入的map属性
System.out.println(set.getGameTitles());
// 获取注入的set属性
System.out.println(set.getSex());
// 获取注入的Properties属性
System.out.println(set.getNickName());
//运行结果
类型:class java.lang.String, 值:玩游戏
类型:class java.lang.String, 值:看书
类型:class java.lang.String, 值:写代码
{LOL=嘴强王者, 王者农药=甩锅大神, 和平精英=null}
[男, 女, 不男不女]
{张三=33, 李四=44}
<bean class="com.lanou3g.spring.bean.Null">
<property name="name" value=""/>
bean>
<bean class="com.lanou3g.spring.bean.Null">
<property name="name">
<null/>
property>
bean>
通过下面的方式来配置
<bean id="stu" class="com.lanou3g.spring.bean.student">
<!-- 注入复合属性 -->
<property name="fred.bob.age" value="22"/>
</bean>
注入外部properties配置文件,先要有一个properties配置文件
jdbc.url=jdbc:mysql://localhost:3306/lanou?charsetEncoding=utf8
jdbc.driver=com.mysql.jdbc.Driver
jdbc.user=root
jdbc.password=root
然后在xml配置文件中引入外部的properties文件,在此有两种方式
<<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="classpath:jdbc.properties" />
bean>
<context:property-placeholder location="classpath:jdbc.properties"/>
<bean id="jdbcConf" class="com.lanou3g.spring.bean.JDBCConf">
<property name="url" value="${jdbc.url}" />
<property name="driver" value="${jdbc.driver}" />
<property name="userName" value="${jdbc.user}" />
<property name="password" value="${jdbc.password}" />
bean>
新建一个JDBCConf类用于测试
package com.lanou3g.spring.bean;
import lombok.Getter;
import lombok.Setter;
/**
* 各参数都从配置中注入
*/
@Setter
@Getter
public class JDBCConf {
private String url;
private String driver;
private String userName;
private String password;
}
最终main方法调用测试结果
JDBCConf jdbcConf = ctx.getBean(JDBCConf.class);
System.out.println(jdbcConf.getUrl());
System.out.println(jdbcConf.getDriver());
System.out.println(jdbcConf.getUserName());
System.out.println(jdbcConf.getPassword());
//运行结果:url:jdbc:mysql://localhost:3306/test?charsetEncoding=utf8
// driver:com.mysql.jdbc.Driver
// username:root
// password:root
通过p和c命名空间注入属性和构造参数
xml文件配置
//通过c命名空间来注入 通过set
<bean id="liu" class="com.lanou3g.spring.bean.test" c:name="阿成" />
//通过p命名空间来注入 通过构造方法
<bean id="liu1" class="com.lanou3g.spring.bean.test" p:name="阿成1" />
测试类运行代码
test stu = ctx.getBean("liu", test.class);
System.out.println("c注入,name: " + stu.getName());
test stu1 = ctx.getBean("liu1", test.class);
System.out.println("p注入, name: " +stu1.getName());
//运行结果c注入,name: 刘成
//p注入, name: 刘成1
还有不要忘了在xml文件中配置摘要,若不配置p和c命名空间注入不能用
xmlns:c="http://www.springframework.org/schema/c"
xmlns:p="http://www.springframework.org/schema/p"
先创建一个类
package com.lanou3g.spring.bean;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class AutoInjectByNameTeacher {
private String tname;
private student student;
}
再在spring配置xml文件中创建bean配置属性装配
<bean id="teacherByName" class="com.lanou3g.spring.bean.AutoInjectByNameTeacher"
autowire="byName">
<property name="tname" value="John" />
bean>
创建一个AutoInjectByTypeTeacher类
package com.lanou3g.spring.bean;
import lombok.Getter;
import lombok.Setter;
@Setter
@Getter
public class AutoInjectByTypeTeacher {
private String tname;
private LazyLiuCheng lazyLiuCheng;
}
在xml配置文件配置类型装配
<bean id="teacherByType" class="com.lanou3g.spring.bean.AutoInjectByTypeTeacher"
autowire="byType">
<property name="tname" value="John" />
bean>
创建一个AutoInjectByConstructorTeacher类
package com.lanou3g.spring.bean;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class AutoInjectByConstructorTeacher {
public AutoInjectByConstructorTeacher(){}
/* public AutoInjectByConstructorTeacher(LazyLiuCheng lazyLiuCheng){
System.out.println("构造参数传入:"+lazyLiuCheng);
}*/
private String tname;
private LazyLiuCheng lazyLiuCheng;
}
在xml配置文件配置类型装配
<bean id="teacherByConstructor" class="com.lanou3g.spring.bean.AutoInjectByConstructorTeacher"
autowire="constructor">
<property name="tname" value="John" />
bean>
public void testAutoInject(ApplicationContext ctx) {
// 按照名称自动注入属性
AutoInjectByNameTeacher teacher = ctx.getBean("teacherByName" , AutoInjectByNameTeacher.class);
System.out.println("教师名称: " + teacher.getTname());
System.out.println("所教学生:" + teacher.getStudent().getSname());
// 按照类型自动注入属性(容器中符合此类型的bean只能有一个,否则报错)
AutoInjectByTypeTeacher teacherByType = ctx.getBean("teacherByType" , AutoInjectByTypeTeacher.class);
System.out.println("教师名称(类型): " + teacherByType.getTname());
teacherByType.getLazyStudent().destroy();
// 下面这行示范了按照类型自动注入,但符合类型不唯一的情况(会直接报错)
// 解决方案就是换成按照名称自动注入
//System.out.println("学生姓名:" + teacherByType.getStudent().getSname());
// 构造器参数自动注入(按照类型)(容器中符合此类型的bean只能有一个,否则报错)
AutoInjectByConstructorTeacher teacherByConstructor = ctx.getBean("teacherByConstructor" , AutoInjectByConstructorTeacher.class);
System.out.println("教师名称(构造参数): " + teacherByConstructor.getTname());
teacherByConstructor.getLazyStudent().destroy();
}