当前位置: 首页 > web >正文

Spring6学习及复习笔记

1、快速入门认识

通过编写xml配置文件来创建对象,读取bean标签的id值和class值来创建。

之后再通过对象调用相关的方法(这里实际上用到的是反射机制)

对象会存放到Map集合中

大致反射思路如下:(这里只是模拟,并非真的就这几行实现)

 2、整合log4j2日志框架

引入依赖,创建配置文件log4j2.xml    这样便可自动生成日志

手动写日志:
Logger logger=LoggerFactory.getLogger(testUser.class);
logger.info("手动写日志成功了");

 3、IOC

一、IOC容器

IOC即为控制反转,使用IOC容器管理bean对象,设计出更加松耦合的程序

用它来管理对象的实例化和初始化,以及对象间的依赖关系。

对象用Map集合存放

DI,即为依赖注入,实现了控制反转这一思想

一般使用set或构造注入

二、XML管理bean

1、获取bean

<bean  id="user" class="com.iocxml.User"></bean>

ApplicationContext context=new ClassPathXmlApplicationContext(bean.xml);

User user1=(User)context.getBean("user");//根据id获取bean

User user2=(User)context.getBean(User.class);//根据类型获取bean

User user3=(User)context.getBean("user",User.class);//根据id和类型获取bean

注意,获取时指定类型bean只能有一个,如果同一个类有多个bean会报错。

一般都只根据id获取,确保每个bean的id不一样 

这里还可以配置接口的实现类,然后获取对象时通过接口的类名来获取,但实现类必须唯一。

2、setter注入

确保属性有set方法和构造方法

//set注入

<bean id="book"  class="com.book">

<property name="name"  value="图书名称"></property>  

<property name="author"  value="图书作者"></property>

</bean>  

//构造器注入

<bean id="book1"  class="com.book">

<constructor-arg  name="name"   value="图书名称"></constructor-arg>

<constructor-arg  name="author"   value="图书作者"></constructor-arg>

</bean>  

特殊值处理 

  1. 字面量赋值。String  a="33a"
  2. null。    使用标签<null/>
  3. xml实体。     对字符转义   <  :&lt     >:&gt
  4. CDATA节       用来写特殊符号
3、对象类型赋值

//引入外部bean

<bean id="dept"   class="com.dept">

<property  name="dname"   value="部门属性"></property>

</bean>

<bean id="emp"   class="com.emp">

<property name="ename"  value="员工名字"></property>  

<property name="age"  value="50"></property>

<property name="dept"  ref="dept"></property>

</bean>

 //内部bean

<bean id="emp2"   class="com.emp">

<property name="ename"  value="员工名字"></property>  

<property name="age"  value="50"></property>

   <property name="dept" >     

           <bean id="dept2"   class="com.dept">

                <property  name="dname"   value="部门属性"></property>

            </bean>

    </property>

</bean>

 //级联属性赋值(少用)

<bean id="dept3"   class="com.dept">

</bean>        

<bean id="emp3"   class="com.emp">

<property name="ename"  value="员工名字"></property>  

<property name="age"  value="50"></property>

<property name="dept"  ref="dept"></property>

<property  name="dept.dname"   value="部门属性"></property>

</bean>

4、数组类型属性注入

<bean id="dept"   class="com.dept">

<property  name="dname"   value="部门属性"></property>

</bean>

<bean id="emp"   class="com.emp">

<property name="ename"  value="员工名字"></property>  

<property name="age"  value="50"></property>

<property name="dept"  ref="dept"></property>

<property name="hobby"  >

     <array>

     <value>抽烟</value>

    <value>喝酒</value>

     <value>烫头</value>

     </array>

</property>

</bean>

5、集合类型属性注入

 List集合属性注入

<bean id="dept"   class="com.dept">

<property  name="dname"   value="部门属性"></property>

<property  name="empList">

     <list>

       <ref  bean="emp2"></ref>

      </list>

