手写spring-ioc
spring ioc指的是控制反转,IOC容器负责实例化、定位、配置应用程序中的对象及建立这些对象间的依赖。交由Spring容器统一进行管理,从而实现松耦合
包结构
执行流程
第一步定义三个注解,用于扫描方法
Service注解表示加了此注解的实现类的实例对象交给spring管理
package org.spring.ioc;
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 Service {
}
RestController注解表示加了此注解的controller可以通过url访问到具体方法并返回json格式的字符串对象
package org.spring.ioc;
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 RestController {
}
Autowired注解表示加了此注解的属性由容器提供值(一般为对象)
package org.spring.ioc;
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 Autowired {
}
第二步定义扫描类,在程序启动时将扫描到注解的类实例化放入容器,并处理autowired注解
package org.spring.ioc;
import java.io.File;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import com.tedu.mall.RunApp;
//框架的启动类
public class ApplicationContext {
// 放的是类名
ArrayList<String> classNameList = new ArrayList<>();
// 容器
// userController,对象
// userServiceImpl,对象
HashMap<String, Object> container = new HashMap<>();
public ApplicationContext() throws Throwable {
classNameList.add("com.tedu.mall.UserController");
classNameList.add("com.tedu.mall.UserServiceImpl");
// 创建对象放到容器中
loadObject();
System.out.println(container);
// 处理autowired注解
autowiredProcess();
}
private void loadObject() throws Throwable {
// 遍历所有的类
for (String className : classNameList) {
Class clazz = Class.forName(className);
// 判断类有没有加@controller或@service
RestController controller = (RestController) clazz.getAnnotation(RestController.class);
Service service = (Service) clazz.getAnnotation(Service.class);
Object object;
if (controller != null || service != null) {
object = clazz.newInstance();
// 得到key
int begin = className.lastIndexOf(".") + 1;
// UserController
className = className.substring(begin);
// 把首字母变成小写的
// userController
String objectName = Character.toLowerCase(className.charAt(0)) + className.substring(1);
// 创建对象放到容器中
container.put(objectName, object);
}
}
}
private void autowiredProcess() throws Throwable {
// 遍历容器
for (String key : container.keySet()) {
// 取到对象,判断对象属性有没有加autowired
System.out.println("key="+key);
Object object = container.get(key);
Class clazz = object.getClass();
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
Autowired autowired = field.getAnnotation(Autowired.class);
if (autowired != null) {
// @autowired
// UserService userServiceImpl
String objectName = field.getName();
// 从容器中找一个对象赋值给属性
Object bean = container.get(objectName);
field.setAccessible(true);
field.set(object, bean);
}
}
}
}
public Object getBean(String beanName) {
return container.get(beanName);
}
}
第三步定义业务层接口和实现类,定义控制层Controller并通过@Autowired注解向spring容器要一个对象。
UserService
package com.tedu.mall;
public interface UserService {
public void register();
}
UserServiceImpl
package com.tedu.mall;
import org.spring.ioc.Service;
@Service
public class UserServiceImpl implements UserService{
@Override
public void register() {
System.out.println("register()");
}
}
UserController
package com.tedu.mall;
import org.spring.ioc.Autowired;
import org.spring.ioc.RestController;
@RestController
public class UserController {
@Autowired
UserService userServiceImpl;
}
第四步定义启动类RunApp,开启扫描,对加了注解的类进行实例化,并访问controller中的属性,看是否赋值。
package com.tedu.mall;
import org.spring.ioc.ApplicationContext;
public class RunApp {
public static void main(String[] args) throws Throwable{
//启动框架
ApplicationContext applicationContext=
new ApplicationContext();
UserController userController=(UserController) applicationContext.getBean("userController");
System.out.println(userController);
UserService userService=userController.userServiceImpl;
userService.register();
}
}
手写spring-aop
本次练习只是实现简单的aop,实则aop的内容很庞大,面向切面编程是一种思想。
包结构
执行流程
第一步定义四个注解
@After注解表示要在目标方法前执行的方法
package org.spring.aop;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface After {
}
@Before注解表示要在目标方法后执行的方法
package org.spring.aop;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Before {
}
@Aspect注解表示该类是切面类,用于无侵入式扩充目标方法
package org.spring.aop;
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 Aspect {
}
@Pointcut注解表示该方法是目标方法
package org.spring.aop;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Pointcut {
//切点com.tedu.mall.UserServiceImpl.register
//调用register(),自动执行TimeAspect中的方法
String value();
}
第二步定义业务层接口和实现类
Service接口
package com.tedu.mall;
public interface UserService {
public void register();
}
ServiceImpl实现类
package com.tedu.mall;
public class UserServiceImpl implements UserService{
@Override
public void register() {
System.out.println("UserServiceImpl.register()");
}
}
第三步定义切面类TimeAspect,对目标方法进行扩充
package com.tedu.mall;
import org.spring.aop.After;
import org.spring.aop.Aspect;
import org.spring.aop.Before;
import org.spring.aop.Pointcut;
@Aspect
public class TimeAspect {
long startTime;
@Pointcut("com.tedu.mall.UserServiceImpl.register")
public void pointCut() {}
@Before
public void doBefore() {
System.out.println("doBefore()");
startTime=System.nanoTime();
}
@After
public void doAfter() {
System.out.println("doAfter()");
System.out.println("time:"+(System.nanoTime()-startTime));
}
}
第四步定义ApplicationContext类,用于扫描注解并对其方法做相应处理
package org.spring.aop;
import java.io.File;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.HashMap;
import com.tedu.mall.RunApp;
import com.tedu.mall.TimeAspect;
import com.tedu.mall.UserServiceImpl;
//框架的启动类
public class ApplicationContext {
// 放的是类
// 容器
// userController,对象
// userServiceImpl,对象
HashMap<String, Object> container = new HashMap<>();
public ApplicationContext() throws Throwable {
UserServiceImpl userServiceImpl=new UserServiceImpl();
container.put("userServiceImpl", userServiceImpl);
TimeAspect timeAspect=new TimeAspect();
container.put("timeAspect", timeAspect);
// 遍历容器中所有的对象
for (String key : container.keySet()) {
// 判断这个对象有没有加@Aspect
Object object = container.get(key);
Class clazz = object.getClass();
Aspect aspect = (Aspect) clazz.getAnnotation(Aspect.class);
if (aspect != null) {
Object aspectObject = object;
// 在执行目标类UserServiceImpl的目标方法register时,自动执行timeAspect
// 找到pointcut,before,after
String pointcutString = null;
Method beforeMethod = null;
Method afterMethod = null;
// 遍历TimeAspect的所有方法
Method[] methods = aspectObject.getClass().getDeclaredMethods();
for (Method method : methods) {
Pointcut pointcut = method.getAnnotation(Pointcut.class);
Before before = method.getAnnotation(Before.class);
After after = method.getAnnotation(After.class);
if (pointcut != null) {
pointcutString = pointcut.value();
}
if (before != null) {
beforeMethod = method;
}
if (after != null) {
afterMethod = method;
}
}
// pointcutString=com.tedu.mall.UserServiceImpl.register
// 得到key userServiceImpl;从容器中找到目标类的对象
String[] strings = pointcutString.split("\\.");
String targetObjectkey = strings[strings.length - 2];
targetObjectkey = Character.toLowerCase(targetObjectkey.charAt(0)) + targetObjectkey.substring(1);
// 得到目标类对象,创建动态代理对象proxy
Object targetObject = container.get(targetObjectkey);
Class[] interfaces = targetObject.getClass().getInterfaces();
ClassLoader loader = targetObject.getClass().getClassLoader();
AopHandler aopHandler = new AopHandler(targetObject, beforeMethod, afterMethod, aspectObject);
Object proxy = Proxy.newProxyInstance(loader, interfaces, aopHandler);
// 容器中userServiceimpl原先的对象是用反射创建的对象,改成proxy
// userServiceImpl,
container.put(targetObjectkey, proxy);
// 程序员从容器中取对象,取到的是proxy,proxy.register()
}
}
}
class AopHandler implements InvocationHandler {
Object targetObject;// UserServiceImpl
Method beforeMethod;
Method afterMethod;
Object aspectObject;
public AopHandler(Object targetObject, Method beforeMethod, Method afterMethod, Object aspectObject) {
super();
this.targetObject = targetObject;
this.beforeMethod = beforeMethod;
this.afterMethod = afterMethod;
this.aspectObject = aspectObject;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 调用切面的before
if (beforeMethod != null)
beforeMethod.invoke(aspectObject);
// 调用目标方法UserServiceImpl.register
method.invoke(targetObject, args);
// 调用切面的after
if (afterMethod != null)
afterMethod.invoke(aspectObject);
return null;
}
}
public Object getBean(String beanName) {
return container.get(beanName);
}
}
第五步定义启动类RunApp,启动扫描类,并测试。
package com.tedu.mall;
import org.spring.aop.ApplicationContext;
public class RunApp {
public static void main(String[] args) throws Throwable {
// 启动框架
ApplicationContext applicationContext = new ApplicationContext();
UserService userService = (UserService) applicationContext.getBean("userServiceImpl");
System.out.println(userService.getClass().getName());
userService.register();
}
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。