官网:https://spring.io
官方下载地址:repo.spring.io
GitHub:https://github.com/spring-projects
Maven包:
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-webmvcartifactId>
<version>5.3.5version>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-jdbcartifactId>
<version>5.3.5version>
dependency>
一句话概括:Spring是一个轻量级的控制反转(IOC)和面向切面(AOP)的容器(框架)
Spring框架是一个分层架构,由7个定义良好的模块组成。
Spring模块构建在核心容器之上,核心容器定义了创建、配置和管理bean的方式。
组成Spring框架的每个模块(或组件)都可以单独存在,或者与其他一个或多个模块联合实现。每个模块的功能如下:
**核心容器:**核心容器提供Spring框架的基本功能。核心容器的主要组件是BeanFactory
,它是工厂模式的实现。BeanFactory
使用控制反转(IOC)模式将应用程序的配置和依赖性规范与世纪的应用程序代码分开。
**Spring上下文:**Spring上下文是一个配置文件,向Spring框架提供上下文信息。Spring上下文包括企业服务,例如JNDI、EJB、电子邮件、国际化、校验和调度功能。
**Spring AOP:**通过配置管理特性,Spring AOP模块直接将面向切面的编程功能,继承到了Spring框架中。所以,很容易地使Spring框架管理任何支持AOP的对象。Spring AOP模块为基于Spring的应用程序中的对象提供了事务管理服务。通过使用Spring AOP,不用依赖组件,就可以将声明性事务管理集成到应用程序中。
**Spring DAO:**JDBC DAO抽象层提供了有意义的异常层次结构,可用该结构来管理异常处理和不同数据库供应商抛出的错误信息。异常层次结构简化了错误处理,并且极大地降低了需要编写的异常代码数量(例如打开和关闭连接)。Spring DAO的面向JDBC的异常遵从通用的DAO异常层次结构。
**Spring ORM:**Spring框架插入了若干个ORM框架,从而提供了ORM的对象关系工具,其中包括JDO、HIbernate和iBatis SQL Map。所有这些都遵从Spring的通用事务和DAO异常层次结构。
**Spring Web模块:**Web上下文模块建立在应用程序上下文模块之上,为基于Web的应用程序提供了上下文。所以,Spring框架支持与Jakarta Struts的集成。Web模块还简化了处理多部分请求以及将请求参数绑定到域对象的工作。
**Spring MVC框架:**MVC框架是一个全功能的构建Web应用程序的MVC实现。通过策略接口,MVC框架变成为高度可配置的,MVC容纳了大量视图技术,其中包括JSP、Velocity、Tiles、iText和POI。
Spring Boot:
Spring Cloud:
Spring弊端:发展了太久之后,违背了原来的理念!配置十分的繁琐,人称:“配置地狱!”
新建一个空白的maven项目
1.原来的MVC方式写一段代码
(1)UserDao接口(dao层)
public interface UserDao {
public void getUser();
}
(2)UserDaoImpl实现类
public class UserDaoImpl implements UserDao{
@Override
public void getUser() {
System.out.println("获取用户数据");
}
}
(3)UserService接口(service层)
public interface UserService {
public void getUser();
}
(4)UserServiceImpl实现类
public class UserServiceImpl implements UserService {
//在service层关联dao层对象
private UserDao userDao=new UserDaoOracleImpl();
@Override
public void getUser() {
userDao.getUser();
}
}
(5)测试(控制层)
public class MyTest {
@Test
public void getUser(){
UserService userService = new UserServiceImpl();
userService.getUser();
}
}
2.dao层增加接口,产生问题
(1)增加一个UserDao的实现类UserDaoMysqlImpl:
public class UserDaoMysqlImpl implements UserDao{
@Override
public void getUser() {
System.out.println("Mysql获取数据");
}
}
紧接着我们想要使用MySql的话,我们就需要去service实现类中修改对应的实现
public class UserServiceImpl implements UserService {
//在service层关联dao层对象,修改new对象
private UserDao userDao=new UserDaoOracleImpl();
@Override
public void getUser() {
userDao.getUser();
}
}
(2)再假设,我们再增加一个UserDao的实现类UserDaoOracleImpl
public class UserDaoOracleImpl implements UserDao{
@Override
public void getUser() {
System.out.println("Oracle获取数据");
}
}
要想使用Oracle,也需要在service实现类中修改对应的new对象实现
public class UserDaoOracleImpl implements UserService {
//在service层关联dao层对象,修改new对象
private UserDao userDao=new UserDaoOracleImpl();
@Override
public void getUser() {
userDao.getUser();
}
}
问题:
如果我们有大量的类似的需求,dao层一个接口有许多实现类,用户访问就需要修改程序(service层引用的dao层实现类)
每次变动都需要修改大量的代码,这种设计的耦合性太高了,牵一发而动全身
3.问题解决【重点】
我们可以在service层中用到dao层的地方不去实现它,而是留一个接口,利用set。我们去代码里修改下:
public class UserServiceImpl implements UserService {
//在service层关联dao层对象
private UserDao userDao;
//【革命性变化】在service层中利用到的dao层接口实现类经常变化,所以不去实现它,而是预留一个接口
public void setUserDao(UserDao userDao){
this.userDao=userDao;
}
@Override
public void getUser() {
userDao.getUser();
}
}
测试:
@Test
public void getUser(){
UserServiceImpl userService = new UserServiceImpl();
//Mysql实现
userService.setUserDao(new UserDaoMysqlImpl());
userService.getUser();
//Oracle实现
userService.setUserDao(new UserDaoOracleImpl());
userService.getUser();
}
**区别:**已经发生了根本性的变化
这种思想,从本质上解决了问题,我们程序员不再去管理对象的创建了
系统的耦合性大大降低,可以更加专注的在业务上,这也就是IOC的原型!
IOC是Spring框架的核心内容,使用多种方式完美的实现了IOC,可以使用XML配置,也可以实用注解,新版本的Spring也可以零配置实现IOC;
采用XML方式配置Bean的时候,Bean的定义信息是和实现分离的;
而采用注解的方式可以把两者合为一体,Bean的定义信息直接以注解的形式定义在实现类中,从而达到零配置的目的。
控制反转是一种通过描述(XML或者注解),并通过第三方去生产或获取特定对象的方式。
在Spring中实现控制反转的是IOC容器,其实现方法时依赖注入(Dependency Injectiion,DI)
注 : spring 需要导入commons-logging进行日志记录 . 我们利用maven , 他会自动下载对应的依赖项 。
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-webmvcartifactId>
<version>5.3.5version>
dependency>
1.编写一个Hello实体类
package com.kuang.pojo;
public class Hello {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void show(){
System.out.println("Hello,"+name);
}
}
2.编写我们的spring文件,这里我们命名为beans.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="hello" class="com.kuang.pojo.Hello">
<property name="name" value="Spring"/>
bean>
beans>
3.测试
public void test(){
//解析beans.xml文件,生成管理相应的Bean对象
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
//getBean:参数即为Spring配置文件中bean的id
Hello hello = (Hello) context.getBean("hello");
hello.show();
}
Hello对象时谁创建的?
hello对象是由Spring创建的
Hello对象的属性是怎么设置的?
hello对象的属性是由Spring容器设置的,这个过程就叫控制反转
控制:谁来控制对象的创建,传统应用程序是由程序本身控制创建的,使用Spring后,对象是由Spring来控制创建的
反转:程序本身不创建对象,而变成被动的接收对象。
依赖注入:就是利用set方法来进行注入的。
IOC是一种编程思想,由主动地编程变成被动的接收
可以通过new ClassPathXmlApplicationContext去浏览一下底层源码。
我们在案例一中,邢增一个Spring配置文件beans.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="MysqlImpl" class="com.kuang.dao.UserDaoMysqlImpl">
bean>
<bean id="OracleImpl" class="com.kuang.dao.UserDaoOracleImpl">
bean>
<bean id="ServiceImpl" class="com.kuang.service.UserServiceImpl">
<property name="userDao" ref="MysqlImpl"/>
bean>
beans>
重新测试:
@Test
public void getUser() {
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
UserServiceImpl serviceImpl = (UserServiceImpl) context.getBean("ServiceImpl");
serviceImpl.getUser();
}
最开始dao层一个接口有多个实现类,service层引用接口并具体实现了其中一个实现类,用户(test)要想变更访问不同的dao层实现类,就需要去修改service层对dao层实现类的引用,从而需要修改了程序,主动权在程序手上,当此种需求较大时,程序修改起来很繁琐。
public class UserDaoOracleImpl implements UserService {
//在service层关联dao层对象,修改new对象
private UserDao userDao=new UserDaoOracleImpl();
@Override
public void getUser() {
userDao.getUser();
}
}
第一次修改:我们将service层对dao层实现类的引用,不去具体实现它,而是将接口变成属性,预留属性set接口。用户(test)想要使用哪个dao层实现类,只需要在test层调用serviceImpl时传入对应的dao层实现类对象,主动权在用户手上。
public class UserServiceImpl implements UserService {
//在service层关联dao层对象
private UserDao userDao;
//【革命性变化】在service层中利用到的dao层接口实现类经常变化,所以不去实现它,而是预留一个接口
public void setUserDao(UserDao userDao){
this.userDao=userDao;
}
@Override
public void getUser() {
userDao.getUser();
}
}
@Test
public void getUser(){
UserServiceImpl userService = new UserServiceImpl();
//Mysql实现
userService.setUserDao(new UserDaoMysqlImpl());
userService.getUser();
//Oracle实现
userService.setUserDao(new UserDaoOracleImpl());
userService.getUser();
}
使用Spring:
new ClassPathXmlApplicationContext("beans.xml");
获得Spring创建和管理的所有对象
<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="MysqlImpl" class="com.kuang.dao.UserDaoMysqlImpl">
bean>
<bean id="OracleImpl" class="com.kuang.dao.UserDaoOracleImpl">
bean>
<bean id="ServiceImpl" class="com.kuang.service.UserServiceImpl">
<property name="userDao" ref="MysqlImpl"/>
bean>
beans>
test无需修改,只需修改上面beans.xml配置文件
@Test
public void getUser() {
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
UserServiceImpl serviceImpl = (UserServiceImpl) context.getBean("ServiceImpl");
serviceImpl.getUser();
}
1.实体类User
public class User {
private String name;
public User(){
System.out.println("user无参构造方法");
}
public void setName(String name){
this.name=name;
}
public void show(){
System.out.println("name="+name);
}
}
2.Spring配置文件beans.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="user" class="com.kuang.pojo.User">
<property name="name" value="kuangshen"/>
bean>
beans>
3.断点测试
测试结果:
当测试类通过ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
将配置文件beans.xml加载到Spring中执行时,获得Spring的上下文环境。
此时已经初始化了所有管理的对象,User对象已经通过无参构造初始化了。
该操作中Spring就已经创建和管理了所有在beans.xml中注册配置的对象。
对象属性的配置,还是通过属性对应的set方法进行的。
删除User中setName
方法后,beans.xml配置类的参数会报错。
1.实体类User
public class User {
private String name;
//有参构造方法
public User(String name){
this.name=name;
System.out.println("user有参构造方法");
}
public void setName(String name){
this.name=name;
}
public void show(){
System.out.println("name="+name);
}
}
2.beans.xml的三种方式编写
初始化实体类User了,因为那只有是无参构造方法时才能创建
配置属性根据参数名字设置【常用】,后两种不常用
<bean id="user" class="com.kuang.pojo.User">
<constructor-arg name="name" value="kuangshen"/>
bean>
<bean id="userT" class="com.kuang.pojo.UserT">
<constructor-arg index="0" value="kuangshen2"/>
bean>
<bean id="userT" class="com.kuang.pojo.UserT">
<constructor-arg type="java.lang.String" value="kuangshen2"/>
bean>
3.测试
同样也是Spring的context一旦获得,即配置文件加载的时候,所有的实体类都初始化了
无论是通过无参构造,此时依靠set方法注入
还是通过有参构造,此时通过有参构造直接注入
可以某些属性通过有参构造,某些属性通过set注入
<bean id="user" class="com.kuang.pojo.User">
<constructor-arg name="name" value="kuangshen"/>
<property name="age" value="12"/>
bean>
alias 为bean设置别名,可以设置多个别名
<bean id="user" class="com.kuang.pojo.User">
<property name="name" value="kuangshen"/>
bean>
<alias name="user" alias="usernew"/>
<bean id="user" class="com.kuang.pojo.User" name="u1,u2 u3;u4">
<property name="name" value="kuangshen"/>
bean>
applicationContext.xml
如:beans1.xml、beans2.xml、beans3.xml ==> applicationContext.xml
applicationContext.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">
<import resource="beans1.xml"/>
<import resource="beans2.xml"/>
<import resource="beans3.xml"/>
beans>
测试:
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
无参构造方法注入==》就是利用set方法注入
有参构造方法注入
set方法注入的类必须要有无参构造方法
测试对象:
Address类:
public class Address {
private String address;
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "Address{" +
"address='" + address + '\'' +
'}';
}
}
Student类:
public class Student {
private String name;
private Address address;
private String[] books;
private List<String> hobbies;
private Map<String,String> card;
private Set<String> games;
private String wife;
private Properties info;
//无参构造
public Student() {
}
//有参构造
public Student(String name, Address address, String[] books, List<String> hobbies, Map<String, String> card, Set<String> games, String wife, Properties info) {
this.name = name;
this.address = address;
this.books = books;
this.hobbies = hobbies;
this.card = card;
this.games = games;
this.wife = wife;
this.info = info;
}
//getter和setter
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
public String[] getBooks() {
return books;
}
public void setBooks(String[] books) {
this.books = books;
}
public List<String> getHobbies() {
return hobbies;
}
public void setHobbies(List<String> hobbies) {
this.hobbies = hobbies;
}
public Map<String, String> getCard() {
return card;
}
public void setCard(Map<String, String> card) {
this.card = card;
}
public Set<String> getGames() {
return games;
}
public void setGames(Set<String> games) {
this.games = games;
}
public String getWife() {
return wife;
}
public void setWife(String wife) {
this.wife = wife;
}
public Properties getInfo() {
return info;
}
public void setInfo(Properties info) {
this.info = info;
}
//toString
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", address=" + address +
", books=" + Arrays.toString(books) +
", hobbies=" + hobbies +
", card=" + card +
", games=" + games +
", wife='" + wife + '\'' +
", info=" + info +
'}';
}
}
beans.xml中类注册和属性注入
注入属性分类:普通注入value、bean注入ref、array、list、map、set、null、properties
<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="address" class="com.kuang.pojo.Address">
<property name="address" value="北京"/>
bean>
<bean id="student" class="com.kuang.pojo.Student">
<property name="name" value="小明"/>
<property name="address" ref="address"/>
<property name="books">
<array>
<value>红楼梦value>
<value>西游记value>
<value>三国演义value>
<value>水浒传value>
array>
property>
<property name="hobbies">
<list>
<value>听歌value>
<value>敲代码value>
<value>看小姐姐value>
<value>看电影value>
list>
property>
<property name="card">
<map>
<entry key="身份证" value="12345678"/>
<entry key="银行卡" value="87654321"/>
map>
property>
<property name="games">
<set>
<value>马里奥value>
<value>魂斗罗value>
<value>坦克大战value>
set>
property>
<property name="wife">
<null/>
property>
<property name="info">
<props>
<prop key="driver">20210710prop>
<prop key="url">manprop>
<prop key="username">rootprop>
<prop key="password">123456prop>
props>
property>
bean>
beans>
测试:
public void test(){
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
Student student = (Student) context.getBean("student");
System.out.println(student.toString());
}
测试结果:
Student{
name='小明',
address=Address{address='北京'},
books=[红楼梦, 西游记, 三国演义, 水浒传],
hobbies=[听歌, 敲代码, 看小姐姐, 看电影],
card={
身份证=12345678,
银行卡=87654321
},
games=[马里奥, 魂斗罗, 坦克大战],
wife='null',
info={
password=123456,
url=man,
driver=20210710,
username=root
}
}
本质:
1.P命名空间注入 : 需要在头文件中加上约束文件
导入约束 : xmlns:p="http://www.springframework.org/schema/p"
<bean id="student" class="com.kuang.pojo.Student" p:name="小明"/>
2.c命名空间注入 : 需要在头文件中加上约束文件
导入约束 : xmlns:c="http://www.springframework.org/schema/c"
<bean id="student" class="com.kuang.pojo.Student" p:name="小明"/>
bean为每个类创建的对象,六种作用域:
1.单例模式(Spring默认机制:每次从容器中getBean的时候,拿到的是同一个对象)
beans.xml:
<bean id="user" class="com.kuang.pojo.User" scope="singleton">
test:
public void test(){
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
User user1 = (User) context.getBean("user");
User user2 = (User) context.getBean("user");
System.out.println(user1==user2); //true
}
2.原型模式(每次从容器中getBean的时候,都会产生一个新的对象)
beans.xml:
<bean id="user" class="com.kuang.pojo.User" scope="prototype">
test:
System.out.println(user1==user2); //false
3.其余的request、session、application这些都只能在web开发中使用到!
Spring中bean中引用bean有三种装配机制,分别是
在xml中显式配置;
在java中显式配置;
隐式的bean发现机制和自动装配(本节研究的)
组件扫描和自动装配,使得显式的配置降低到最少。
实际应用中不推荐使用自动装配xml配置,而是使用注解装配。
1.新建一个项目
2.新建两个实体类,Cat、Dog都有一个叫的方法
public class Cat {
public void shout() {
System.out.println("miao~");
}
}
public class Dog {
public void shout() {
System.out.println("wang~");
}
}
3.新建一个拥有者类People
package com.kuang.pojo;
import lombok.Data;
public class People {
private Cat cat;
private Dog dog;
private String name;
public Cat getCat() {
return cat;
}
public void setCat(Cat cat) {
this.cat = cat;
}
public Dog getDog() {
return dog;
}
public void setDog(Dog dog) {
this.dog = dog;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "People{" +
"cat=" + cat +
", dog=" + dog +
", name='" + name + '\'' +
'}';
}
}
4.编写Spring配置文件beans.xml**【在xml中显式配置引用的bean】**
<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="cat" class="com.kuang.pojo.Cat">bean>
<bean id="dog" class="com.kuang.pojo.Dog">bean>
<bean id="people" class="com.kuang.pojo.People">
<property name="cat" ref="cat"/>
<property name="dog" ref="dog"/>
<property name="name" value="qinjiang"/>
bean>
beans>
5.测试
@Test
public void test(){
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
People people = context.getBean("people",People.class);
people.getCat().shout();
people.getDog().shout();
}
结果正常输出,环境ok
autowire="byName"
按名称自动装配
测试:
1.修改bean配置,增加一个属性autowire="byName"
<bean id="cat" class="com.kuang.pojo.Cat">bean>
<bean id="dog" class="com.kuang.pojo.Dog">bean>
<bean id="people" class="com.kuang.pojo.People" autowire="byName">
<property name="name" value="qinjiang"/>
bean>
2.再次测试,结果依旧成功输出
3.如果将cat的id修改,和people属性名称不一致,此时按名称自动装配失败,空指针异常。
因为byname规则实际上是按people属性的set方法找对应的bean去装配,此时找不到。
<bean id="cat111" class="com.kuang.pojo.Cat">bean>
byName装配规则:
autowire="byType"
按类型自动装配
使用时需要保证:同一类型的对象,在spring容器中唯一。否则会报不唯一异常。
测试:
修改bean配置,增加一个属性autowire="byType"
测试,正常输出
此时被引用的bean的id名称无所谓了,可以去掉,因为是按照对象类型来寻找并自动装配的。
<bean id="cat22" class="com.kuang.pojo.Cat">bean>
<bean id="dog22" class="com.kuang.pojo.Dog">bean>
<bean id="people" class="com.kuang.pojo.People" autowire="byType">
<property name="name" value="qinjiang"/>
bean>
jdk1.5开始支持注解,spring2.5全面支持注解
准备工作:
在beans.xml配置文件中引入context文件头,注意学会修改方式配置文件
xmlns:context="http://www.springframework.org/schema/context" 【注意开头加上context】
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
beans.xml中开启属性 注解支持
<context:annotation-config/>
<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/>
<bean id="cat" class="com.kuang.pojo.Cat">bean>
<bean id="dog" class="com.kuang.pojo.Dog">bean>
<bean id="people" class="com.kuang.pojo.People">
<property name="name" value="qinjiang"/>
bean>
beans>
@Autowired
是按照类型自动寻找匹配,不支持id名字匹配
public class People {
@Autowired
private Cat cat;
@Autowired
private Dog dog;
private String name;
}
@Autowired(required=false)
使用,false表示注解标记的对象可以为null,true不能为空必须有对象
如在没有注册cat的bean时,people仍能成功注入,只是此时cat引用对象可以为空
@Autowired(required = false)
private Cat cat;
可以辅助使用@Qualifier(value = "dog2")
,进而可以通过id名字匹配
@Autowired
@Qualifier(value = "dog2")
private Dog dog;
@Resource
:如有指定name属性,按照先按照指定id名称查找匹配
@Resource(name = "dog2")
private Dog dog;
再进行默认的byName方式查找装配
@Resource
private Dog dog;
以上都不成功,则按byType方式自动装配
@Autowired与@Resource异同:
@Component
注解取代xml中的
需要在beans.xml中配置扫描哪些包下的注解
<context:component-scan base-package="com.kuang.pojo"/>
@Value
@Autowired
类对象
Cat:
@Component
public class Cat {
public void bark(){
System.out.println("miao~");
}
}
User:
//类bean注册采用注解替代
@Component
public class User {
//普通属性注入
@Value("kuangshen")
private String name;
//引用类型属性 bean注入
@Autowired
private Cat cat;
}
等价于原来beans.xml中:
<bean id="cat" class="com.kuang.pojo.Cat"/>
<bean id="user" class="com.kuang.pojo.User">
<property name="name" value="kuangshen"/>
<property name="cat" ref="cat"/>
bean>
beans.xml
<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.kuang.pojo"/>
beans>
测试
public void test(){
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
User user = (User) context.getBean("user");
System.out.println(user.getName());
user.getCat().bark();
}
开发中我们通常采用MVC三层架构
为了区分在不同的层中对其实现类,在Spring中进行注册装配bean
@Component有一些别名,功能都一样:都是注册bean对象
写上这些注解,就相当于将这个类交给Spring管理装配了!
一般在具体类前@Component
下跟随书写
//类bean注册采用注解替代
@Component
@Scope("singleton")
public class User {
...
}
xml与注解 实现注册bean和注入属性 比较:
**xml与注解 整合开发:**推荐做法
JavaConfig原来是基于Spring的一个子项目,它通过Java类的方式提供Bean的定义信息
在Spring4的版本,JavaConfig正式成为Spring4的核心功能
采用此种配置方法,可以完全摒弃beans.xml配置文件
编写实体类User
仍然采用注解注册bean,和进行属性注入
//注解实现bean注入,可以不需要,因为在MyConfig配置类中注册了bean
@Component
public class User {
//属性注入
@Value("kuangshen")
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
在java的com.kuang下新建一个config的包,编写一个MyConfig配置类【关键】
//用MyConfig的Java类取代配置文件beans.xml配置文件
@Configuration
//注解扫描包声明
@ComponentScan("com.kuang.pojo")
public class MyConfig {
//用Java返回函数取代beans.xml中类的bean注册。方法名:等于bean中的id
@Bean
public User user(){
return new User();
}
}
测试
需要采用new AnnotationConfigApplicationContext(MyConfig.class);
获取Spring中管理的对象
@Test
public void test(){
ApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class);
User user = (User) context.getBean("user");
System.out.println(user.getName());
}
这种纯Java的配置模式,在SpringBoot中随处可见!