</property>

</bean>

Map集合属性注入 

<bean id="dept"   class="com.dept">

<property  name="dname"   value="部门属性"></property>

<property  name="empMap">

     <map>

       <entry>

         <key>

            <value>1</value>

          </key>

         <ref bean="emp2"></ref>

       </entry>

   </map>

</property>

</bean>

引用集合类型的bean,使用util

 <property  name="empList"  ref="empList"></property>

<util:list  id=empList>

     //里面写集合

       <ref  bean="emp2"></ref>

</util:list>

6、引入外部属性文件

引用依赖,再创建properties文件。

7、bean的作用域

8、bean的生命周期

 

<bean  id="user"  class="com.User"  init-method="initMethod"  destory-method="destoryMethod">

<property  name="name"   value="名字"></property> 

</bean>

销毁用context.close()

//后置处理器使用,要实现BeanPostProcess接口 

9、FactoryBean

 ​​​​​​配置MyFactoryBean会生成User对象

 10、自动注入

三、注解管理bean

1、注解初识

不提供value默认找首字母小写的同类名id

2、Autowired

默认根据类型匹配

@AutoWired                    //属性注入

private    Service   service;

@Autowired                   //set方法注入

public  void setUserController(UserService   userservice) 

{   this.userservice=userservice;}

 @Autowired                   //构造方法注入

public  UserController(UserService   userservice) 

{   this.userservice=userservice;}

                //形参注入

public  UserController( @Autowired   UserService   userservice) 

{   this.userservice=userservice;}

 @AutoWired               

@Qualifier(value="userServiceFirst")        //联合使用,根据名称进行注入

private    Service   service;

3、Resource

 

4、全注解开发

使用配置类来替代配置文件

 四、手写IOC

1、Java反射

Car类

