Spring学习

发布时间:2024-12-22 04:07

学习Java的Spring框架,有助于软件开发人员取得相关认证 #生活技巧# #工作学习技巧# #职业技能认证#

IOC控制反转,依赖注入

IOC解释:对象依赖的对象获取的方式被反转了,以前是自己new,现在是ioc容器注入给我们使用

一,内容说明

1.实现@Service注解和@Autowired(其他@controller @compent等等注解原理一样,只是将类注入到spring容器)

2.问题:如何创建自定义注解

3.问题:如何在框架启动时加载标有注解的类和属性(@Autowired标注在类的属性上)

二,原理说明

1.jdk1.4之后新增注解功能 关键字@interface

2.在spring框架启动时,扫(项目路径下)所有的包,循环遍历所有类,使用反射获取类是否有注解@Service,如果有,则使用反射newInstance该类的实例,并将类名和类的实例存放在全局变量Map集合中

3.如果类的属性上有@Autowired,从全局变量Map获取该属性对应的实例,使用反射技术给类的该属性赋值field.set(object, newBean);

三,源码

1.自定义注解,名称可以自定义,一般为ExtAutowired 表示自己扩展的注解

package com.huajie.spring.annotation;

import java.lang.annotation.ElementType;

import java.lang.annotation.Retention;

import java.lang.annotation.RetentionPolicy;

import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)

@Target({ ElementType.CONSTRUCTOR, ElementType.FIELD, ElementType.METHOD })

public @interface XwfAutowired {

}

package com.huajie.spring.annotation;

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 XwfService {

String value() default "";

}

2.ExtClassPathXmlApplicationContext 为了方便这里不模拟spring启动过程,这是核心类

package com.huajie.spring.ext;

import java.lang.reflect.Field;

import java.util.List;

import com.huajie.spring.annotation.XwfAutowired;

import com.huajie.spring.annotation.XwfService;

import com.huajie.utils.ClassUtil;

import java.util.concurrent.ConcurrentHashMap;

import org.apache.commons.lang.StringUtils;

public class ExtClassPathXmlApplicationContext {

private String packageName;

private ConcurrentHashMap<String, Object> beans = null;

public ExtClassPathXmlApplicationContext(String packageName) throws Exception {

this.packageName = packageName;

beans = new ConcurrentHashMap<String, Object>();

initBeans();

initAttris();

}

private void initAttris() throws Exception {

for (Object o : beans.keySet()) {

System.out.println("key=" + o + " value=" + beans.get(o));

attriAssign(beans.get(o));

}

}

public void initBeans() throws IllegalArgumentException, IllegalAccessException {

List<Class<?>> classes = ClassUtil.getClasses(packageName);

ConcurrentHashMap<String, Object> findClassExisAnnotation = findClassExisAnnotation(classes);

if (findClassExisAnnotation == null || findClassExisAnnotation.isEmpty()) {

throw new RuntimeException("该包下没有这个注解");

}

}

public Object getBean(String beanId) throws Exception {

if (beanId == null || StringUtils.isEmpty(beanId)) {

throw new RuntimeException("beanId不能为空");

}

Object class1 = beans.get(beanId);

if (class1 == null) {

throw new RuntimeException("该包下没有BeanId为" + beanId + "的类");

}

return class1;

}

public ConcurrentHashMap<String, Object> findClassExisAnnotation(List<Class<?>> classes)

throws IllegalArgumentException, IllegalAccessException {

for (Class<?> class1 : classes) {

XwfService annotation = class1.getAnnotation(XwfService.class);

if (annotation != null) {

String beanId = annotation.value();

if (StringUtils.isEmpty(beanId)) {

beanId = toLowerCaseFirstOne(class1.getSimpleName());

}

Object newInstance = newInstance(class1);

beans.put(beanId, newInstance);

}

}

return beans;

}

public static String toLowerCaseFirstOne(String s) {

if (Character.isLowerCase(s.charAt(0)))

return s;

else

return (new StringBuilder()).append(Character.toLowerCase(s.charAt(0))).append(s.substring(1)).toString();

}

public Object newInstance(Class<?> classInfo) {

try {

return classInfo.newInstance();

} catch (Exception e) {

throw new RuntimeException("反射生成对象失败" + e.getMessage());

}

}

public void attriAssign(Object object) throws Exception {

Field[] declaredFields = object.getClass().getDeclaredFields();

for (Field field : declaredFields) {

XwfAutowired annotation = field.getAnnotation(XwfAutowired.class);

if (annotation != null) {

String name = field.getName();

Object newBean = getBean(name);

if (object != null) {

field.setAccessible(true);

field.set(object, newBean);

}

}

}

}

}

3.扫包工具类 ClassUtil.java 此为网上搜索版本

package com.huajie.utils;

import java.io.File;

import java.io.FileFilter;

import java.io.IOException;

import java.net.JarURLConnection;

import java.net.URL;

import java.net.URLDecoder;

import java.util.ArrayList;

import java.util.Enumeration;

import java.util.LinkedHashSet;

import java.util.List;

import java.util.Set;

import java.util.jar.JarEntry;

import java.util.jar.JarFile;

public class ClassUtil {

public static List<Class> getAllClassByInterface(Class c) {

List<Class> returnClassList = null;

if (c.isInterface()) {

String packageName = c.getPackage().getName();

List<Class<?>> allClass = getClasses(packageName);

if (allClass != null) {

returnClassList = new ArrayList<Class>();

for (Class classes : allClass) {

if (c.isAssignableFrom(classes)) {

if (!c.equals(classes)) {

returnClassList.add(classes);

}

}

}

}

}

return returnClassList;

}

public static String[] getPackageAllClassName(String classLocation, String packageName) {

String[] packagePathSplit = packageName.split("[.]");

String realClassLocation = classLocation;

int packageLength = packagePathSplit.length;

for (int i = 0; i < packageLength; i++) {

realClassLocation = realClassLocation + File.separator + packagePathSplit[i];

}

File packeageDir = new File(realClassLocation);

if (packeageDir.isDirectory()) {

String[] allClassName = packeageDir.list();

return allClassName;

}

return null;

}

public static List<Class<?>> getClasses(String packageName) {

List<Class<?>> classes = new ArrayList<Class<?>>();

boolean recursive = true;

String packageDirName = packageName.replace('.', '/');

Enumeration<URL> dirs;

try {

dirs = Thread.currentThread().getContextClassLoader().getResources(packageDirName);

while (dirs.hasMoreElements()) {

URL url = dirs.nextElement();

String protocol = url.getProtocol();

if ("file".equals(protocol)) {

String filePath = URLDecoder.decode(url.getFile(), "UTF-8");

findAndAddClassesInPackageByFile(packageName, filePath, recursive, classes);

} else if ("jar".equals(protocol)) {

JarFile jar;

try {

jar = ((JarURLConnection) url.openConnection()).getJarFile();

Enumeration<JarEntry> entries = jar.entries();

while (entries.hasMoreElements()) {

JarEntry entry = entries.nextElement();

String name = entry.getName();

if (name.charAt(0) == '/') {

name = name.substring(1);

}

if (name.startsWith(packageDirName)) {

int idx = name.lastIndexOf('/');

if (idx != -1) {

packageName = name.substring(0, idx).replace('/', '.');

}

if ((idx != -1) || recursive) {

if (name.endsWith(".class") && !entry.isDirectory()) {

String className = name.substring(packageName.length() + 1, name.length() - 6);

try {

classes.add(Class.forName(packageName + '.' + className));

} catch (ClassNotFoundException e) {

e.printStackTrace();

}

}

}

}

}

} catch (IOException e) {

e.printStackTrace();

}

}

}

} catch (IOException e) {

e.printStackTrace();

}

return classes;

}

public static void findAndAddClassesInPackageByFile(String packageName, String packagePath, final boolean recursive,

List<Class<?>> classes) {

File dir = new File(packagePath);

if (!dir.exists() || !dir.isDirectory()) {

return;

}

File[] dirfiles = dir.listFiles(new FileFilter() {

public boolean accept(File file) {

return (recursive && file.isDirectory()) || (file.getName().endsWith(".class"));

}

});

for (File file : dirfiles) {

if (file.isDirectory()) {

findAndAddClassesInPackageByFile(packageName + "." + file.getName(), file.getAbsolutePath(), recursive,

classes);

} else {

String className = file.getName().substring(0, file.getName().length() - 6);

try {

classes.add(Class.forName(packageName + '.' + className));

} catch (ClassNotFoundException e) {

e.printStackTrace();

}

}

}

}

}

四,测试效果

客户端测试类

package com.huajie;

import com.huajie.service.UserService;

import com.huajie.spring.ext.ExtClassPathXmlApplicationContext;

public class TestApp {

public static void main(String[] args) throws Exception {

ExtClassPathXmlApplicationContext app = new ExtClassPathXmlApplicationContext("com.huajie.service");

UserService userService = (UserService) app.getBean("userService");

userService.add("test");

}

}

impl实现类

package com.huajie.service.impl;

import com.huajie.service.OrderService;

import com.huajie.service.UserService;

import com.huajie.spring.annotation.XwfAutowired;

import com.huajie.spring.annotation.XwfService;

@XwfService(value = "userService")

public class UserServiceImpl implements UserService {

@XwfAutowired

private OrderService orderService;

public int add(String a) {

System.out.println("####UserServiceImpl====添加" + a);

orderService.add();

return 0;

}

}

package com.huajie.service.impl;

import com.huajie.service.OrderService;

import com.huajie.spring.annotation.XwfService;

@XwfService(value = "orderService")

public class OrderServiceImpl implements OrderService {

public void add() {

System.out.println("####OrderServiceImpl====依赖注入添加");

}

}

接口

package com.huajie.service;

import org.springframework.stereotype.Service;

@Service

public interface UserService {

int add(String a);

}

package com.huajie.service;

public interface OrderService {

void add();

}

测试结果截图

网址:Spring学习 https://www.yuejiaxmz.com/news/view/536597

相关内容

spring学习笔记 (3)aop的原理与实现
基于Spring Boot的在线学习系统的设计与实现
为什么越来越多的开发者选择使用Spring Boot?
Spring Boot 事务的简单使用
The benefits of spring cleaning 春季大扫除的好处
Spring Boot中使用Server
基于Spring Boot + Vue + MySQL的公益旧物捐赠系统
Spring事务控制 @Transactional(propagation = Propagation.REQUIRED, rollbackFor = {Exception.class},)
【本科毕业论文】基于Spring Boot框架的健康管家系统
Spring中文件的上传下载

随便看看