Spring
2020-12-27 22:31
标签:jdk动态代理 参数 prope itext 层次结构 password 签名 roo 名称查找 目的:解决企业应用开发的复杂性 功能:使用基本的JavaBean代替EJB,并提供了更多的企业应用功能 范围:任何Java应用 优点: 总结:Spring是一个轻量级控制反转(IoC)和面向切面(AOP)的容器框架 官方文档 下载地址 github地址 Maven仓库: Spring框架是一个分层架构,由7个定义好的模块组成,Spring模块构建在核心容器之上,核心容器定义了创建、配置和管理bean的方式 组成Spring框架的每个模块(或组件)都可以单独存在,或者与其他一个或多个模块联合实现,每个模块的功能如下: Spring core:核心容器提供Spring框架的基本功能,核心容器的主要组件是BeanFactory,它是工厂模式的实现。BeanFactory使用控制反转(IOC) 模式将应用程序的配置和依赖性规范与实际的应用程序代码分开 Spring context:Spring context是一个配置文件,向Spring框架提供上下文信息,Spring context包括企业服务,例如JNDI、EJB、电子邮件、国际化、校验和调度功能 Spring DAO:JDBC DAO抽象层提供了有意义的异常层次结构,可用该结构来管理异常处理和不同数据库供应商抛出的错误消息,异常层次结构简化了错误处理,并且极大地降低了需要编写的异常代码数量(例如打开和关闭连接)。Spring DAO的面向JDBC的异常遵从通用的DAO异常层次结构 Spring AOP:通过配置管理特性,Spring AOP模块直接将面向切面的编程功能,集成到了Spring框架中,所以,可以很容易地使Spring框架管理任何支持AOP的对象。Spring AOP模块为基于Spring的应用程序中的对象提供了事务管理服务,通过使用Spring AOP,不用依赖组件,就可以将声明性事务管理集成到应用程序中 Spring ORM:Spring框架插入了若干个ORM框架,从而提供了ORM的对象关系工具,其中包括JDO、Hibernate 和iBatis SQL Map。所有这些都遵从Spring的通用事务和DAO异常层次结构 Spring WEB:Web上下文模块建立在应用程序上下文模块之上,为基于Web的应用程序提供了上下文,所以,Spring框架支持与Jakarta Struts的集成。Web模块还简化了处理多部分请求以及将请求参数绑定到域对象的工作 Spring MVC:MVC框架是一个全功能的构建Web应用程序的MVC实现。通过策略接口,MVC框架变成为高度可配置的,MVC容纳了大量视图技术,其中包括JSP、Velocity、Tiles、iText和POI 因为现在大多数公司都在使用SpringBoot进行快速开发,学习SpringBoot的前提, 需要完全掌握Spring及SpringMVC,承上启下的作用 弊端:发展了太久之后,违背了原来的理念,配置十分繁琐,人称:”配置地狱” UserDao接口 UserDaoImpl实现类 UserService业务接口 UserServiceImpl实现类 注:之前的业务中,用户的需求可能会影响原来的代码,需要根据用户的需求去修改原代码,如果程序代码量十分大,修改一次的成本代价十分昂贵 解决:使用一个set接口实现 总结:这种思想,从本质上解决了问题,程序猿不用再去管理对象的创建了,系统的耦合性大大降低,可以更加专注的在业务的实现上,这是IOC思想的原型 控制反转loC(Inversion of Control),是一种设计思想,DI(依赖注入)是实现loC的一种方法 没有loC的程序中, 我们使用面向对象编程,对象的创建与对象间的依赖关系完全硬编码在程序中,对象的创建由程序自己控制,控制反转后将对象的创建转移给第三方,个人认为所谓控制反转就是:获得依赖对象的方式反转了 采用XML方式配置Bean的时候,Bean的定义信息是和实现分离的,而采用注解的方式可以把两者合为一体,Bean的定义信息直接以注解的形式定义在实现类中,从而达到了零配置的目的 控制反转是一种通过描述(XML或注解)并通过第三方去生产或获取特定对象的方式,在Spring中实现控制反转的是IoC容器,其实现方法是依赖注入(Dependency Injection,DI) 编写实体类(重点set方法) 编写配置文件 测试 Hello对象是谁创建的? hello对象是由Spring创建的 Hello对象的属性是怎么设置的? hello对象的属性是由Spring容器设置的 这个过程就叫控制反转: 总结:IOC思想就是对象由Spring来创建,管理,装配!不用在程序中去改动了,要实现不同的操作,只需要在xml配置文件中进行修改 默认使用无参构造创建,如果实体类中没有无参构造方法,则会报错 No default constructor found; 使用下标赋值 数据类型赋值 属性名称赋值 总结:在配置文件加载的时候,容器中管理的对象就已经初始化了 作用:一般用于团队开发使用,可以将多个配置文件,导入合并为一个 使用无参构造或者有参构造注入 依赖注入:set注入 环境搭建: 复杂类型 真实测试对象 applicationContext.xml 测试 总结:用的比较多的就是普通注入和引用注入 可以使用p命名空间和c命名空间注入 使用: 测试: 总结:p命名空间和c命名空间可以直接使用,需要导入约束 singleton 单例模式(Spring默认机制):每次从容器get的都是同一个对象 prototype原型模式:每次从容器中get的时候,都会产生一个新的对象 其余的request、session、application、websocket这些都只能在web开发中使用到 注: 除了byName和byType自动装配方式,Spring还支持注解自动装配 导入context约束 开启注解支持 在实体类添加注解 扩展: 总结: @Resource,相当于@Autowired和@Qualifier的组合体 @Autowired和@Resouce的区别: 它们的作用相同都是用注解方式注入对象,但执行顺序不同,@Autowired先byType,@Resource先byName 为什么要学习代理模式,因为AOP的底层机制就是动态代理 代理模式的定义:给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用 学习aop之前 , 我们要先了解一下代理模式 代理模式: 静态代理角色分析 代码实现 Rent.java即抽象角色 Host.java即真实角色 Proxy.java即代理角色 Client.java即客户 流程分析:在这个过程中,客户直接接触的就是中介,就如同现实生活中的样子,客户看不到房东,但是客户通过代理依旧租到了房东的房子,这就是所谓的代理模式,程序源自于生活,所以学编程的人,一般能够更加抽象的看待生活中发生的事情 静态代理优点: 静态代理缺点: 我们想要静态代理的好处,又不想要静态代理的缺点,所以 , 就有了动态代理 练习步骤: 创建一个抽象角色 真实角色完成增删改查操作 需求来了,需要增加一个日志功能,怎么实现? 代理角色来处理日志 测试访问类 理解思想:在不改变原来的代码的情况下,实现了对原有功能的增强,这是AOP中最核心的思想 **JDK的动态代理需要了解两个类:InvocationHandler和Proxy ** InvocationHandler:调用处理程序 Proxy : 代理 代码实现 Rent.java即抽象角色 Host.java即真实角色 ProxyInvocationHandler.java即代理角色 Client.java即客户 使用动态代理实现代理UserService添加日志功能 测试 静态代理有的它都有,静态代理没有的,它也有 面向切面编程(Aspect Oriented Programming,缩写为:AOP),通过预编译方式和运行期间动态代理实现程序功能的统一维护的一种技术 AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型 利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率 提供声明式事务,允许用户自定义切面 SpringAOP中,通过Advice定义横切逻辑,Spring中支持5种类型的Advice: 即AOP在不改变原有代码的情况下,去增加新的功能 使用AOP织入,需要导入一个依赖包 创建切面:BeforeLog.java applicatContext.xml 测试 自定义切面类,DiyPointCut.java applicatContext.xml 测试 自定义切面类,AnnotationPointCut.java applicatContext.xml 测试 Spring 标签:jdk动态代理 参数 prope itext 层次结构 password 签名 roo 名称查找 原文地址:https://www.cnblogs.com/thetree/p/Spring.htmlSpring
Spring简介
什么是Spring?
如何获得Spring?
Spring七大组成模块
扩展
IOC理论推导
理论推导
private UserDao userDao;
//利用set进行动态实现值的注入
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
public void getUser() {
userDao.getUser();
}
IOC本质
HelloSpring
编写HelloSpring
package com.believe.pojo;
public class Hello {
private String str;
public String getStr() {
return str;
}
public void setStr(String str) {
this.str = str;
}
@Override
public String toString() {
return "Hello{" +
"str=‘" + str + ‘\‘‘ +
‘}‘;
}
}
public static void main(String[] args) {
//获取ApplicationContext,拿到Spring容器,参数可以是多个
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
//在容器中获取到对象(bean),参数为对象的id,也就是通过id获取对象
Hello hello = (Hello) context.getBean("hello");
System.out.println(hello);
}
思考问题?
分析总结
控制:谁来控制对象的创建,传统应用程序的对象是由程序本身控制创建的,使用Spring后,对象的是由Spring来创建的
反转:程序本身不创建对象,变成被动的接收对象
依赖注入:就是利用set方法来进行注入的
IOC是一种编程思想,由主动的编程变成被动的接收
IOC创建对象的方式
使用无参构造创建
使用有参构造方法
Spring配置
alias:取别名
bean
import
依赖注入
构造器注入
set方式注入(重点)
package com.believe.pojo;
public class Address {
private String address;
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "Address{" +
"address=‘" + address + ‘\‘‘ +
‘}‘;
}
}
package com.believe.pojo;
import java.util.*;
public class Student {
private String name;
private Address address;
private String[] books;
private List
package com.believe.test;
import com.believe.pojo.Student;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class SpringTest {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
Student student = (Student) context.getBean("student");
System.out.println(student);
/*Student{
name=‘坤坤‘,
address=Address{address=‘郑州‘},
books=[红楼梦, 水浒传, 西游记],
hobbies=[唱, 跳, rap, 篮球],
card={学生卡=20200520, 身份证=66666666},
games=[cf, dnf, lol],
girlfriend=‘null‘,
info={password=123456, username=root}}
*/
}
}
拓展方式注入
@Test
public void test(){
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
User user1 = context.getBean("user1", User.class);
System.out.println(user\.toString());
User user2 = context.getBean("user2", User.class);
System.out.println(user2.toString());
}
xmlns:p="http://www.springframework.org/schema/p"
xmlns:c="http://www.springframework.org/schema/c"
bean的作用域
bean的自动装配
环境搭建
package com.believe.pojo;
public class People {
private Cat cat;
private Dog dog;
private String name;
public Cat getCat() {
return cat;
}
public void setCat(Cat cat) {
this.cat = cat;
}
public Dog getDog() {
return dog;
}
public void setDog(Dog dog) {
this.dog = dog;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "People{" +
"cat=" + cat +
", dog=" + dog +
", name=‘" + name + ‘\‘‘ +
‘}‘;
}
}
手动装配
byName自动装配
byType自动装配
使用注解实现自动装配
@Autowired注解
@Autowired
private Cat cat;
@Autowired
private Dog dog;
@Resouce注解
@Resource
private Cat cat;
@Resource
private Dog dog;
总结
代理模式
静态代理
package com.believe.proxy;
//抽象角色:出租
public interface Rent {
public void rentHouse();
}
package com.believe.proxy;
//真实角色:房东
public class Host implements Rent {
public void rentHouse() {
System.out.println("房东出租房子");
}
}
package com.believe.proxy;
//代理角色:中介
public class Proxy implements Rent {
private Host host;
public Proxy() {
}
public Proxy(Host host) {
this.host = host;
}
public void rentHouse() {
helpHost();
host.rentHouse();
visitHouse();
agencyFee();
}
//托管中介
public void helpHost() {
System.out.println("中介帮助房东");
}
//客户看房
public void visitHouse() {
System.out.println("带客户看房子");
}
//付中介费
public void agencyFee() {
System.out.println("中介收中介费");
}
}
package com.believe.proxy;
//客户,一般客户去找代理
public class Client {
public static void main(String[] args) {
//房东出租房子
Host host = new Host();
//中介帮助房东
Proxy proxy = new Proxy(host);
//找中介租房子
proxy.rentHouse();
}
}
静态代理深入理解
package com.believe.dynamicProxy;
//抽象角色:增删改查业务
public interface UserService {
public void add();
public void del();
public void set();
public void get();
}
package com.believe.dynamicProxy;
//真实角色:完成增删改查操作的实现类
public class UserServiceImpl implements UserService {
public void add() {
System.out.println("添加用户");
}
public void del() {
System.out.println("删除用户");
}
public void set() {
System.out.println("修改用户");
}
public void get() {
System.out.println("查询用户");
}
}
package com.believe.dynamicProxy;
//代理角色:增加日志的实现
public class UserServiceProxy implements UserService {
private UserServiceImpl userServiceImpl;
public UserServiceProxy() {
}
public void setUserServiceImpl(UserServiceImpl userServiceImpl) {
this.userServiceImpl = userServiceImpl;
}
public void add() {
log("add");
userServiceImpl.add();
}
public void del() {
log("del");
userServiceImpl.del();
}
public void set() {
log("set");
userServiceImpl.set();
}
public void get() {
log("get");
userServiceImpl.get();
}
private void log(String msg) {
System.out.println("执行了"+msg+"方法");
}
}
package com.believe.dynamicProxy;
//客户:通过代理角色实现日志添加
public class Client {
public static void main(String[] args) {
//真实角色
UserServiceImpl userServiceImpl = new UserServiceImpl();
//代理角色
UserServiceProxy userServiceProxy = new UserServiceProxy();
userServiceProxy.setUserServiceImpl(userServiceImpl);
userServiceProxy.add();
userServiceProxy.del();
userServiceProxy.set();
userServiceProxy.get();
}
}
动态代理
InvocationHandler是由代理实例调用处理程序实现的接口 每个代理实例都有一个关联的调用处理程序,当在代理实例上调用方法时,调用的方法进行编码并分派其调用处理程序的invoke方法
//在代理实例上处理方法调用,并返回结果
//当在与它关联的代理实例上调用方法时,该方法将在调用处理程序上调用此方法
invoke(Object proxy, Method method, Object[] args)
//proxy,调用该方法的代理实例
//method,此方法对应调用代理实例上的接口的实例方法,对象的声明类将是该方法声明的接口,它可以是代理类继承该方法的代理接口的超级接口
//args,包含在方法上通过代理实例调用的实参的值、对象的数组或null,如果接口方法不需要参数,原始类型的实参是包裹在适当的原始包装类的实例,如java.lang.Integer或java.lang.Boolean
Proxy提供了创建动态代理类实例的静态方法,也是所有动态代理类的父类的方法创建
每个代理实例有一个关联的调用处理程序对象,它实现了接口InvocationHandler
//创建由指定的类加载器定义的代理类的指定调用处理程序的代理实例,并实现指定的接口
newProxyInstance(ClassLoader loader, 类>[] interfaces, InvocationHandler h)
//loader,类装载器来定义代理类
//interfaces,为代理类实现的接口列表
//h,调用处理程序进行方法调用
package com.believe.dynamicProxy;
//抽象角色:出租
public interface Rent {
public void rentHouse();
}
package com.believe.dynamicProxy;
//真实角色:房东
public class Host implements Rent {
public void rentHouse() {
System.out.println("房东出租房子");
}
}
package com.believe.dynamicProxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class ProxyInvocationHandler implements InvocationHandler {
//被代理的接口
private Rent rent;
public void setRent(Rent rent) {
this.rent = rent;
}
//生成代理类,重点是第二个参数,获取要代理的抽象角色,之前都是一个角色,现在可以代理一类角色
public Object getProxy(){
return Proxy.newProxyInstance(this.getClass().getClassLoader(),rent.getClass().getInterfaces(),this);
}
//proxy,调用该方法的代理实例
//method,此方法对应调用代理实例上的接口的实例方法
//处理代理实例,并返回结果
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
helpHost();
//动态代理本质使用反射机制实现
Object result = method.invoke(rent, args);
visitHouse();
agencyFee();
return result;
}
//托管中介
public void helpHost() {
System.out.println("中介帮助房东");
}
//客户看房
public void visitHouse() {
System.out.println("带客户看房子");
}
//付中介费
public void agencyFee() {
System.out.println("中介收中介费");
}
}
package com.believe.dynamicProxy;
public class Client {
public static void main(String[] args) {
//真实角色
Host host = new Host();
//代理角色,不存在
ProxyInvocationHandler pih = new ProxyInvocationHandler();
//通过调用代理程序处理要调用的接口对象
pih.setRent(host);//设置要代理的对象
//动态生成代理类
Rent proxy = (Rent) pih.getProxy();
proxy.rentHouse();
}
}
动态代理深入了解
package com.believe.proxyInvocationHandler;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class ProxyInvocationHandler 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);
}
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+"方法");
}
}
package com.believe.proxyInvocationHandler;
import com.believe.staticProxy.UserService;
import com.believe.staticProxy.UserServiceImpl;
public class Client {
public static void main(String[] args) {
//真实角色
UserServiceImpl userServiceImpl = new UserServiceImpl();
//代理角色,不存在
ProxyInvocationHandler pih = new ProxyInvocationHandler();
//设置要代理的对象
pih.setTarget(userServiceImpl);
//动态生成代理类
UserService proxy = (UserService) pih.getProxy();
proxy.add();
proxy.del();
proxy.set();
proxy.get();
}
}
动态代理的好处
AOP
什么是AOP?
AOP在Spring中的作用
通知类型
连接点
Before前置通知
方法执行开始前执行
After后置通知
方法执行结束后执行
AfterReturning返回通知
方法正常执行之后执行的代码
AfterThrowing异常通知
方法抛出异常时
Around环绕通知
方法执行开始前和结束后执行
使用Spring实现AOP
方式一:使用Spring的接口
package com.believe.log;
import org.springframework.aop.MethodBeforeAdvice;
import java.lang.reflect.Method;
public class BeforeLog implements MethodBeforeAdvice {
//method,要执行的目标对象的方法
//objects,参数
//o,目标对象
public void before(Method method, Object[] objects, Object o) throws Throwable {
System.out.println(o.getClass().getName()+"的"+method.getName()+"方法被执行了");
}
}
package com.believe.test;
import com.believe.service.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class SpringTest {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
//动态代理代理的是接口:注意点
UserService userServiceImpl = context.getBean("userServiceImpl", UserService.class);
userServiceImpl.add();
userServiceImpl.del();
userServiceImpl.set();
userServiceImpl.get();
}
}
方式二:自定义切面实现AOP
package com.believe.diy;
public class DiyPointCut {
public void before() {
System.out.println("===方法前===");
}
public void after() {
System.out.println("===方法后===");
}
}
package com.believe.test;
import com.believe.service.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class SpringTest {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
//动态代理代理的是接口:注意点
UserService userServiceImpl = context.getBean("userServiceImpl", UserService.class);
userServiceImpl.add();
userServiceImpl.del();
userServiceImpl.set();
userServiceImpl.get();
}
}
方式三:使用注解实现AOP
package com.believe.anno;
//方式三:使用注解方式实现AOP
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
//标注这是一个切面
@Aspect
public class AnnotationPointCut {
@Before("execution(* com.believe.service.UserServiceImpl.*(..))")
public void before(){
System.out.println("==方法前==");
}
@After("execution(* com.believe.service.UserServiceImpl.*(..))")
public void after() {
System.out.println("==方法后==");
}
//在环绕增强中,可以给定一个参数,代表要处理切入的点
@Around("execution(* com.believe.service.UserServiceImpl.*(..))")
public void around(ProceedingJoinPoint pj) throws Throwable {
System.out.println("环绕前");
//执行方法
Object proceed = pj.proceed();
System.out.println("环绕后");
/*获得签名
Signature signature = pj.getSignature();
System.out.println(signature);
System.out.println(proceed);*/
}
}
package com.believe.test;
import com.believe.service.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class SpringTest {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
//动态代理代理的是接口:注意点
UserService userServiceImpl = context.getBean("userServiceImpl", UserService.class);
userServiceImpl.add();
}
}