package reflect;public class Car {private String name;private int age;private String color;private void run(){System.out.println("私有方法run......");}public Car() {}public Car(String name, int age, String color) {this.name = name;this.age = age;this.color = color;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public String getColor() {return color;}public void setColor(String color) {this.color = color;}
}

TestCar,获取类并实例化对象

package reflect;import org.junit.Test;public class TestCar {//获取class对象的三种方式@Testpublic void test1() throws Exception {//方式一:调用运行时类的属性.classClass carClass = Car.class;System.out.println(carClass);//方式二:通过运行时类的对象,调用getClass()Class carClass1 = new Car().getClass();System.out.println(carClass1);//方式三:调用Class的静态方法:forName(String classPath)Class carClass2 = Class.forName("reflect.Car");System.out.println(carClass2);//实例化Car car=(Car)carClass.getDeclaredConstructor().newInstance();System.out.println(car);}
}

获取构造方法,并设置对象参数

@Testpublic void test2() throws Exception {Class carClass = Car.class;//获取所有构造方法包括private修饰的Constructor[] constructors=carClass.getDeclaredConstructors();for(Constructor constructor:constructors){System.out.println(constructor);}//    获取指定的构造方法Constructor constructor=carClass.getDeclaredConstructor(    String.class,int.class,String.class);constructor.setAccessible(true);//解除私有限定Car car=(Car)constructor.newInstance("宝马",10,"红色");System.out.println(car);}

获取属性并设置

@Testpublic void test3() throws Exception {//获取所有属性包括private修饰的Class carClass = Car.class;Car car=(Car)carClass.getDeclaredConstructor().newInstance();Field[]  fields=carClass.getDeclaredFields();for(Field field:fields){if(field.getName().equals("name")){field.setAccessible(true);//解除私有限定field.set(car,"奔驰");}//  System.out.println(field);System.out.println(car);}}

获取方法得到返回值

@Testpublic void test4() throws Exception {Car car=new Car("奔驰",10,"红色");Class carClass = car.getClass();Method[] methods=carClass.getDeclaredMethods();for(Method method:methods){if(method.getName().equals("run")){method.setAccessible(true);//解除私有限定method.invoke(car);}else if(method.getName().equals("toString")){method.setAccessible(true);//解除私有限定String str=(String)method.invoke(car);System.out.println(str);}}}
2、手写IOC

创建两个注解,bean和di,分别用于创建对象和注入属性

package com.anno;import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Bean {
}
package com.anno;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Di {
}

实现AnnotationApplicationContext

package com.bean;public interface ApplicationContext {Object getBean(Class clazz);
}
package com.bean;import com.anno.Bean;import java.io.File;
import java.net.URL;
import java.net.URLDecoder;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;public class AnnotationApplicationContext implements ApplicationContext {private  Map<Class,Object> beanMap = new HashMap<>();private  String rootpath;@Overridepublic Object getBean(Class clazz) {return beanMap.get(clazz);}public AnnotationApplicationContext(String basepackage){//把包名转化为路径名String packagepath= basepackage.replaceAll("\\.","\\\\");try {//获取当前线程的类加载器,然后获取所有资源的路径Enumeration<URL> urls=Thread.currentThread().getContextClassLoader().getResources(packagepath);//遍历路径while (urls.hasMoreElements()){//获取路径URL url=urls.nextElement();//解码String FilePath= URLDecoder.decode(url.getFile(),"UTF-8");//获取项目的根路径rootpath=FilePath.substring(0,FilePath.length()-packagepath.length());//加载beanloadBean(new File(FilePath));}}catch (Exception e){e.printStackTrace();}}private void loadBean(File file) throws Exception {//如果是文件夹,就进入文件夹if(file.isDirectory()){//获取文件夹下的所有文件File[] files=file.listFiles();//如果文件夹下没有文件,就返回if(files==null||files.length==0){return;}//遍历文件夹下的所有文件for (File child:files){//如果是文件夹,就递归进入文件夹加载if(child.isDirectory())loadBean(child);else {//如果是文件,就加载bean//获取类的路径String pathwithclass=child.getAbsolutePath().substring(rootpath.length()-1);//如果是class文件,就加载beanif(pathwithclass.contains(".class")){//把路径转化为包名String allname=pathwithclass.replaceAll("\\\\",".").replace(".class","");Class<?> clazz=Class.forName(allname);//不是接口if(!clazz.isInterface()){Bean annotation=clazz.getAnnotation(Bean.class);//是beanif(annotation!=null){Object instance =clazz.getConstructor().newInstance();//是否实现了接口if(clazz.getInterfaces().length>0){beanMap.put(clazz.getInterfaces()[0],instance);}else {beanMap.put(clazz,instance);}}}}}}}}
}

实现service和dao的实现类

package com.dao;import com.anno.Bean;@Bean
public class UserDaoImpl implements UserDao {@Overridepublic void add() {System.out.println("UserDaoImpl add");}}
package com.service;import com.anno.Bean;
import com.anno.Di;
import com.dao.UserDao;@Bean
public class UserServiceImpl implements UserService{@Diprivate UserDao userDao;@Overridepublic void add() {System.out.println("userservice add");}
}

测试:

package com;import com.bean.AnnotationApplicationContext;
import com.bean.ApplicationContext;
import com.service.UserService;import java.net.URL;
import java.util.Enumeration;public class Main {public static void main(String[] args) {ApplicationContext context=new AnnotationApplicationContext("com");UserService userService=(UserService)context.getBean(UserService.class);System.out.println(userService);userService.add();}
}

修改AnnotationApplicationContext代码,增加属性注入 。getbean里增加loadDi()

 private void loadDi(){//遍历beanMapfor (Map.Entry<Class,Object> entry:beanMap.entrySet()){//获取bean的所有属性Object obj=entry.getValue();//获取对象ClassClass<?> clazz=obj.getClass();//获取对象的所有属性Field[] fields=clazz.getDeclaredFields();//遍历属性for (Field field:fields){//判断属性是否有Di注解Di annotation=field.getAnnotation(Di.class);if(annotation!=null){field.setAccessible(true);//如果有Di注解,就注入属性try {field.set(obj,beanMap.get(field.getType()));} catch (IllegalAccessException e) {throw new RuntimeException(e);}}}}}

测试

4、AOP 

一、代理模式

核心代码与日志代码在一起不合理,不利于维护。所以使用代理模式

1、静态代理

再写一个接口的实现类,定义一个核心实现类的对象作为属性,然后同样的方法中去调用,前后增加自己的代码。

但是代码写死了没有具备灵活性。

2、动态代理

public Object getProxy(){//得到类加载器ClassLoader classloader=target.getClasss().getClassLoader();//目标对象实现接口的数组形式Class<?> interfaces=target.getClass().getInterfaces();//设置实现目标方法的过程InvocationHandler invocationhandler= new InvocationHandler(){public Object invoke(Object proxy,Method method,Object[] args)  throws Throwable{
//代理对象、需要重写的方法,方法里面的参数System.out.println("动态代理日志1");Object  result=method.invoke(target,args);System.out.println("动态代理日志2");return result;}};return Proxy.newProxyInstance(classloader,interfaces,invocationhandler);} 

 二、概念

面向切面编程,通过预编译和运行期间动态代理方式实现,在不改变原代码的情况下,给程序动态统一添加额外功能的一种技术。

  1. 横切关注点:各个模块解决同一个问题。如事务、日志都属于横切关注点
  2. 通知:想要增强的功能,比如事务、日志,所实现的方法叫通知方法
  3. 切面:封装通知方法的类。
  4. 目标:目标对象
  5. 代理:代理对象
  6. 连接点:spring允许你使用通知的位置
  7. 切入点:定位连接点的方式

三、注解实现AOP

 

 

切入点表达式:

JoinPoint获得切入点信息

 

切面的优先级用@Order实现

四、xml实现AOP

<aop:config>

  <aop:aspect  ref="logAspect">

    <aop:pointcut  id="pointcut"  expression="execution(* com.*((..))"/>

    <aop:before  method:"beforemethod"  pointcut-ref="pointcut"></aop:before>

  </aop:aspect>

</aop:config> 

http://www.xdnf.cn/news/6918.html

相关文章:

  • flutter 配置 安卓、Ios启动图
  • CoverM:contig/bin的相对丰度计算
  • 数字万用表与指针万用表使用方法及注意事项
  • Redis键(Key)操作完全指南:从基础到高级应用
  • Java-Objects类高效应用的全面指南
  • Animaster:一次由 CodeBuddy 主导的 CSS 动画编辑器诞生记
  • 小型气象站应用之鱼塘养殖方案
  • GitHub文档加载器设计与实现
  • Win11下轻松搭建wiki.js,Docker.desktop部署指南(mysql+elasticsearch+kibana+wiki.js)
  • 国内AWS CloudFront与S3私有桶集成指南:安全访问静态内容
  • 用Python玩转人工智能——数字识别技术 之三
  • React 中,闭包陷阱
  • hadoop.proxyuser.代理用户.授信域 用来干什么的
  • 【目标检测】【Transformer】Swin Transformer
  • JVM 双亲委派机制
  • How to install alibaba font on Linux mint
  • Git 多人协作
  • 系统架构设计(十一):架构风格总结2
  • Java-Collections类高效应用的全面指南
  • 数值分析知识重构
  • 【Redis】List 列表
  • 黑马k8s(十)
  • 如何分析动态采样引起的计划不稳定 | OceanBase SQL 调优实践
  • 2025.05.17淘天机考笔试真题第一题
  • 【时时三省】(C语言基础)字符数组应用举例2
  • 游戏引擎学习第290天:完成分离渲染
  • 一阶线性方程 线性方程
  • JAVA EE_HTTP
  • Python训练营打卡Day28
  • Java二叉树题目练习