既然想要理解原理 那尽头即是语文
IOC 控制反转
先说一下大致笼统的:
由用户管理Bean 转变为 框架管理Bean
框架即是 IOC Container
Bean就相当于一个组件 调用它实现相应功能
Ioc即“控制反转”,不是什么技术,而是一种设计思想
控制
不再进行new创建对象 而是IOC容器控制对象的创建
反转
容器帮忙创建及注入依赖对象
优点:
使代码松散耦合
看一个例子:
Dao: public interface UserDao { void getUser(); } public class UserImpl implements UserDao{ public void getUser() { System.out.println("获取用户数据"); } } Service: public interface UserService { void getUser(); } public class UserServiceImpl implements UserService { private UserDao userDao; // 注入 public void setUserDao(UserDao userDao){ this.userDao=userDao; } //写死 传统下: // private UserDao userDao = new UserImpl(); public void getUser() { userDao.getUser(); } }
假如数据源很多需要实现的服务很多 <?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 id="mysql" class="dao.UserImplMysql"/> <bean id="other" class="dao.UserImplOtherSQl"/> <bean id="UserServiceImpl" class="Service.UserServiceImpl"> <!-- ref 应用spring容器中创建好的对象--> <!-- value 具体的值--> <property name="userDao" ref="mysql"/> </bean> </beans>
import Service.UserService; import Service.UserServiceImpl; import dao.UserImpl; import dao.UserImplMysql; import dao.UserImplOtherSQl; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class Daotest { public static void main(String[] args) { //用户实际调用的是业务层 dao层不接触 UserServiceImpl userService = new UserServiceImpl(); // // // userService.setUserDao(new UserImplMysql()); // userService.setUserDao(new UserImplOtherSQl()); // userService.getUser(); ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); UserServiceImpl userServiceImpl = (UserServiceImpl) context.getBean("UserServiceImpl"); userServiceImpl.getUser(); } }
不用再一个一个new创建调用 而是直接beans.xml配置好 然后直接使用
首先 配置Bean
- xml
- java
- 注解
1. 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"> <!-- spring中创建对象 都用作Bean--> <!-- 等同于new 一个对象--> <bean id="hello" class="pojo.Hello"> <property name="name" value="高低远近"/> </bean> </beans>
优点: 可以使用于任何场景,结构清晰,通俗易懂
缺点: 配置繁琐,不易维护,枯燥无味,扩展性差
2. java
@Configuration注解声明为配置类
@Bean 标记实例 交给Spring管理
优点:适用于任何场景,配置方便,因为是纯Java代码,扩展性高,十分灵活
缺点:由于是采用Java类的方式,声明不明显,如果大量配置,可读性比较差
3. 注解
- @Component
标记一个普通的Spring组件类
通过()可替代后三个 - @Controller
MVC控制器类 跳转 - @Service
业务服务类 - @Repository
标记Dao类
优点:开发便捷,通俗易懂,方便维护。
缺点:具有局限性,对于一些第三方资源,无法添加注解。只能采用XML或JavaConfig的方式配置
DI 依赖注入 实现方式
- 构造器注入
- setter注入
- 注解注入
直接看例子:
pojo实体类: package pojo; public class User { public User(String name) { this.name = name; } private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } public void show() { System.out.println(name); } }
构造器方式配置Bean 注意pojo类中要有有参构造方法 <?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 https://www.springframework.org/schema/beans/spring-beans.xsd"> <!--构造器注入 有参构造器--> <bean id="user" class="pojo.User" name="users,users2 users3;users4"> <!-- <property name="name" value="高地远近"/>--> <!-- <constructor-arg index="0" value="高地远近"/>--> <constructor-arg type="java.lang.String" value="高远"/> </bean> <alias name="user" alias="other_name"/> </beans>
测试: import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import pojo.User; public class TTest { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); User user = (User) context.getBean("user"); User user1 = (User) context.getBean("other_name"); User user2 = (User) context.getBean("users"); User user3 = (User) context.getBean("users2"); User user4 = (User) context.getBean("users3"); User user5 = (User) context.getBean("users4"); user.show(); user1.show(); user2.show(); user3.show(); user4.show(); user5.show(); } }
pojo实体类: package pojo; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.Set; 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; //Properties 继承于 Hashtable,用于管理配置信息的类。 //由于 Properties 继承自 Hashtable 类,因此具有 Hashtable 的所有功能,同时还提供了一些特殊的方法来读取和写入属性文件。 //Properties 类常用于存储程序的配置信息,例如数据库连接信息、日志输出配置、应用程序设置等。 // 使用Properties类可以将这些信息存储在一个文本文件中,并在程序中读取这些信息。 private Properties info; private String wife; public String[] getBooks() { return books; } public void setBooks(String[] books) { this.books = books; } 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 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 Properties getInfo() { return info; } public void setInfo(Properties info) { this.info = info; } public String getWife() { return wife; } public void setWife(String wife) { this.wife = wife; } @Override public String toString() { return "student{" + "name='" + name + '\'' + ", address=" + address.toString() + ", hobbies=" + hobbies + ", card=" + card + ", games=" + games + ", info=" + info + ", wife='" + wife + '\'' + '}'; } }
setter注入: <?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 https://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="address" class="pojo.Address"> <property name="addr" value="河北"/> </bean> <bean id="student" class="pojo.Student"> <!-- 值注入--> <property name="name" value="高远"/> <!-- bean注入--> <property name="address" ref="address"/> <!-- 数组注入--> <property name="books"> <array> <value>啊啊啊</value> <value>sda</value> <value>是的撒阿德</value> </array> </property> <!-- List注入--> <property name="hobbies"> <list> <value>阿萨德</value> <value>实打实</value> <value>我问问</value> </list> </property> <!-- Map注入--> <property name="card"> <map> <entry key="id卡" value="1111"/> <entry key="英航卡" value="2222"/> <entry key="萨达" value="3333"/> </map> </property> <!-- set注入--> <property name="games"> <set> <value>cf</value> <value>cs</value> <value>pubg</value> </set> </property> <!-- null注入--> <property name="wife"> <null/> </property> <!-- Properties注入--> <property name="info"> <props> <prop key="学号">222020</prop> <prop key="id">5555</prop> <prop key="电话">555555</prop> </props> </property> </bean> </beans>
测试: import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import pojo.Student; public class Mytest { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); Student student = (Student) context.getBean("student"); System.out.println(student.getName()); System.out.println(student.toString()); } }
注解注入:
package pojo; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import javax.annotation.Resource; /** * @Resource * byName默认和byType * * @Autowired * byType默认和byName 唯一一个 * */ public class People { //required=false 对象可以为空 // @Autowired(required = false) @Resource private Cat cat; @Autowired @Qualifier(value = "dog222") private Dog dog; private String name; @Override public String toString() { return "People{" + "cat=" + cat + ", dog=" + dog + ", name='" + name + '\'' + '}'; } public void setCat(Cat cat) { this.cat = cat; } public void setDog(Dog dog) { this.dog = dog; } public void setName(String name) { this.name = name; } public Cat getCat() { return cat; } public Dog getDog() { return dog; } public String getName() { return name; } }
<?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" xmlns:p="http://www.springframework.org/schema/p" 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"> <bean id="cat" class="pojo.Cat"/> <bean id="dog" class="pojo.Dog"/> <bean id="dog222" class="pojo.Dog"/> <!-- <bean id="people" class="pojo.People" p:cat-ref="cat" p:dog-ref="dog" p:name="高远">--> <!-- autowire自动装配--> <!-- <bean id="people" class="pojo.People" autowire="byName" p:name="高远">--> <!-- <bean id="people" class="pojo.People" autowire="byType" p:name="高远">--> <bean id="people" class="pojo.People" p:name="高远"> </bean> <context:annotation-config/> </beans> <!-- 2. "byName"--> <!-- Autowiring by property name. If a bean of class Cat exposes a "dog"--> <!-- property, Spring will try to set this to the value of the bean "dog"--> <!-- in the current container. If there is no matching bean by name, nothing--> <!-- special happens.--> <!-- 3. "byType"--> <!-- Autowiring if there is exactly one bean of the property type in the--> <!-- container. If there is more than one, a fatal error is raised, and--> <!-- you cannot use byType autowiring for that bean. If there is none,--> <!-- nothing special happens.-->
测试: import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import pojo.People; public class Mytest { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); People people = context.getBean("people", People.class); people.getDog().shout(); people.getCat().shout(); } }
@Autowired和@Resource以及@Inject等注解注入有何区别
1、@Autowired是Spring自带的,@Resource是JSR250规范实现的,@Inject是JSR330规范实现的
2、@Autowired、@Inject用法基本一样,不同的是@Inject没有required属性
3、@Autowired、@Inject是默认按照类型匹配的,@Resource是按照名称匹配的
4、@Autowired如果需要按照名称匹配需要和@Qualifier一起使用,@Inject和@Named一起使用,@Resource则通过name进行指定
参考:
https://pdai.tech/md/spring/spring-x-framework-ioc.html
https://segmentfault.com/a/1190000022016826
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?