既然想要理解原理 那尽头即是语文
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