欢迎您访问365答案网,请分享给你的朋友!
生活常识 学习资料

Spring·狂神说听课笔记

时间:2023-06-16
1、Spring 1.1 简介

Spring框架是由于软件开发的复杂性而创建的。Spring使用的是基本的JavaBean来完成以前只可能由EJB完成的事情。然而,Spring的用途不仅仅限于服务器端的开发。从简单性、可测试性和松耦合性角度而言,绝大部分Java应用都可以从Spring中受益。

1.2 优点

Spring是一个开源的免费的框架(容器)Spring是一个轻量级的、非入侵式的框架控制反转(IOC),面向切面编程(AOP)支持事务的处理,对框架整合的支持

总结一句话:Spring就是一个轻量级的控制反转(IOC)和面向切面编程(AOP)的框架

1.3 拓展

Spring Boot 是 Spring 的一套快速配置脚手架,可以基于Spring Boot 快速开发单个微服务;Spring Cloud是基于Spring Boot实现的;Spring Boot专注于快速、方便集成的单个微服务个体,Spring Cloud关注全局的服务治理框架;Spring Boot使用了约束优于配置的理念,很多集成方案已经帮你选择好了,能不配置就不配置 , Spring Cloud很大的一部分是基于Spring Boot来实现,Spring Boot可以离开Spring Cloud独立使用开发项目,但是Spring Cloud离不开Spring Boot,属于依赖的关系。SpringBoot在SpringClound中起到了承上启下的作用,如果你要学习SpringCloud必须要学习SpringBoot。 2、IOC

UserDao接口

public interface UserDao { void getUser();}

Dao 的实现类

public class UserDaoImpl implements UserDao{ @Override public void getUser() { System.out.println("默认获取用户的数据"); }}

UserService的接口

public interface UserService { void getUser();}

UserService的实现类

public class UserServiceImpl implements UserService { private UserDao userDao = new UserDaoImpl(); @Override public void getUser() { userDao.getUser(); }}

测试

@Testpublic void test(){ UserService service = new UserServiceImpl(); service.getUser();}

把Userdao的实现类增加一个 .

@Override public void getUser() { System.out.println("MySQl获取用户数据"); }

需要去service实现类里面修改对应的实现

private UserDao userDao = new UserDaoMySqlImpl(); @Override public void getUser() { userDao.getUser(); }

**结论:**我们要使需使用那个dao类 , 就要去service实现类里面修改对应的实现 、假设我们的这种需求非常大 , 这种方式就根本不适用了,因为 每次变动 , 都需要修改大量代码 、这种设计的耦合性太高了, 牵一发而动全身 .

如何解决?

我们可以在需要用到他的地方 , 不去实现它 , 而是留出一个接口 , 利用set , 我们去代码里修改下 .

private UserDao userDao; //利用set进行动态实现值的注入 public void setUserDao(UserDao userDao){ this.userDao = userDao; } @Override public void getUser() { userDao.getUser(); }

测试:

public static void main(String[] args) { //用户实际调用的是业务层,dao层他们不需要接触 UserServiceImpl userService = new UserServiceImpl(); userService.setUserDao(new UserDaoMysqlImpl()); userService.getUser(); }

结论:-

之前,程序员是主动创建对象,控制权在程序员手上使用set注入后,程序不在具有主动性,而是变成了被动接受的对象从本质上解决了问题,我们不用去管理对象的创建,系统耦合性大大降低,可以更加专注业务的实现,这就是IOC的原型

IOC本质

控制反转IoC(Inversion of Control),是一种设计思想,DI(依赖注入)是实现IoC的一种方法,也有人认为DI只是IoC的另一种说法。没有IoC的程序中 , 我们使用面向对象编程 , 对象的创建与对象间的依赖关系完全硬编码在程序中,对象的创建由程序自己控制,控制反转后将对象的创建转移给第三方,个人认为所谓控制反转就是:获得依赖对象的方式反转了。

采用XML方式配置Bean的时候,Bean的定义信息是和实现分离的,而采用注解的方式可以把两者合为一体,Bean的定义信息直接以注解的形式定义在实现类中,从而达到了零配置的目的。

控制反转是一种通过描述(XML或注解)并通过第三方去生产或获取特定对象的方式。在Spring中实现控制反转的是IoC容器,其实现方法是依赖注入(Dependency Injection,DI)。

3.HelloSpring

pojo

public class Hello { private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "Hello{" + "name='" + name + ''' + '}'; }}

编写beans.xml

<?xml version="1.0" encoding="UTF-8"?>

测试

public class MyTest { public static void main(String[] args) { //获取Spring的上下文对象 ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); Hello hello = (Hello) context.getBean("hello"); System.out.println(hello.toString()); }}

结论:

控制:传统应用程序的对象由程序本身控制,使用Spring后由Spring来创建反转:程序本身不创建对象,而变成被动的接收对象依赖注入:就是利用set方法来进行注入的IOC是一种编程思想,由主动编程变被动接收要实现不同的操作,只需要在xml文件中进行修改对象由Spring来创建,管理,分配

4、IOC创建对象的方式

使用无参构造

private String name; public User(){ System.out.println("User的无参构造!"); } public String getName() { return name; } public void setName(String name) { this.name = name; } public void show(){ System.out.println("name="+name); }}

使用有参构造的方式

public class User { private String name; public User(String name) { this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } public void show(){ System.out.println("name="+name); }}

下标赋值

通过类型创建(不建议使用)

参数名

总结:在配置文件加载的时候,容器中管理的对象就已经初始化了

5、Spring配置 5.1 别名

5.2 Bean配置

5.3 import

一般用于团队开发,可以将多个配置文件合并为一个

6、DI依赖注入 6.1 构造器注入 6.2 Set方式注入【重点】

依赖注入:Set注入

依赖:bean对象的创建依赖于容器注入:bean对象中的所有属性,由容器来注入

环境搭建

复杂类型

public class Address { private String address; public String getAddress() { return address; } public void setAddress(String address) { this.address = address; }}

真实测试对象

public class Student { private String name; private Address address; private String[] books; private List hobbies; private Map card; private Set games; private String wife; private Properties info; 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 getHobbies() { return hobbies; } public void setHobbies(List hobbies) { this.hobbies = hobbies; } public Map getCard() { return card; } public void setCard(Map card) { this.card = card; } public Set getGames() { return games; } public void setGames(Set 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; } @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

测试

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()); }}

完善注入信息

<?xml version="1.0" encoding="UTF-8"?> 红楼梦 西游记 水浒传 三国演义 抽烟 喝酒 烫头 洗脚 按摩 刺客信条 巫师3 使命召唤 202045678

6.3 拓展方式注入

可以使用p命名空间和c命名空间进行注入

userbean.xml

测试

@Test public void Test(){ ApplicationContext context = new ClassPathXmlApplicationContext("userbean.xml"); User user = context.getBean("user2",User.class); System.out.println(user); }

注意点:p命名和c命名空间不能直接使用,需要导入xml约束

```xml xmlns:p="http://www.springframework.org/schema/p" xmlns:c="http://www.springframework.org/schema/c" ```

6.4 bean的作用域

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5NwjEWWP-1644740162813)(C:UsersliangAppDataRoamingTyporatypora-user-imagesimage-20220208153959223.png)]

单例模式(Spring默认机制)

原型模式:每次从容器中get的时候,都会产生一个新对象

其余的request,session,application这些只能在web开发中使用的

7、Bean的自动装配

自动装配是Spring满足bean依赖一种方式Spring会在上下文中自动寻找,并自动给bean装配属性

Spring中的三种装配方式:

xml中显示的配置java中显示的配置隐式的自动装配bean【重要】 7.1 测试

环境搭建:一个人有两个宠物

工具类

public class Dog { public void shout(){ System.out.println("wang~"); }}

public class Cat { public void shout(){ System.out.println("miao~"); }}

public class People { private Dog dog; private Cat cat; private String name; public Dog getDog() { return dog; } public void setDog(Dog dog) { this.dog = dog; } public Cat getCat() { return cat; } public void setCat(Cat cat) { this.cat = cat; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "People{" + "dog=" + dog + ", cat=" + cat + ", name='" + name + ''' + '}'; }}

beans.xml

<?xml version="1.0" encoding="UTF-8"?>

测试

@Test public void test(){ ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); People people = context.getBean("people", People.class); people.getCat().shout(); people.getDog().shout(); }

7.2 ByName自动装配

7.3 ByType自动装配

小结:

ByName的时候,需要保证所有的bean的id唯一,并且这个bean需要和自己注入的属性的set方法的值一致ByType的时候,需要保证所有的bean的class唯一,并且这个bean需要和自己注入的属性的类型一致 7.4 使用注解实现自动装配

使用注解须知:

导入约束。context约束

配置注解的支持 : context:annotation-config/

<?xml version="1.0" encoding="UTF-8"?>

@Autowired

直接在属性上使用即可,也可以在set方式上使用可以不用编写set方法,前提是自动装配的属性在IOC(Spring)容器中存在,且符合名字ByName

科普:

@Nullable 字段标记了这个注解,说明这个字段可以为null

public @interface Autowired { boolean required() default true;}

测试代码:

public class People { //如果显示了定义了Autowired的required属性为false,说明这个对象可以为null,否则不允许为空 @Autowired(required = false)

@Qualifier

@Autowired是根据类型自动装配的,加上@Qualifier则可以根据byName的方式自动装配

@Qualifier不能单独使用

测试:

@Autowired @Qualifier("dog22") private Dog dog; @Autowired @Qualifier("cat11") private Cat cat; private String name;

@Resource注解

@Resource(name = "dog2") private Dog dog; @Resource(name = "cat1") private Cat cat;

小结:

@Resource和@Autowired的区别:

都是自动装配的,都可以放在属性字段上@Autowired通过ByType的方式实现,并必须要求这个对象存在【常用】@Resource默认通过ByName的方式实现,如果找不到名字,则通过ByType实现,如果都找不到,则会报错【常用】执行顺序不同

@Autowired通过ByType的方式实现@Resource默认通过ByName的方式实现 8、使用注解开发

bean

//等价于 //@Component@Componentpublic class User { public String name = "小刘";}

@Component:组件,放在类上,说明这个类被Spring管理了,就是bean

属性如何注入

//相当于 @Value("小四") public String name;

衍生注解

@Component有几个衍生注解,我们在web开发中,会按照mvc三层架构分层

dao【@Repository】

service【@Service】

controller【@Controller】

它们的注解功能都是一样的,都是代表将某个类注册到Spring中,装配Bean

自动装配

@Autowired 是根据类型自动装配的

@Nullable 字段标记了这个注解,说明这个字段可以为null

@Resource 通过装配名字,类型

作用域

@Component@Scope("singleton")public class User { //相当于 @Value("小四") public String name;

@scope

singleton:默认的,Spring会采用单例模式创建这个对象。关闭工厂 ,所有的对象都会销毁。prototype:多例模式。关闭工厂 ,所有的对象不会销毁。内部的垃圾回收机制会回收

小结

xml与注解:

XML可以适用任何场景 ,结构清晰,维护方便注解不是自己提供的类使用不了,开发简单方便

xml与注解最佳实践:

xml管理Bean

注解完成属性注入

要注意想让注解生效,就需要开启注解支持

9、使用Java的方式配置Spring

实体类

public class User { @Value("pig") private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "User{" + "name='" + name + ''' + '}'; }}

配置文件

//这个也会Spring容器托管,注册到容器中,因为他本来就是一个@Component//@Configuration代表这是一个配置类,就和我们之前看的beans.xml@Configuration@ComponentScan("com.lyd.pojo")@import(UserConfig2.class)public class UserConfig { //注册一个bean,就相当于我们之前写的一个bean标签 //这个方法的名字,就相当于bean标签中的id属性 //这个方法的返回值,就相当于bean标签中的class属性 @Bean public User getUser(){ return new User(); //就是返回要注入到bean的对象 }}

测试

public class MyTest { public static void main(String[] args) { ApplicationContext context = new AnnotationConfigApplicationContext(UserConfig.class); User user = (User) context.getBean("getUser"); System.out.println(user.getName()); }}

10、代理模式

两种代理模式:

静态代理动态代理 10.1 静态代理

角色分析:

抽象角色:一般会使用接口或抽象类真实角色:被代理角色代理角色:代理真实角色,代理后一般会做一些附属操作客户:访问代理对象的人

接口

public interface Rent { public void rent();}

真实角色

public class Host implements Rent{ @Override public void rent() { System.out.println("房东要出租房屋"); }}

代理角色

public class Proxy implements Rent{ private Host host; public Proxy() { } public Proxy(Host host) { this.host = host; } @Override public void rent() { seeHouse(); host.rent(); heTong(); fee(); } public void seeHouse(){ System.out.println("看房"); } public void heTong(){ System.out.println("签合同"); } public void fee(){ System.out.println("缴费"); }}

客户端访问代理角色

public class Client { public static void main(String[] args) { Host host = new Host(); //代理 Proxy proxy = new Proxy(host); proxy.rent(); }}

代理模式的好处:

可以使真实角色的操作更加纯粹,不用去关注一些公共的业务公共交给代理角色,实现业务的分工公共业务发生扩展的时候,方便集中管理

缺点:

一个真实角色产生一个代理角色,代码量会翻倍,开发效率会变低 10.2 动态代理

动态代理和静态代理角色一样动态代理的代理类是动态生成的,不是我们直接写好的动态代理分为两大类:

基于接口的动态代理基于类的动态代理

基于接口:JDK动态代理基于类:cglibjava字节码实现:javasist

需要了解两个类:Proxy:代理InvocationHandIer:调用处理程序

动态代理的好处:

可以使真实角色的操作更加纯粹,不用去关注一些公共的业务公共交给代理角色,实现业务的分工公共业务发生扩展的时候,方便集中管理一个动态代理类代理的是一个接口,一般就是对应的一类业务一个动态代理类可以代理多个类,只要实现了同一个接口即可

代码示例:

ProxyInvocationHandIer

import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;public class ProxyInvocationHandIer implements InvocationHandler { //被代理的接口 private Object target; public void setTarget(Object target){ this.target = target; } //生成得到代理类 public Object getProxy(){ return Proxy.newProxyInstance(this.getClass().getClassLoader(),target.getClass().getInterfaces(),this); } //处理代理实例,并返回结果 @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //动态代理的本质,就是使用反射机制 log(method.getName()); Object result = method.invoke(target, args); return result; } public void log(String msg){ System.out.println("执行了"+msg+"方法"); }}

实体类

public interface Rent { public void rent();}

public class Host implements Rent { @Override public void rent() { System.out.println("房东要出租房屋"); }}

客户端

public class Client { public static void main(String[] args) { //真实角色 UserServiceImpl userService = new UserServiceImpl(); //代理角色:现在没有 ProxyInvocationHandIer pih = new ProxyInvocationHandIer(); //通过调用程序处理角色来处理我们要调用的接口对象 pih.setTarget(userService); UserService proxy = (UserService) pih.getProxy(); proxy.add(); }}

11、AOP

使用Spring实现Aop

【重点】使用Aop,需要导入一个依赖包

org.aspectj aspectjweaver 1.9.8.RC3

方式一:使用Spring的API接口

public interface UserService { public void add(); public void delete(); public void update(); public void select();}

public class UserServiceImpl implements UserService{ public void add() { System.out.println("增加一个用户"); } public void delete() { System.out.println("删除一个用户"); } public void update() { System.out.println("修改一个用户"); } public void select() { System.out.println("查找一个用户"); }}

public class Log implements MethodBeforeAdvice { //method:要执行的目标对象的方法 //args:参数 //target:目标对象 public void before(Method method, Object[] args, Object target) throws Throwable { System.out.println(target.getClass().getName()+"的"+method.getName()+"执行了"); }}

public class AfterLog implements AfterReturningAdvice { public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable { System.out.println("执行了"+method.getName()+"方法,返回结果为:"+returnValue); }}

<?xml version="1.0" encoding="UTF-8"?>

public class MyTest { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); //动态代理的是接口 UserService userService = context.getBean("userService", UserService.class); userService.add(); }}

方式二:自定义来实现AOP【主要是切面定义】

public class DiyPointCut { public void before(){ System.out.println("======方法执行前======"); } public void after(){ System.out.println("======方法执行后======"); }}

方式三:使用注解来实现

@Aspectpublic class AnnotationPointCut { @Before("execution(* com.lyd.service.UserServiceImpl.*(..))") public void before(){ System.out.println("======方法执行前======"); } @After("execution(* com.lyd.service.UserServiceImpl.*(..))") public void after(){ System.out.println("======方法执行后======"); } //在环绕增强中,我们可以给定一个参数,代表我们要获取处理切入的点 @Around("execution(* com.lyd.service.UserServiceImpl.*(..))") public void around(ProceedingJoinPoint jp) throws Throwable { System.out.println("环绕前"); Signature signature = jp.getSignature(); //获得签名 System.out.println("signature"+signature); Object proceed = jp.proceed(); //执行方法 System.out.println("环绕后"); }}

12.整合Mybatis 12.1 回忆Mybatis

步骤:

导入相关jar包

junitmybatismysql数据库spring相关的aop织入mybatis-spring

junit junit 4.13.1 mysql mysql-connector-java 8.0.13 org.mybatis mybatis 3.5.8 org.springframework spring-webmvc 5.3.15 org.springframework spring-jdbc 5.3.15 org.aspectj aspectjweaver 1.9.8.RC3 org.mybatis mybatis-spring 2.0.7

编写核心配置文件

<?xml version="1.0" encoding="UTF8" ?>

编写接口

public interface UserMapper { public List selectUser();}

编写Mapper.xml

<?xml version="1.0" encoding="UTF-8" ?> select * from mybatis.user; insert into mybatis.user(id, name, pwd) values (#{id},#{name},#{pwd}) delete from mybatis.user where id = #{id}

public class UserMapperImpl extends SqlSessionDaoSupport implements UserMapper{ public List selectUser() { User user = new User(6, "pp", "1234567"); SqlSession sqlSession = getSqlSession(); UserMapper mapper = sqlSession.getMapper(UserMapper.class); mapper.addUser(user); mapper.deleteUser(6); return mapper.selectUser(); } public int addUser(User user) { return getSqlSession().getMapper(UserMapper.class).addUser(user); } public int deleteUser(int id) { return getSqlSession().getMapper(UserMapper.class).deleteUser(id); }}

Copyright © 2016-2020 www.365daan.com All Rights Reserved. 365答案网 版权所有 备案号:

部分内容来自互联网,版权归原作者所有,如有冒犯请联系我们,我们将在三个工作时内妥善处理。