IOC思想是基于IOC容器完成,IOC容器底层就是工厂对象。
Spring提供了IOC容器实现两种方式:(两个接口)
在spring配置文件中,使用bean标签,标签里面添加对应的属性就可以实现对象的创建。
bean标签有很多的属性
id :唯一标识
class: 类全路径
name:现在用的很少,和id基本一个性质,但是可以添加特殊符号
创建对象的时候,默认也是执行的无参构造方法完成对象的创建
<!--配置User对象创建-->
<bean id="user" class="net.yscxy.spring5.User"/>
第一种注入方式:使用set方法进行注入
<bean id="book" class="net.yscxy.spring5.Book">
<!--使用property进行属性注入-->
<property name="banme" value="测试注入"/>
</bean>
第二种注入方式:使用有参构造进行注入
<!--有参构造注入属性-->
<bean id="order" class="net.yscxy.spring5.Order">
<constructor-arg index="0" value="1"/>
<constructor-arg index="1" value="测试订单"/>
</bean>
第三种注入方式:使用名称空间注入其实也是set方法进行注入
加入名称空间
xmlns:p="http://www.springframework.org/schema/p"
<!--使用名称空间进行注入-->
<bean id="order" class="net.yscxy.spring5.Order" p:id="123" p:name="测试"></bean>
分割线
1、Spring有两种类型的bean,一种是普通Bean,另外一种是工厂Bean
2、普通Bean:在配置文件中定义bean类型就是返回类型
3、工厂bean:在配置文件中定义bean类型可以返回的不一样
第一步:创建类,让这个类作为工厂bean实现接口FactoryBean
第二步:实现接口里面的方法,在实现方法中定义返回的bean类型
工厂模式就是为了不暴露创建对象的过程
package net.yscxy.spring5.factorybean;
import org.springframework.beans.factory.FactoryBean;
public class MyBean implements FactoryBean<User> {
//定义返回bean
@Override
public User getObject() throws Exception {
return new User("安其拉");
}
@Override
public Class<?> getObjectType() {
return null;
}
@Override
public boolean isSingleton() {
return false;
}
}
1、在Spring里面。可以设置bean实例是单实例还是多实例的
2、在Spring里面,默认是单实例的bean
//单实例测试
@Test
public void testuser() {
//记载spring配置文件
ApplicationContext context = new FileSystemXmlApplicationContext("bean03.xml");
//获取配置创建的对象
User user1= context.getBean("user", User.class);
user1.setName("123");
System.out.println(user1.toString());
User user2= context.getBean("user", User.class);
System.out.println(user2.toString());
}
//输出结果:
User{name='123'}
User{name='123'}
3、如何设置多实例(在bean标签里面有属性用于设置时多实例还是单实例-scope)scope="prototype"
//此时的输出 结果为下所示
User{name='123'}
User{name='null'}
如果设置的值为scope="prototype"那么就不是在加载Spring配置文件的时候创建对象,而是在调用getBean的时候创建对象,每次都是新建的一个实例。
1、通过构造器创建bean(无参构造)
2、为bean的属性设置值和对其他bean的引用(调用set方法)
-->把bean实例传递bean后置处理方法
3、调用bean的初始化方法(需要进行配置)
-->把bean实例传递bean后置处理方法
4、bean可以使用了(对象获取到了)
5、让容器关闭的时候,调用bean的销毁方法(需要进行配置销毁的方法)
<bean id="order" class="net.yscxy.spring5.bean.Orders" init-method="initMethod" destroy-method="destory">
<property name="oname" value="手机" ></property>
</bean>
1、根据指定装配的规则(属性名称或者属性类型)Spring自动将匹配的属性进行注入
<!--实现自动装配 bean标签属性autowire 配置自动装配 autowire属性常用两个值: byName根据属性名称注入,注入bean的id的值和类的属性的名称需要一样 byType根据属性类型注入 --> <bean id="emp" class="net.yscxy.spring5.autoWire.Emp" autowire="byType">
1、直接配置数据库信息
2、通过引入外部的属性文件(记得引入名称空间)
IOC操作Bean管理(基于注解方式)
Spring 针对Bean管理中的创建对象提供注解
1、@Component
2、@Service
3、@Controller
4、@Respository
<!--开启组件扫描
1.如果扫描多个包,多个包使用逗号隔开
2.扫描包的上层目录
-->
<context:component-scan base-package="net.yscxy.spring5"></context:component-scan>
需要注意的细节问题
1、@AutoWired 根据属性类型进行自动装配
2、@Qualifier 根据属性名称进行注入,需要配合@AutoWired 自定义名称的时候
3、@Resource 根据类型注入,可以根据名称注入
4、@Value 注入普通类型属性
当然上面的写法还是没有完全脱离xml配置文件,我们也可以写一下配置文件类去进行替代,但是需要这样来进行加载配置类
面向切面编程-不改变源代码,可以添加先功能
底层使用动态代理
1、有接口情况 ——使用JDK动态代理
2、没有接口的情况——使用CGLIB
package net.yscxy.spring5;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;
public class JDKProxy {
public static void main(String[] args) {
//创建接口实现类代理对象
Class[] interfaces = {UserDao.class};
UserDaoImpl userDao = new UserDaoImpl();
UserDao dao = (UserDao) Proxy.newProxyInstance(JDKProxy.class.getClassLoader(), interfaces, new UserDaoProxy(userDao));
int add = dao.add(1, 2);
System.out.println(add);
}
}
class UserDaoProxy implements InvocationHandler {
private Object object;
//把创建的谁的代理对象,需要把这个对象传过来
public UserDaoProxy(Object object) {
this.object = object;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//方法之前
System.out.println("方法执行之前" + method.getName() + " 传递的参数:" + Arrays.toString(args));
//被增强的方法
Object res = method.invoke(object, args);
//方法之后执行
System.out.println("方法执行之后执行..." + object.toString());
return res;
}
}
1、连接点:类里面哪些方法可以被增强,这些方法称为连接点
2、切入点:实际被真增强的方法称为 、切入点
3、通知(增强):实际增强的逻辑部分称为通知
通知有多种类型:前置通知,后置通知、环绕通知、异常通知、最终通知(finally)
4、切面:是动作,把通知应用到切入点的过程
package net.yscxy.spring5.aopanno;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
//增强类
@Aspect //表示要生成一个代理对象
@Component
public class UserProxy {
@Before(value = "execution(* net.yscxy.spring5.aopanno.User.add(..))")
public void before() {
System.out.println("before...");
}
//最终通知
@After(value = "execution(* net.yscxy.spring5.aopanno.User.add(..))")
public void After() {
System.out.println("After...");
}
//有异常的时候通知
@AfterThrowing(value = "execution(* net.yscxy.spring5.aopanno.User.add(..))")
public void AfterThrowing() {
System.out.println("AfterThrowing...");
}
@AfterReturning(value = "execution(* net.yscxy.spring5.aopanno.User.add(..))")
public void AfterReturning() {
System.out.println("AfterReturning ...");
}
//环绕通知
@Around(value = "execution(* net.yscxy.spring5.aopanno.User.add(..))")
public void Around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
System.out.println("环绕之前...");
proceedingJoinPoint.proceed();
System.out.println("环绕之后...");
}
}
执行顺序为:
环绕之前...
before...
add ....
环绕之后...
After...
AfterReturning ...
//相同切入点抽取
@Pointcut(value = "execution(* net.yscxy.spring5.aopanno.User.add(..))")
public void pointdemo() {
}
@Before(value = "pointdemo()")
public void before() {
System.out.println("before...");
}
事务是数据库操作最基本单元,逻辑上一组操作,要么都成功,如果有一个操作失败,那么都失败
事务四个特性ACID
1、原子性
2、一致性
3、隔离性
4、持久性
事务一般加到Service层,且有两种方式,一种是编程方式,一种是声明式
@Tyansactional(),直接写在类上
propagation:事务的传播行为
多事务方法直接进行调用,这个过程事务是如何进行管理的
3、ioslation: 隔离级别
事务有特性成为隔离性,多事务操作之间不会产生影响。不考虑隔离性产生很多问题
(1)脏读、不可重复读、虚(幻)读
脏读:一个未提交事务读取到另一个未提交事务的数据
不可重复读 :一个未提交事务读取到另一个提交事务修改数据
虚读:一个未提交事务读取到另一个提交事务添加数据
隔离级别配置参数:mysql默认-可重复读
4、timeout:超时时间
(1)事务需要在一定时间内进行提交,如果不提交进行回滚
(2)默认值时-1,设置时间以秒未单位进行计算
5、readOnly:是否只读
(1)读,只能查询,默认未false
6、rollbackFor:回滚
(1)设置出啊先哪些异常进行事务回滚
7、noRollbackFor:不回滚
(1)设置出现哪些异常不进行事务回滚
事务的传播行为
(1)Spring5整合Log4j2
(2)@Nullable,可以使用在方法上(返回值可为空),参数,属性,
(3)支持函数式表达式
(1)是Spring5添加的新模块,用于Web开发的,功能和SpringMvc类似,Webflux使用当前一种比较流程像饮食编程出现的框架。
(2)使用传统的Web框架比如SpringMvc,这些基于Servlet容器,Webflux是哟中异步非阻塞的框架,异步非阻塞的框架在Servlet3.1以后才支持,核心是基于Reactor的相关API实现的。
(3)异步和同步针对调用者,调用者发送请求
响应式编程是一种面向数据流和变化传播的编程范式。这意味着可以在编程语言中很方便地表达静态或动态的数据流,而相关的计算模型会自动将变化的值通过数据流进行传播。
提供得到观察者模式两个类:Observer和Observable
package net.yscxy.demoreactor8.reactor8;
import java.util.Observable;
public class ObserverDemo extends Observable {
public static void main(String[] args) {
ObserverDemo observerDemo = new ObserverDemo();
//添加观察者
observerDemo.addObserver((o, arg) -> {
System.out.println("发生变化");
});
observerDemo.addObserver((o, arg) -> {
System.out.println("手动被观察者通知,准备改变");
});
observerDemo.setChanged();//数据变化
observerDemo.notifyObservers();//通知
}
}
(1)响应式编程操作中,Reactor是满足Reactive规饭框架
(2)Reactor有两个核心类,Mono和Glux,这两个类实现接口Publisher,提供丰富操作符,Flux对象实现发布者,返回N个元素;Mono实现翻发布者,返回0或者1个元素
(3)Flux和Mono都是数据流的发布者,使用Flux和Mono都可以发出三种信号:元素值,错误信号,完成信号,错误信号 和完成信号,都代表终止信号,终止信号告诉订阅者数据流结束了。
最后挂几个链接咯感兴趣可以瞧瞧的: