① Spring是轻量级的开源的JavaEE框架;
② Spring可以决解企业开发的复杂性;
③ Spring的两个核心部分:IOC 和 Aop;
(1)IOC:控制反转,把创建对象过程交给Spring进行管理。
(2)Aop:面向切面,不修改代码
④ Spring特点:
(1)方便解耦,简化开发;
(2)Aop编程的支持;
(3)方便程序的测试;
(4)方便整合其他框架一起使用;
(5)方便进行事物的操作;
(6)降低API开发难度;
(1)下载Spring5的框架
下载地址:https://repo.spring.io/ui/native/release/org/springframework/spring/
(2)使用Idea创建一个普通Java工程
(3)导入Spring5相关jar包
1.直接从下载好的框架中复制进去;
2.选择导入项目
(4)创建普通的类,普通方法
(5)创建Spring配置文件,在配置文件配置创建对象
Spring配置文件使用.xml格式;
(6)测试代码
什么是IOC:
① 控制反转,把对象创建和对象之间的调用过程,交给Spring进行管理;
② 使用IOC目的:降低耦合度;
底层原理:
① xml解析、工厂模式、反射;
// 第一步&#xff1a;xml配置文件&#xff0c;配置创建对象<!--配置User对象创建--><bean id&#61;"user" class&#61;"com.nzs.spring5.User"></bean>
// 第二步&#xff1a;有servise类和dao类&#xff0c;创建工厂
class UserFactory{public static UserDao getDao(){String classValue &#61; class属性值; // xml解析Class myclass &#61; Class.forName(classValue);// 通过反射创建对象return (UserDao)myclass.newInstance();}
}
① IOC思想基于IOC容器完成&#xff0c;IOC容器底层就是对象工厂&#xff1b;
② Spring提供IOC容器实现的两种方式&#xff1a;&#xff08;两个接口&#xff09;&#xff08;1&#xff09;
BeanFactory
&#xff1a;是Spring内部使用的接口&#xff0c;不提供开发人员使用。加载配置文件时候不会创建对象&#xff0c;在获取对象(使用)才会去创建对象。&#xff08;2&#xff09;
ApplicationContext
&#xff1a;是BeanFactory接口的子接口&#xff0c;提供了更多更强大的功能&#xff0c;一般由开发人员使用。加载配置文件时就会把配置文件对象进行创建。
&#xff08;3&#xff09;ApplicationContext接口的实现类&#xff1a;ClassPathXmlApplicationContext (项目路径)和FileSystemXmlApplicationContext(盘符路径)。
什么是Bean管理&#xff1a; Bean管理指两个操作&#xff0c;Spring创建对象 和 Spring注入属性。
Bean管理的两种方式&#xff1a; 基于xml配置文件方式实现&#xff0c;基于注解方式实现。
两种Bean
&#xff1a;普通bean&#xff0c;工厂Bean
普通Bean&#xff1a;在配置文件中定义Bean类型就是返回类型&#xff1b;
工厂Bean&#xff1a;在配置文件中定义Bean类型可以和返回值类型不一样&#xff1b;
1. 基于xml方式创建对象&#xff1a;
① 默认执行无参的构造方法&#xff1b;
2. 基于xml方式注入属性&#xff1a;
① DI&#xff1a;依赖注入&#xff0c;就是注入属性&#xff1b;
第一种
&#xff1a;使用set方法进行注入&#xff1b;1.创建属性、创建属性set方法;
2.在spring配置文件中配置对象创建&#xff0c;配置属性注入&#xff1b;
<bean id&#61;"user" class&#61;"com.nzs.spring5.User"><property name&#61;"myname" value&#61;"宁"></property></bean>
第二种
&#xff1a;有参构造进行注入&#xff1b;1.声明属性、声明有参构造方法;
2.在spring配置文件中配置对象创建&#xff0c;配置属性注入&#xff1b;
<bean id&#61;"user" class&#61;"com.nzs.spring5.User"><constructor-arg name&#61;"myname" value&#61;"宁"></constructor-arg></bean>
第三种
&#xff1a;p命名空间进行注入&#xff1b;
添加&#xff1a;xmlns:p&#61;"http://www.springframework.org/schema/p"
<bean id&#61;"user" class&#61;"com.nzs.spring5.User" p:myname&#61;"宁"></bean>3. 基于xml方式注入
其他类型
的属性&#xff1a;
①自变量
1.null值&#xff1a;
2.属性值中包含特殊字符&#xff1a;
②
注入属性 - 外部bean
1.创建两个类&#xff0c;service类和dao类&#xff1b;
2.在service类中调用dao中的方法&#xff1b;
3.在spring配置文件中进行配置&#xff1b;
③
注入属性 - 内部bean
1.一对多关系&#xff1a;部门与员工&#xff1b;
2.在实体类之间表示一对多的关系&#xff1b;
3.在spring配置文件中进行配置&#xff1b;
④
注入属性 - 级联赋值
⑤注入数组类型属性
⑥注入List集合类型属性
⑦注入Map集合类型属性
⑧注入Set集合类型属性
4. 在集合里面设置对象类型值&#xff1a;
5. 把集合注入部分提取出来&#xff1a;(1) 在spring配置文件中引入名称空间util&#xff1b;
&#xff08;2&#xff09;使用util标签完成list集合注入提取
步骤&#xff1a;
&#xff08;1&#xff09;创建类&#xff0c;让这个类作为工厂bean&#xff0c;实现接口FactoryBean
&#xff1b;
&#xff08;2&#xff09;实现接口里面的方法&#xff0c;在实现的方法中返回自己想要的Bean类型&#xff1b;
1. 单实例和多实例&#xff1a;
① 默认情况下是单实例&#xff0c;通过设置bean标签中的scope
属性来设置单实例和多实例&#xff0c;sinleton
为单实例&#xff0c;prototype
为多实例。
② scope为sinleton时&#xff0c;加载配置文件时就会创建单实例对象&#xff1b;scope为prototype时&#xff0c;在调用getBean方法时才会创建多实例对象。
① 通过构造器创建bean实例&#xff08;无参构造&#xff09;&#xff1b;
② 为bean的属性设置值 或者 对其他bean引用&#xff08;调用set方法&#xff09;&#xff1b;
③ 初始化之前&#xff0c;把bean实例传递bean后置处理器的方法postProcessBeforeInitialization
&#xff1b;
④ 调用bean的初始化方法&#xff08;需要进行配置初始化方法&#xff1a;init-method
属性&#xff09;&#xff1b;
⑤ 初始化之后&#xff0c;把bean实例传递bean后置处理器方法postProcessAfterInitialization
&#xff1b;
⑥ bean可以使用了&#xff1b;
⑦ 当容器关闭时&#xff0c;调用bean的销毁方法&#xff08;需要进行配置销毁方法&#xff1a;destroy-method
属性 &#43; 手动调用context.close()
&#xff09;;配置后置处理器&#xff1a;
根据指定的装配规则(属性名称或者属性类型)&#xff0c;spring自动将匹配的属性进行注入。
① 根据属性名称注入(
byName
)&#xff1a;注入值bean的id值和类型属性值一样&#xff1b;
② 根据属性类型注入(byType
)&#xff1a;多个相同类型bean就会出错&#xff1b;
① 注解可以作用在类、方法、属性上面&#xff1b;
② 注解的作用&#xff1a;简化xml配置
注&#xff1a;四个注解的功能都是一样的&#xff0c;都可以用来创建对象。
&#64;Component
&#xff0c;&#64;Service
&#xff0c;&#64;Controll
&#xff0c;&#64;Repository
步骤&#xff1a;
① 引入依赖 - spring-aop-5.2.6.RELEASE.jar&#xff1b;
② 开启组件扫描&#xff1b;
③ 使用注解创建对象
// value值可以不写&#xff0c;默认值为类名首字母小写
&#64;Component(value &#61; "userService") // 等价与 &#61;
public class UserService {private String uName;public void add(){System.out.println("service add -----------------");>}
}
&#64;Autowired
&#xff1a;根据属性类型注入&#xff1b;
&#64;Qualifier
&#xff1a;根据属性名称注入&#xff0c;和&#64;Autowired一起使用(以防同一个类型有多个对象&#xff0c;而找不到)&#xff1b;
&#64;Resource
&#xff1a;可根据类型注入&#xff0c;也可根据名称注入&#xff1b;
&#64;Value
&#xff1a;注入普通数据类型&#xff1b;
① 创建配置类&#xff0c;代替xml配置文件&#xff1b;
&#64;Configuration //作为配置类&#xff0c;代替xml配置文件
&#64;ComponentScan(basePackages &#61; {"com.nzs.spring5"})// 替换
public class SpringConfig {
}② 测试
&#64;Testpublic void test2(){// 加载配置类ApplicationContext context &#61; new AnnotationConfigApplicationContext(SpringConfig.class);UserService userService &#61; context.getBean("userService", UserService.class);userService.add();}
① 面向切面编程&#xff0c;利用AOP可以对业务逻辑的各个部分进行隔离&#xff0c;从而使得业务逻辑各个部分之间的耦合度降低&#xff0c;提高程序的可重用性&#xff0c;同时提高开发效率。
Aop术语&#xff1a;
① 连接点&#xff1a;类里面哪些方法可以被增强&#xff0c;这些方法称为连接点&#xff1b;
② 切入点&#xff1a;实际被增强的方法&#xff0c;称为切入点&#xff1b;
③ 通知(增强)&#xff1a;实际增强的逻辑部分称为通知(5种)&#xff1b;
④ 切面&#xff1a;把通知应用到切入点过程&#xff1b;
5种通知&#xff1a;
① 前置通知&#xff1a;
② 后置通知&#xff1a;
③ 环绕通知&#xff1a;
④ 异常通知&#xff1a;
⑤ 最终通知&#xff1a;
Aop底层使用动态代理两种方法&#xff1a;
① 有接口&#xff0c;使用JDK动态代理&#xff1b;创建接口类代理对象&#xff0c;增强类的方法。
② 没有接口&#xff0c;使用CGLIB动态代理&#xff1b;创建子类的代理对象&#xff0c;增强类的方法。
JDK动态代理&#xff1a;
① 使用Proxy类里面的方法创建代理对象。调用newProxyInstance
&#xff1b;
第一个参数&#xff1a;类加载器&#xff1b;
第二个参数&#xff1a;增强方法所在的类&#xff0c;这个类实现的接口&#xff0c;支持多个接口&#xff1b;
第三个参数&#xff1a;实现这个接口InvocationHandler&#xff0c;创建代理对象&#xff0c;写增强方法&#xff1b;
② 实现代码&#xff1a;创建接口 ----> 创建类实现接口 ----> 使用Proxy类创建接口代理对象&#xff1b;
public class JDKProxy {public static void main(String []args){// 创建接口实现类代理对象Class[] interfaces &#61; {UserDao.class};UserDaoImpl temp_userDao &#61; new UserDaoImpl();UserDao userDao &#61; (UserDao)Proxy.newProxyInstance(JDKProxy.class.getClassLoader(), interfaces, new UserDaoProxy(temp_userDao));userDao .update("战胜");}
}class UserDaoProxy implements InvocationHandler{private Object obj;public UserDaoProxy(Object obj){this.obj &#61; obj;}&#64;Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {// 在方法之前 --增强System.out.println("在方法之前&#xff1a;" &#43; method.getName() &#43; "传递参数&#xff1a;"&#43; Arrays.toString(args));// 被增强的方法执行Object res &#61; method.invoke(obj,args);// 在方法之后 -- 增强System.out.println("在方法之后 -- 增强-");return res;}
}
Spring框架一般都是基于AspectJ实现AOP操作&#xff1b;AspectJ不是Sprnig组成部分&#xff0c;独立于AOP框架&#xff1b;
两种方式&#xff1a;基于xml配置文件实现、基于注解方式实现。
切入点表达式&#xff1a;
① 切入点作用&#xff1a;知道对哪个类里面的哪个方法进行增强&#xff1b;
② 语法结构&#xff1a;execution([权限修饰符][返回值类型][类全路径][方法名称]([参数列表]))
&#xff1b;
// 举例1&#xff1a;对com.nzs.dao.BookDao类里面的add方法进行增强&#xff1b;
execution(* com.nzs.dao.BookDao.add(..))
// 举例2&#xff1a;对com.nzs.dao.BookDao类里面的所有方法进行增强&#xff1b;
execution(* com.nzs.dao.BookDao.*(..))
// 举例3&#xff1a;对com.nzs.dao包下所有类中的所有方法进行增强&#xff1b;
execution(* com.nzs.dao.*.*(..))
① 创建类&#xff0c;定义需要增强的方法&#xff1b;
② 创建增强类(编写增强逻辑)&#xff1b;
③ 进行通知配置&#xff1b;
&#xff08;1&#xff09;在配置文件中开启注解扫描&#xff1b;
&#xff08;2&#xff09;使用注解创建User和UserProxy对象&#xff1b;
&#xff08;3&#xff09;在增强类添加注解&#64;Aspect&#xff1b;
&#xff08;4&#xff09;在spring配置文件中开启生成代理对象&#xff1b;
④ 配置不同类型的通知&#xff0c;在增强类里面&#xff0c;在作为通知方法上添加通知类型注解&#xff0c;使用切入表达式配置&#xff1b;
执行user.add()方法
当多个增强类对同一个方法进行增强时&#xff0c;可以在增强类上添加注解&#64;Order(值)
来设置执行顺序。
不同通知&#xff1a;
① &#64;Before&#xff1a;前置通知
② &#64;AfterReturning&#xff1a;返回通知
③ &#64;After&#xff1a;最终通知
④ &#64;AfterThrowing&#xff1a;异常通知
⑤ &#64;Around&#xff1a;环绕通知
相同切入点抽取&#xff1a;
① 创建增强类 和 被增强类&#xff0c;声明方法&#xff1b;
② 在spring配置文件中创建两个类对象&#xff1b;
③ 在spring配置文件中配置切入点&#xff1b;
<!-- 创建两个类对象 -->
<bean id&#61;"user" class&#61;"com.nzs.spring5.aopanon.User"></bean>
<bean id&#61;"userProxy" class&#61;"com.nzs.spring5.aopanon.UserProxy"></bean>
<!-- 配置aop增强 -->
<aop:config><!--切入点--><aop:pointcut id&#61;"p1" expression&#61;"execution(* com.nzs.spring5.aopanon.User.add(..))"/><!--切面--><aop:aspect ref&#61;"userProxy"><!--增强作用在具体的方法上--><aop:before method&#61;"before" pointcut-ref&#61;"p1"/></aop:aspect>
</aop:config>
四、JdbcTemplate
五、事物管理
六、Spring5新特性
后续内容&#xff1a;Spring5框架学习总结【JdbcTemplate、事物管理、Spring5新特性】