文章目录
介绍
- Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器(框架)
ioc基础
原始的项目写法-接口和实现
public interface UserDao {
void getUer();
}
public class UserDaoImpl implements UserDao {
public void getUer() {
System.out.println("获取用户数据");
}
}
service
public interface Iuser {
public void getUser();
}
public class IUserService implements Iuser {
private UserDao userDao = new UserDaoImpl();
public void getUser() {
userDao.getUer();
}
}
如果想要增加不同的实现,需要修改新的实现
public class UserDaoMysql implements UserDao{
public void getUer() {
System.out.println("msyql 获取用户信息");
}
}
service层
public class IUserService implements Iuser {
// private UserDao userDao = new UserDaoImpl();
private UserDao userDao = new UserDaoMysql();
public void getUser() {
userDao.getUer();
}
}
那么我们要使用Oracle , 又需要去service实现类里面修改对应的实现 . 假设我们的这种需求非常大 , 这种方式就根本不适用了, 甚至反人类对吧 , 每次变动 , 都需要修改大量代码 . 这种设计的耦合性太高了, 牵一发而动全身 .
那我们如何去解决呢 ?
可以用set方法,在调用的时候在把属性set进来!
public class IUserServiceSet implements Iuser {
private UserDao userDao;
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
public void getUser() {
userDao.getUer();
}
}
在调用的时候,根据业务set dao
public void user() {
// Iuser iuser = new IUserService();
// iuser.getUser();
Iuser iuser =new IUserServiceSet();
((IUserServiceSet) iuser).setUserDao(new UserDaoOracle());
iuser.getUser();
//需要用到MySQL
((IUserServiceSet) iuser).setUserDao(new UserDaoMysql());
iuser.getUser();
}
以前所有东西都是由程序去进行控制创建 , 而现在是由我们自行控制创建对象 , 把主动权交给了调用者 . 程序不用去管怎么创建,怎么实现了 . 它只负责提供一个接口 .
这种思想 , 从本质上解决了问题 , 我们程序员不再去管理对象的创建了 , 更多的去关注业务的实现 . 耦合性大大降低 . 这也就是IOC的原型 !
IOC本质
控制反转IoC(Inversion of Control),是一种设计思想,DI(依赖注入)是实现IoC的一种方法,也有人认为DI只是IoC的另一种说法。没有IoC的程序中 , 我们使用面向对象编程 , 对象的创建与对象间的依赖关系完全硬编码在程序中,对象的创建由程序自己控制,控制反转后将对象的创建转移给第三方,个人认为所谓控制反转就是:获得依赖对象的方式反转了。
IoC是Spring框架的核心内容,使用多种方式完美的实现了IoC,可以使用XML配置,也可以使用注解,新版本的Spring也可以零配置实现IoC。
Spring容器在初始化时先读取配置文件,根据配置文件或元数据创建与组织对象存入容器中,程序使用时再从Ioc容器中取出需要的对象。
采用XML方式配置Bean的时候,Bean的定义信息是和实现分离的,而采用注解的方式可以把两者合为一体,Bean的定义信息直接以注解的形式定义在实现类中,从而达到了零配置的目的。
控制反转是一种通过描述(XML或注解)并通过第三方去生产或获取特定对象的方式。在Spring中实现控制反转的是IoC容器,其实现方法是依赖注入(Dependency Injection,DI)。
HelloSpring -入门例子
Hello 实体
public class Hello {
private String name;
public Hello() {
}
public Hello(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void show() {
System.out.println("hello:" + name);
}
}
resource 目录下新建bean.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 id="hello" class="com.songyang.service.Hello">
<property name="name" value="songyang"/>
</bean>
</beans>
测试
@Test
public void hello() {
//解析beans.xml文件 , 生成管理相应的Bean对象
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
//getBean : 参数即为spring配置文件中bean的id .
Hello hello = (Hello) context.getBean("hello");
hello.show();
}
属性注入的本质是通过set方法进行注入,如果将实体中的set方法去掉,将不能完成注入!!!!
Hello 对象是谁创建的 ? 【hello 对象是由Spring创建的 Hello 对象的属性是怎么设置的 ? hello 对象的属性是由Spring容器设置的
这个过程就叫控制反转 :
- 控制 : 谁来控制对象的创建 , 传统应用程序的对象是由程序本身控制创建的 , 使用Spring后 , 对象是由Spring来创建的
- 反转 : 程序本身不创建对象 , 而变成被动的接收对象 .
依赖注入 : 就是利用set方法来进行注入的.
IOC是一种编程思想,由主动的编程变成被动的接收
可以通过newClassPathXmlApplicationContext去浏览一下底层源码 .
现在对原来的代码进行修改
在bean.xml中配置类
<bean id="UserDaoImpl" class="com.songyang.dao.UserDaoImpl"></bean>
<bean id="UserDaoMysql" class="com.songyang.dao.UserDaoMysql"></bean>
<bean id="UserDaoOracle" class="com.songyang.dao.UserDaoOracle"></bean>
<bean id="IUserServiceSet" class="com.songyang.service.IUserServiceSet">
<!--注意: 这里的name并不是属性 , 而是set方法后面的那部分 , 首字母小写-->
<!--引用另外一个bean , 不是用value 而是用 ref-->
<property name="userDao" ref="UserDaoOracle"></property>
</bean>
注意!这里的name并不是属性 , 而是set方法后面的那部分 , 首字母小写!
测试方法
@Test
public void hello() {
//解析beans.xml文件 , 生成管理相应的Bean对象
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
//getBean : 参数即为spring配置文件中bean的id .
// Hello hello = (Hello) context.getBean("hello");
// hello.show();
IUserServiceSet iUserServiceSet = (IUserServiceSet) context.getBean("IUserServiceSet");
iUserServiceSet.getUserInfo();
}
到了现在 , 我们彻底不用再程序中去改动了 , 要实现不同的操作 , 只需要在xml配置文件中进行修改 , 所谓的IoC,一句话搞定 : 对象由Spring 来创建 , 管理 , 装配 !
IOC创建对象的方式
无参构造器创建
public class Hello {
private String name;
public Hello() {
System.out.println("这是hello的无参构造函数!!!!");
}
<bean id="hello" class="com.songyang.service.Hello">
<property name="name" value="songyang"/>
</bean>
实现
@Test
public void hello() {
//解析beans.xml文件 , 生成管理相应的Bean对象
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
//getBean : 参数即为spring配置文件中bean的id .
Hello hello = (Hello) context.getBean("hello");
hello.show();
// IUserServiceSet iUserServiceSet = (IUserServiceSet) context.getBean("IUserServiceSet");
// iUserServiceSet.getUserInfo();
}
结果:
这是hello的无参构造函数!!!!
hello:songyang
<property 标签默认就是无参构造器创建bean
有参构造函数创建对象
<!-- 第一种根据index参数下标设置 -->
<bean id="userT" class="com.kuang.pojo.UserT">
<!-- index指构造方法 , 下标从0开始 -->
<constructor-arg index="0" value="kuangshen2"/>
</bean>
<!-- 第二种根据参数名字设置 -->
<bean id="userT" class="com.kuang.pojo.UserT">
<!-- name指参数名 -->
<constructor-arg name="name" value="kuangshen2"/>
</bean>
<!-- 第三种根据参数类型设置(不推荐使用) -->
<bean id="userT" class="com.kuang.pojo.UserT">
<constructor-arg type="java.lang.String" value="kuangshen2"/>
</bean>
别名
<!--设置别名:在获取Bean的时候可以使用别名获取-->
<alias name="userT" alias="userNew"/>
<!--bean就是java对象,由Spring创建和管理-->
<!--
id 是bean的标识符,要唯一,如果没有配置id,name就是默认标识符
如果配置id,又配置了name,那么name是别名
name可以设置多个别名,可以用逗号,分号,空格隔开
如果不配置id和name,可以根据applicationContext.getBean(.class)获取对象;
class是bean的全限定名=包名+类名
-->
<bean id="hello" name="hello2 h2,h3;h4" class="com.kuang.pojo.Hello">
<property name="name" value="Spring"/>
</bean>
import
<import resource="{path}/beans.xml"/>
bean作用域
在Spring中,那些组成应用程序的主体及由Spring IoC容器所管理的对象,被称之为bean。简单地讲,bean就是由IoC容器初始化、装配及管理的对象 .
<bean id="ServiceImpl" class="cn.csdn.service.ServiceImpl" scope="singleton">
Bean 的自动装配
实际项目中都是用注解装配
1、在spring配置文件中引入context文件头
xmlns:context="http://www.springframework.org/schema/context"
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
2、开启属性注解支持!
<context:annotation-config/>
需要导入 spring-aop的包!
测试
1、实体中set方法去掉 用@autowird
public class User {
@Autowired
private Cat cat;
@Autowired
private Dog dog;
private String str;
public Cat getCat() {
return cat;
}
public Dog getDog() {
return dog;
}
public String getStr() {
return str;
}
}
2、配置文件中的bean
<context:annotation-config/>
<bean id="dog" class="com.kuang.pojo.Dog"/>
<bean id="cat" class="com.kuang.pojo.Cat"/>
<bean id="user" class="com.kuang.pojo.User"/>
注意要开启注解配置 context:annotation-config/
使用注解开发
1、配置文件中引入context约束
<?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">
</beans>
2、配置扫描哪些包下的注解
<context:component-scan base-package="com.kuang.pojo"/>
3、编写实体类 加上@component 注解
@Component("user")
// 相当于配置文件中 <bean id="user" class="当前注解的类"/>
public class User {
public String name = "秦疆";
}
@Component(“user”) 默认是类名小写
4、属性注入
4.1 属性上直接注入
@Component("user")
// 相当于配置文件中 <bean id="user" class="当前注解的类"/>
public class User {
@Value("秦疆")
// 相当于配置文件中 <property name="name" value="秦疆"/>
public String name;
}
4.2 set方法上注入
@Component("user")
public class User {
public String name;
@Value("秦疆")
public void setName(String name) {
this.name = name;
}
}
小结
XML与注解比较
XML可以适用任何场景 ,结构清晰,维护方便
注解不是自己提供的类使用不了,开发简单方便
xml与注解整合开发 :推荐最佳实践
xml管理Bean
注解完成属性注入
使用过程中, 可以不用扫描,扫描是为了类上的注解
context:annotation-config/
作用:
进行注解驱动注册,从而使注解生效
用于激活那些已经在spring容器里注册过的bean上面的注解,也就是显示的向Spring注册
如果不扫描包,就需要手动配置bean
如果不加注解驱动,则注入的值为null!
使用Java的方式配置spring
1、编写一个实体类,Dog
@Component //将这个类标注为Spring的一个组件,放到容器中!
public class Dog {
public String name = "dog";
}
2、新建一个config配置包,编写一个MyConfig配置类
@Configuration //代表这是一个配置类
public class MyConfig {
@Bean //通过方法注册一个bean,这里的返回值就Bean的类型,方法名就是bean的id!
public Dog dog(){
return new Dog();
}
3、测试
@Test
public void test2(){
ApplicationContext applicationContext =
new AnnotationConfigApplicationContext(MyConfig.class);
Dog dog = (Dog) applicationContext.getBean("dog");
System.out.println(dog.name);
}
4、成功输出结果!