Delete aop directory

This commit is contained in:
Tursom K. Ulefits 2021-08-17 16:45:50 +08:00 committed by GitHub
parent 28de77dc79
commit 0fa7a13940
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 0 additions and 363 deletions

View File

@ -1,5 +0,0 @@
dependencies {
implementation project(":utils:xml")
// XML
implementation group: 'dom4j', name: 'dom4j', version: '1.6.1'
}

View File

@ -1,51 +0,0 @@
package cn.tursom.aop
import cn.tursom.aop.advice.AdviceContent
import cn.tursom.aop.aspect.Aspect
import java.lang.reflect.InvocationHandler
import java.lang.reflect.Method
import java.lang.reflect.Proxy
class ProxyHandler(private val target: Any, private val aspect: Aspect) : InvocationHandler {
fun getTopBean(): Any {
var bean = target
while (Proxy.isProxyClass(bean.javaClass)) {
val handler = Proxy.getInvocationHandler(bean)
if (handler is ProxyHandler)
bean = handler.target
else break
}
return bean
}
override fun invoke(proxy: Any?, method: Method, args: Array<out Any>?): Any? {
return if (aspect.pointcut.matchMethod(method)) {
aspect.advice.invoke(AdviceContent(target, method, args))
} else {
method.invoke(target, args)
}
}
companion object {
fun proxyEnhance(bean: Any, aspect: Aspect): Any {
val clazz = bean.javaClass
return Proxy.newProxyInstance(
clazz.classLoader,
clazz.interfaces,
ProxyHandler(bean, aspect)
)
}
fun getTopBean(target: Any): Any {
var bean = target
while (Proxy.isProxyClass(bean.javaClass)) {
val handler = Proxy.getInvocationHandler(bean)
if (handler is ProxyHandler)
bean = handler.target
else break
}
return bean
}
}
}

View File

@ -1,6 +0,0 @@
package cn.tursom.aop.advice
interface Advice {
operator fun invoke(content: AdviceContent): Any?
}

View File

@ -1,27 +0,0 @@
package cn.tursom.aop.advice
import cn.tursom.aop.ProxyHandler
import java.lang.reflect.Method
import java.lang.reflect.Proxy
@Suppress("MemberVisibilityCanBePrivate")
class AdviceContent(
val target: Any,
val method: Method,
val args: Array<out Any>?
) {
val bean: Any = if (Proxy.isProxyClass(target.javaClass)) {
val handler = Proxy.getInvocationHandler(target)
if (handler is ProxyHandler)
handler.getTopBean()
else target
} else target
fun invoke() {
if (args != null) {
method.invoke(target, *args)
} else {
method.invoke(target)
}
}
}

View File

@ -1,10 +0,0 @@
package cn.tursom.aop.aspect
import cn.tursom.aop.advice.Advice
import cn.tursom.aop.pointcut.Pointcut
interface Aspect {
val pointcut: Pointcut
val advice: Advice
}

View File

@ -1,6 +0,0 @@
package cn.tursom.aop.aspect
import cn.tursom.aop.advice.Advice
import cn.tursom.aop.pointcut.Pointcut
data class DefaultAspect(override val pointcut: Pointcut, override val advice: Advice) : Aspect

View File

@ -1,150 +0,0 @@
package cn.tursom.aop.factory
import cn.tursom.aop.advice.Advice
import cn.tursom.aop.aspect.DefaultAspect
import cn.tursom.aop.ioc.DefaultIocContainer
import cn.tursom.aop.ioc.IocContainer
import cn.tursom.aop.pointcut.Pointcut
import cn.tursom.aop.pointcut.RegexPointcut
import cn.tursom.utils.xml.Xml
import org.dom4j.Element
import java.io.File
@Suppress("MemberVisibilityCanBePrivate")
object IocContainerFactory {
/**
* example:
* <IOC>
* <bean class="cn.tursom.Example1" id="exampleBean1"/>
* <bean class="cn.tursom.Example2" id="exampleBean2">
* <property name="propertyField" value="test"/>
* <ref name="refField" id="exampleBean1" />
* <bean name="beanField" class="cn.tursom.BeanField" />
* </bean>
* <aspect>
* <advice class="cn.tursom.AdviceExample" />
* <advice class="cn.tursom.AdviceExample2" />
* <RegexPointcut class="cn\.tursom\.aop\..*" method=".*" />
* <pointcut pointcut="RegexPointcut" class="cn\.tursom\.aop\.ioc\..*" method=".*" />
* </aspect>
* </IOC>
*/
fun loadFromXml(path: String): IocContainer = loadFromXml(path, Thread.currentThread().contextClassLoader)
fun loadFromXml(path: String, classLoader: ClassLoader): IocContainer {
val element: Element = Xml.saxReader.read(File(path)).rootElement
val iocContainer = DefaultIocContainer()
element.elements("bean").forEach {
if (it !is Element) return@forEach
val id = it.attribute("id").value
val bean = getXmlBean(it, classLoader, iocContainer)
iocContainer.addBean(id, bean)
}
element.elements("aspect").forEach {
if (it !is Element) return@forEach
val advices = getXmlAdvices(it, classLoader)
val pointcuts = getXmlPointCuts(it)
advices.forEach { advice ->
pointcuts.forEach { pointcut ->
iocContainer.addAspect(DefaultAspect(pointcut, advice))
}
}
}
return iocContainer
}
fun getXmlPointCuts(root: Element): List<Pointcut> {
val pointcuts = ArrayList<Pointcut>()
root.elements("RegexPointcut").forEach {
if (it !is Element) return@forEach
val clazz = it.attributeValue("class")
val method = it.attributeValue("method")
pointcuts.add(RegexPointcut(clazz, method))
}
root.elements().forEach {
if (it !is Element) return@forEach
val clazz = it.attributeValue("class")
val method = it.attributeValue("method")
pointcuts.add(RegexPointcut(clazz, method))
}
return pointcuts
}
fun getXmlAdvices(root: Element, classLoader: ClassLoader): List<Advice> {
val advices = ArrayList<Advice>()
root.elements("advice").forEach {
if (it !is Element) return@forEach
val clazzName = it.attributeValue("class")
val clazz = classLoader.loadClass(clazzName)
advices.add(clazz.newInstance() as Advice)
}
return advices
}
fun getXmlBean(root: Element, classLoader: ClassLoader, iocContainer: IocContainer): Any {
val clazz = classLoader.loadClass(root.attribute("class").value)
val bean = clazz.newInstance()
root.elements()?.forEach subForEach@{ sub ->
if (sub !is Element) return@subForEach
when (sub.name) {
"property" -> {
val name = sub.attributeValue("name")
val value = sub.attributeValue("value")
val field = clazz.getDeclaredField(name)
field.isAccessible = true
field.set(bean, value)
}
"ref" -> {
val name = sub.attributeValue("name")
val refId = sub.attributeValue("id")
val field = clazz.getDeclaredField(name)
field.isAccessible = true
field.set(bean, iocContainer[refId])
}
"bean" -> {
val name = sub.attributeValue("name")
val field = clazz.getDeclaredField(name)
field.isAccessible = true
field.set(bean, getXmlBean(sub, classLoader, iocContainer))
}
}
}
return bean
}
/**
* example:
* {
* "beans": [
* {
* "id": "exampleBean1",
* "class": "cn.tursom.Example1"
* },
* {
* "id": "exampleBean2",
* "class": "cn.tursom.Example2",
* "properties": [
* {
* "style": "property",
* "name": "propertyField",
* "value": "test"
* },
* {
* "style": "ref",
* "name": "refField",
* "id": "exampleBean1"
* },
* {
* "style": "bean",
* "id": "refFiled",
* "class": "cn.tursom.BeanField"
* }
* ]
* }
* ]
* }
*/
fun loadFromJson(json: String): IocContainer {
TODO()
}
}

View File

@ -1,69 +0,0 @@
package cn.tursom.aop.ioc
import cn.tursom.aop.aspect.Aspect
import cn.tursom.aop.ProxyHandler
import java.lang.reflect.Proxy
class DefaultIocContainer : IocContainer {
private val benDefinitionMap = HashMap<String, Class<*>>()
private val beanMap = HashMap<String, Any>()
private val aspectSet: java.util.AbstractSet<Aspect> = HashSet<Aspect>()
override val aspects: Set<Aspect> get() = aspectSet
override fun addBeanDefinition(beanName: String, clazz: Class<*>) {
benDefinitionMap[beanName] = clazz
}
override fun addBean(beanName: String, bean: Any) {
beanMap[beanName] = proxyEnhance(bean)
}
override fun getBean(beanName: String): Any {
return beanMap[beanName] ?: run {
val bean = createInstance(beanName)
val proxyBean = proxyEnhance(bean)
beanMap[beanName] = proxyBean
proxyBean
}
}
private fun proxyEnhance(bean: Any): Any {
val clazz = getTopBean(bean).javaClass
var enhanceBean = bean
aspectSet.forEach {
if (it.pointcut.matchClass(clazz)) {
enhanceBean = ProxyHandler.proxyEnhance(enhanceBean, it)
}
}
return enhanceBean
}
private fun createInstance(beanName: String): Any {
return (benDefinitionMap[beanName] ?: throw NullPointerException()).newInstance()
}
override fun addAspect(aspect: Aspect) {
if (aspectSet.contains(aspect)) return
aspectSet.add(aspect)
beanMap.forEach { (t, u) ->
val bean = getTopBean(u)
if (aspect.pointcut.matchClass(bean.javaClass)) {
beanMap[t] = ProxyHandler.proxyEnhance(u, aspect)
}
}
}
private fun getTopBean(bean: Any): Any {
return if (Proxy.isProxyClass(bean.javaClass)) {
val handler = Proxy.getInvocationHandler(bean)
if (handler is ProxyHandler) handler.getTopBean()
else bean
} else {
bean
}
}
}

View File

@ -1,17 +0,0 @@
package cn.tursom.aop.ioc
import cn.tursom.aop.aspect.Aspect
interface IocContainer {
val aspects: Set<Aspect>
fun addAspect(aspect: Aspect)
fun addBeanDefinition(beanName: String, clazz: Class<*>)
fun addBean(beanName: String, bean: Any)
operator fun set(beanName: String, bean: Any) = addBean(beanName, bean)
fun getBean(beanName: String): Any
@Suppress("UNCHECKED_CAST")
operator fun <T> get(beanName: String): T = getBean(beanName) as T
}

View File

@ -1,9 +0,0 @@
package cn.tursom.aop.pointcut
import java.lang.reflect.Method
interface Pointcut {
fun matchClass(clazz: Class<*>): Boolean
fun matchMethod(method: Method): Boolean
}

View File

@ -1,13 +0,0 @@
package cn.tursom.aop.pointcut
import java.lang.reflect.Method
data class RegexPointcut(
private val classRegex: Regex,
private val methodRegex: Regex
) : Pointcut {
constructor(classRegex: String, methodRegex: String) : this(classRegex.toRegex(), methodRegex.toRegex())
override fun matchClass(clazz: Class<*>) = classRegex.matches(clazz.name)
override fun matchMethod(method: Method) = methodRegex.matches(method.name)
}