自定义注解:
xml是干嘛的:用来描述元数据的
例:user类和user表关联起来,用文本文件关联起来的。
自定义注解:
代码1:luban/aop1:
复刻代码:
代码讲解:
package com.luban.aop.anno;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
//TYPE表示是出现在类上的,不能应用在属性上 FIELD表示属性......
//@Target(ElementType.TYPE)
@Target({ElementType.TYPE,ElementType.FIELD})
//表示仅仅存在源代码 编译为class没有了
//@Retention(RetentionPolicy.SOURCE)
//这个才能在执行的时候被发掘到
@Retention(RetentionPolicy.RUNTIME)
public @interface Entity {
//value是在@Entity可以不指定其余的要指定 @Entity(value="city")
public String value();
}
@Entity(value="city")
public class CityEntity {
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
private String id;
private String name;
}
public class CommonUtil {
public static String builfQueryEntity(Object object) {
Class clazz = object.getClass();
//判断是否加了注解
Entity entity = null;
if(clazz.isAnnotationPresent(Entity.class)){
//得到注解的值
entity = (Entity)clazz.getDeclaredAnnotation(Entity.class);
System.out.println(entity.value());
}
String sql = "select * from ";
return sql+entity.value();
}
}
和springboot的@Value有异曲同工之处。
--------------------------------------------------------------------------------------------------------------------------------------------------------------
AOP
------------------------
aop:002538
代码2:luban/aop2aop
aop文档
看这个博客:https://blog.csdn.net/qq_28764557/article/details/100189201
这个章节讲的是aop的知识。
---------------------------------------------------------------
解决横切性的问题:不会影响我们的主业务逻辑。
Aspect:切面就是以下所有功能的集合,是一个载体是一个概念,可能是类ASPECTJ,XML就是个标签。
Join point:连接点目标对象中的方法。
pointcut:切点,连接点的集合。
Target object:目标对象,切入之前的对象。
AOP proxy:代理对象,切入之后的对象,就是增强之后的对象。
Wearing:织入,方法变为代理方法的过程。
Introduction:
Advice:通知,织入的代码放入的位置,通知的具体的内容。
AspectJ。
Spring实现AOP 。
aspect实现AOP。
默认是使用JDK的动态代理。
为什么两个?spring借助了ASPECTJ的语法。
体现就是借助了一个注解。
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------
aop是解决横切性的问题,不影响主业务。
两种方法:
代码2:luban/aop2aop
声明一个aop步骤:
1.引入@EnableAspectJAutoProxy在配置文件或者xml来开启aop
2.加pom依赖
3.加@Aspect 切面
4.加@pointCut 切点可以关联多个和连接点
5.通知@Before
package com.luban.appconfig;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
@Configuration
@EnableAspectJAutoProxy
public class AppConfig {
}
很简单就开启了aop的支持。这格式必须要开启的。
写aop:
Aspect要单独引用的。
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.0</version>
</dependency>
spring借助了AspectJ的语法的。
举例:
如何声明切点:
//切点在哪里就是在dao下面的任意包的任意子包下面的方法
@Pointcut("execution(* com.luban.dao.*.*(..))")
public void pointCut(){
}
如何声明通知:
@Before("pointCut()")
public void before() {
System.out.println("before通知");
}
调用方法的时候才引起aop。
代码:
------------------------------------------------------------------------------------------------------------------------------------------------------------
这个是很重要的:
上面的是切点的声明支持的表达式:
execution和within的区别:面试问题
代码2:
@Component
@Aspect
public class Aspect1 {
@Pointcut("within(com.luban.dao.*)")
public void pointCutWithWithis() {
}
@Before("pointCutWithWithis()")
public void before() {
System.out.println("before通知within");
}
}
跑下依然可以的。
举例:代码:
@Pointcut("execution(public String com.luban.dao.*.*(..))")
public void pointCut() {
}
excusion定义到方法:可以定义到最小的粒度
* * com.luban.dao.*.*(..)
*:方法的类型
*:方法返回值类型,方法是目标方法
*:方法放入可见性
*:方法名字
..:参数类型 注意有顺序性质的
within:粒度为类
定义到类。
--------------------------------------------------------------------------------------------------
代码:
args的用法,定义到参数:
@Pointcut("args(java.lang.String)")
public void pointArgs(){
}
@Before("pointCutWithWithis()&&!pointArgs()")
public void before(){
System.out.println("before");
}
目前这三个已经有了结果:
------------------------------------------------------------------------------------------------------------
自定义一个注解:看代码即可。
自定义一个注解:
@Retention(RetentionPolicy.RUNTIME)
public @interface Luban {
}
@Retention(RetentionPolicy.RUNTIME)
public @interface Luban {
}
@Luban
public void qyeryLuban(String a){
System.out.println("dao1");
}
在这里加了注解才可以的。
@Luban
public void qyeryLuban(String a){
System.out.println("dao1");
}
-------------------------------------------------------------------------------------------------------------------------------------------------
关键的关键重点:
复刻代码:
两个源码this和@target
-------------------------------------------
实验的代码和现象:
代码:
@Configuration
//false是JDK的
//@EnableAspectJAutoProxy(proxyTargetClass = false)
@EnableAspectJAutoProxy(proxyTargetClass = false)
//@ComponentScan(value="com.luba.dao2")
@ComponentScan({"com.luban"})
public class AppConfig {
}
public static void main(String[] args) {
AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
// IndexDao dao = annotationConfigApplicationContext.getBean(IndexDao.class);
Dao dao = (Dao)annotationConfigApplicationContext.getBean("indexDao");
System.out.println(dao instanceof IndexDao);
dao.qyery(1);
}
此时打印为false
@Configuration
//false是JDK的
//@EnableAspectJAutoProxy(proxyTargetClass = false)
@EnableAspectJAutoProxy(proxyTargetClass = true)
//@ComponentScan(value="com.luba.dao2")
@ComponentScan({"com.luban"})
public class AppConfig {
}
此时打印为true
----------------------------------------------------------------------------------------------------------
建一个接口:Dao
改下方式:
注意此时不是一个对象了,为false。
在容器中没有IndexDao:是因为什么呢?因为代理对象不是IndexDao了
加这个就不报错了。
并且打印为true。
true是用的cglib 其他的用的是JDK动态代理。
为什么?aop写了满足推荐了要是JDK的动态代理的话或者其他的就变为代理对象了。而不是调用才变的。
看文档:
JDK动态代理为什么一定要用接口而不是继承?
实现代理:继承 聚合 动态代理
JSK是聚合。
--------------------------------------------------------------------------------------------------------------------------------------------------------
代码:
写一个动态代理的例子:
/**
* 还原JDK动态代理产生的字节码
*/
Class<?>[] interfaces = new Class[]{Dao.class};
byte bytes[] = ProxyGenerator.generateProxyClass("lubanAa",interfaces);
File file = new File("d:\\Test.class");
try{
FileOutputStream fw = new FileOutputStream(file);
fw.write(bytes);
fw.flush();
fw.close();
}catch(Exception e){
e.printStackTrace();
}
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
import com.luban.dao.Dao;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;
public final class lubanAa extends Proxy implements Dao {
private static Method m1;
private static Method m2;
private static Method m4;
private static Method m3;
private static Method m0;
public lubanAa(InvocationHandler var1) throws {
super(var1);
}
public final boolean equals(Object var1) throws {
try {
return (Boolean)super.h.invoke(this, m1, new Object[]{var1});
} catch (RuntimeException | Error var3) {
throw var3;
} catch (Throwable var4) {
throw new UndeclaredThrowableException(var4);
}
}
public final String toString() throws {
try {
return (String)super.h.invoke(this, m2, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
public final void qyery1(String var1) throws {
try {
super.h.invoke(this, m4, new Object[]{var1});//h是生成出来的代理对象是基于接口的
} catch (RuntimeException | Error var3) {
throw var3;
} catch (Throwable var4) {
throw new UndeclaredThrowableException(var4);
}
}
public final void qyery() throws {
try {
super.h.invoke(this, m3, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
public final int hashCode() throws {
try {
return (Integer)super.h.invoke(this, m0, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
static {
try {
m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
m2 = Class.forName("java.lang.Object").getMethod("toString");
m4 = Class.forName("com.luban.dao.Dao").getMethod("qyery1", Class.forName("java.lang.String"));
m3 = Class.forName("com.luban.dao.Dao").getMethod("qyery");
m0 = Class.forName("java.lang.Object").getMethod("hashCode");
} catch (NoSuchMethodException var2) {
throw new NoSuchMethodError(var2.getMessage());
} catch (ClassNotFoundException var3) {
throw new NoClassDefFoundError(var3.getMessage());
}
}
}
h是innoveationhandler接口。
JDK动态代理为什么只能是基于接口:因为是单继承的
已经继承了Proxy了。
所以看,它既是Dao也是Proxy就是不等于我们的目标对象。
-----------------------------------------------------------------------------------------------------------------------------------------------------------------
JDK的话代理对象不是原来的对象了,接口是一个。
注意看里面根本没有IndexDao了,已经被代理了。
------------------------------------------------------------------------------------------------------------------------------------------------------------------
cglib是继承了目标对象----------------------------------------------------------------------------
-----
总结:this是加在代理上对象,target是加在了目标对象。
---
//this是代理对象
@Pointcut("this(com.luban.dao.IndexDao)")
public void pointCutThis(){
}
@Before("pointCutThis()")
public void before(){
System.out.println("before");
}
这样写的话true是增强,false不是增强。fasle是动态代理。
之所以不增强是因为dao不是代理对象,代理对象继承了Proxy。
增强是因为dao是被代理对象继承的对象。
this是匹配的代理对象。
代码:
@Configuration
//false是JDK的
//@EnableAspectJAutoProxy(proxyTargetClass = false)
@EnableAspectJAutoProxy(proxyTargetClass = true)
//@ComponentScan(value="com.luba.dao2")
@ComponentScan({"com.luban"})
public class AppConfig {
}
target永远可以的。
-----
------------------------------------------------------
------------------------------------------