spring底层机制环境搭建
1.模块创建和依赖引入
聚合模块,下面有一个myspring
查看父模块是否管理了子模块
myspring模块引入基本包
<dependencies> <dependency> <groupid>org.springframework</groupid> <artifactid>spring-context</artifactid> <version>5.3.8</version> </dependency> <dependency> <groupid>org.springframework</groupid> <artifactid>spring-aspects</artifactid> <version>5.3.8</version> </dependency> </dependencies>
2.进行环境搭建
目录概览
usercontroller.java
package com.sunxiansheng.myspring.component; import org.springframework.stereotype.component; /** * description: 就是一个controller组件 * @author sun * @create 2024/8/4 13:53 * @version 1.0 */ @component public class usercontroller { }
userservice.java
package com.sunxiansheng.myspring.component; import org.springframework.beans.factory.annotation.autowired; import org.springframework.stereotype.component; /** * description: 一个service组件 * @author sun * @create 2024/8/4 13:54 * @version 1.0 */ @component public class userservice { /** * 依赖注入userdao */ @autowired private userdao userdao; public void add() { system.out.println("userservice 调用了userdao的add方法"); userdao.add(); } }
userdao.java
package com.sunxiansheng.myspring.component; import org.springframework.stereotype.component; /** * description: 一个dao组件 * @author sun * @create 2024/8/4 13:53 * @version 1.0 */ @component public class userdao { public void add() { system.out.println("userdao add..."); } }
appmain.java
package com.sunxiansheng.myspring; import com.sunxiansheng.myspring.component.usercontroller; import com.sunxiansheng.myspring.component.userdao; import com.sunxiansheng.myspring.component.userservice; import org.springframework.context.applicationcontext; import org.springframework.context.support.classpathxmlapplicationcontext; /** * description: 启动类 * @author sun * @create 2024/8/4 13:59 * @version 1.0 */ public class appmain { public static void main(string[] args) { // 从类路径下加载beans.xml配置文件 applicationcontext ioc = new classpathxmlapplicationcontext("beans.xml"); // 从容器中获取usercontroller对象,这里获取两次,看是否是同一个对象 usercontroller usercontroller1 = (usercontroller) ioc.getbean("usercontroller"); usercontroller usercontroller2 = (usercontroller) ioc.getbean("usercontroller"); system.out.println("usercontroller1 == usercontroller2 ? " + (usercontroller1 == usercontroller2)); // 从容器中获取userservice对象 userservice userservice = (userservice) ioc.getbean("userservice"); system.out.println("userservice = " + userservice); // 从容器中获取userdao对象 userdao userdao = (userdao) ioc.getbean("userdao"); system.out.println("userdao = " + userdao); } }
beans.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" 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 https://www.springframework.org/schema/context/spring-context.xsd"> <!-- 配置自动扫描的包 --> <context:component-scan base-package="com.sunxiansheng.myspring.component"/> </beans>
测试
配置usercontroller.java为多例的,然后测试
userservice调用add方法,然后测试
引入bean后置处理器
1.位置
2.mybeanpostprocessor.java
package com.sunxiansheng.myspring.process; import org.springframework.beans.factory.config.beanpostprocessor; import org.springframework.stereotype.component; /** * description: bean的后置处理器 * @author sun * @create 2024/8/4 14:19 * @version 1.0 */ @component // 将这个类加入到容器中 public class mybeanpostprocessor implements beanpostprocessor { /** * 在每个bean的初始化方法之前执行 * @param bean * @param beanname * @return */ @override public object postprocessbeforeinitialization(object bean, string beanname) { // 这里可以提前对bean进行一些处理 system.out.println("postprocessbeforeinitialization..."+beanname+"=>"+bean.getclass()); return bean; } /** * 在每个bean的初始化方法之后执行 * @param bean * @param beanname * @return */ @override public object postprocessafterinitialization(object bean, string beanname) { system.out.println("postprocessafterinitialization..."+beanname+"=>"+bean.getclass()); return bean; } }
3.userservice.java 设置初始化方法
4.beans.xml配置扫描
5.测试
6.注意事项
- bean的后置处理器在初始化方法调用前后执行
- 触发时机为单例的第一次getbean和多例的每次getbean,也就是,每个bean都会经过bean的后置处理器处理
引入aop
1.目录
2.smartanimal.java
package com.sunxiansheng.myspring.aop; /** * description: smartanimal * @author sun * @create 2024/8/4 14:51 * @version 1.0 */ public interface smartanimal { public float getsum(float a, float b); public float getsub(float a, float b); }
3.smartdog.java
package com.sunxiansheng.myspring.aop; import org.springframework.stereotype.component; /** * description: smartdog * @author sun * @create 2024/8/4 14:51 * @version 1.0 */ @component // 交给spring容器管理 public class smartdog implements smartanimal { @override public float getsum(float a, float b) { system.out.println("smartdog...getsum...res=" + (a + b)); return a + b; } @override public float getsub(float a, float b) { system.out.println("smartdog...getsub...res=" + (a - b)); return a - b; } }
4.smartanimalaspect.java
package com.sunxiansheng.myspring.aop; import org.aspectj.lang.joinpoint; import org.aspectj.lang.proceedingjoinpoint; import org.aspectj.lang.signature; import org.aspectj.lang.annotation.*; import org.aspectj.lang.reflect.methodsignature; import org.springframework.stereotype.component; import java.util.arrays; /** * description: 切面类 * @author sun * @create 2024/8/4 14:53 * @version 1.0 */ @component // 交给spring容器管理 @aspect // 标注这是一个切面类 public class smartanimalaspect { /** * @param joinpoint 保存了要切入的方法的信息 * @before 前置通知 * execution(。。。) 切入表达式,表明要切入的方法,格式:格式:访问修饰符+返回类型 全类名 方法名(参数类型) */ @before(value = "execution(public float com.sunxiansheng.myspring.aop.smartdog.getsub(float, float))") public void before(joinpoint joinpoint) { // 获取方法签名 signature signature = joinpoint.getsignature(); system.out.println("方法执行开始-日志-方法名-" + signature.getname() + "-参数" + arrays.aslist(joinpoint.getargs())); // 还可以获取目标对象,这样就可以反射进行任何操作了 smartdog target = (smartdog) joinpoint.gettarget(); system.out.println("目标对象-" + target.getclass()); } /** * @param joinpoint 保存了要切入的方法的信息 * @afterreturning 返回通知 */ @afterreturning(value = "execution(public float com.sunxiansheng.myspring.aop.smartdog.getsub(float, float))") public void afterreturning(joinpoint joinpoint) { signature signature = joinpoint.getsignature(); system.out.println("方法执行正常结束-日志-方法名-" + signature.getname()); } /** * @param joinpoint * @afterthrowing 异常通知 */ @afterthrowing(value = "execution(public float com.sunxiansheng.myspring.aop.smartdog.getsub(float, float))") public void throwing(joinpoint joinpoint) { signature signature = joinpoint.getsignature(); system.out.println("方法出现异常-日志-方法名-" + signature.getname()); } /** * @param joinpoint * @after 后置通知 */ @after(value = "execution(public float com.sunxiansheng.myspring.aop.smartdog.getsub(float, float))") public void after(joinpoint joinpoint) { signature signature = joinpoint.getsignature(); system.out.println("方法最终执行完毕-日志-方法名-" + signature.getname()); } /** * 环绕通知 * @param joinpoint * @return * @throws throwable */ @around("execution(public float com.sunxiansheng.myspring.aop.smartdog.getsub(float, float))") public object logmethodexecution(proceedingjoinpoint joinpoint) throws throwable { methodsignature signature = (methodsignature) joinpoint.getsignature(); // 获取方法信息 string methodname = signature.getmethod().getname(); string classname = signature.getdeclaringtype().getsimplename(); system.out.println("环绕通知 method " + classname + "." + methodname); // 获取目标对象 object targetobject = joinpoint.gettarget(); // 环绕通知获取目标对象 system.out.println("环绕通知获取目标对象:" + targetobject); try { // 前置通知:环绕通知获取参数 system.out.println("环绕通知获取参数:" + arrays.aslist(joinpoint.getargs())); object result = joinpoint.proceed(); // 执行目标方法 // 返回通知:环绕通知获取结果 system.out.println("环绕通知获取结果:" + result); return result; } catch (exception e) { // 异常通知 throw e; } finally { // 最终通知 system.out.println("环绕通知 method " + classname + "." + methodname); } } }
5.beans.xml开启aop注解并扫描aop包
6.appmain.java 测试aop
6.简单分析aop和后置处理器的关系
3.抛出问题
- 1.bean是怎么注入容器的?
- 2.为什么加了@autowired就能被依赖注入?
- 3.单例多例是怎么实现的?
- 4.bean的后置处理器是怎么实现的?
- 5.原生spring的aop是如何实现的?
4.将代码放到远程仓库
- vcs -》 share
- 查看仓库
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。
发表评论