Spring中的IOC和AOP以及Spring中的声明式事务
Spring中的IOC和AOP以及Spring中的声明式事务(基于狂神说Java-Spring)
Spring中的IOC
IOC(Inversion Of Controller)⼜称控制反转,是⼀种通过(xml或者注解)并通过第三⽅⽣成或获取特定对象的⽅式,在Spring中实现控制反转的是IOC容器,其实现⽅法是依赖注⼊(DI:Dependency Injection)
控制:控制对象的创建,传统的Java⾯向对象编程,对象是由程序本⾝控制实现创建的。⽤了Spring之后,对象都是由Spring来进⾏创建的
反转:程序现在不⽤⾃⼰创建对象,⽽是⾃⼰被动的接收⼀个对象
总结:所谓的控制反转,就是创建对象的⽅式反转了,总的来说,对象可以交给Spring容器进⾏创建,管理,装配
Spring 当中的依赖
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.7.RELEASE</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
</dependencies>
注解说明
@Autowired:Spring注解⾃动装配,可以通过类型和名字,但是当Bean实例多于两个时⽆法装配,需要通过@Quefilier注解配合使⽤指定某个Bean实例(注意:@Qualifier不能单独使⽤),如果允许对象为null,设置required = false,required属性默认为true,即为**@Autowired(required = false)**
@Nullable:如果某个字段标记了这个注解后,说明这个字段可以为null
@Resource:此注解是JavaEE原⽣注解实现,同样可以实现⾃动装配,在Bean实例多于两个时可以通过name属性指定Bean实例(但是这边有⼀个⼩问题,随着JDK版本的提升,JavaEE原⽣注解就不再⽀持,所以在⾼版本的JDK中还需要导⼊相关的Maven依赖),@Resource会通过name属性进⾏查,如果说查不到才会通过Bean的类型进⾏查。
<dependency>
<groupId>javax.annotation</groupId>
<artifactId>javax.annotation-api</artifactId>
<version>1.3.2</version>
</dependency>
@Component:组件,使⽤此注解声明当前Java类交由Spring进⾏管理(在此注解的基础上还增加了三个衍⽣注解,基于MVC三层架构)
@Repository:dao层注解
spring ioc注解@Service:Service层注解
@Controller:Controller层注解
注意事项:翻阅底层源码可以发现这四个注解的代码都是⼀样的,意味着他们的功能都是⼀样的,都是代表将某个类交由Spring托管,进⾏Bean的装配
对于xml和注解:
xml配置在有些情况下会较为复杂,但是xml⽂件配置适⽤于任何场合
注解,对于注解,它的作⽤范围最⼤只能在当前这个Java类中,⽆法延伸到其他的类其他的包中,并且在后期项⽬维护极为不便所以针对这种情况最直接的解决⽅案就是两种⽅式进⾏组合(最佳实现)
xml⽤来对Bean进⾏统⼀的管理
注解⽤来对属性进⾏注⼊处理
在使⽤的过程中,必须要让注解⽣效,就需要在xml中进⾏开启注解⽀持
<!--扫描包,在指定包下的注解即刻⽣效-->
<component-scan base-package="com.hrc"/>
<annotation-config/>
回顾代理模式
SpringAOP(Aspect Oriented Programming)的底层就是代理设计模式
代理模式有两种:静态代理和动态代理
静态代理
业务分析:
抽象⾓⾊:⼀般都会⽤接⼝(使⽤较多)或者是抽象类来解决
// 以租房为例实现静态代理
public interface Rent {
void rent();
}
真实⾓⾊:处理真实业务,同时被代理⾓⾊进⾏代理
// 房东
public class Host implements Rent {
@Override
public void rent(){
System.out.println("房东要出租房⼦(真实业务)");
}
}
代理⾓⾊:代理真实⾓⾊,并且实现属于⾃⼰的扩展业务
public class MiddleProxy extends Host {
// 处理真实业务
public void rent(){
<();// 真实业务
}
/
/ 实现扩展业务
public void rentBefore(){
System.out.println("中介接单");
}
public void rentAfter(){
System.out.println("中间商赚差价");
}
public void res(){
System.out.println("扩展业务完成");
}
}
⽤户:访问代理对象
public class Client {
public static void main(String[] args){
// 代理⾓⾊,中介帮房东租房⼦,但是中介会做⼀些房东不会做的扩展业务
MiddleProxy proxy =new MiddleProxy();
<();
}
}
代理模式的好处:
可以让真实业务操作变得更加纯粹,说⽩了就是“我”该⼲嘛就⼲嘛,不⽤去关⼼其他的扩展业务
公共业务就交给了其他的代理⾓⾊,实现业务的分⼯处理
公共业务延伸出其他的扩展业务时,⽅便集中进⾏管理
缺点:
⼀个真实业务就需要⼀个代理对象进⾏代理,⼀旦真实业务多了之后,代码量提升就会造成冗余,开发效率降低动态代理
业务分析:
抽象⾓⾊:与静态代理相同
代理⾓⾊:动态⽣成,不是由开发者⾃⼰编写,⽽是开发者⾃定义⼀个模板然后交给程序去⽣成代理对象动态代理的实现机制有两种:⼀种是基于接⼝的动态代理,还有⼀种就是基于cglib实现动态代理基于接⼝:JDK动态代理
基于类的动态代理,也就是cglib动态代理(需要导⼊额外的cglib相关依赖)
Java字节码实现动态代理:Javassist
⾸先需要熟悉两个Java类:Proxy:代理;InvocationHandler:调⽤处理程序
动态代理的好处:
静态代理的优点全部具备
⼀个动态代理类代理的是⼀个接⼝,⼀般就是对应其某⼀个类型的业务,⽽不是单个业务
⼀个动态代理类可以代理多个类,只要是实现了同⼀个接⼝即可
优化之前实现的房东买房⼦的业务操作
import flect.InvocationHandler;
import flect.Method;
import flect.Proxy;
// ⽤此类动态⽣成代理类
public class ProxyInvocationHandler implements InvocationHandler {
// 在⽣成代理类的同时还需要⼀个被代理的接⼝
private Object target;
public void setTarget(Object target){
this.target = target;
}
// ⽣成代理类
public Object getProxy(){
Class().getClassLoader(), Class().getInterfaces(),this);
}
/**
* 处理代理实例,并返回结果
* @param proxy
* @param method
* @param args
* @return
* @throws Throwable
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args)throws Throwable {
Name());
// 动态代理的本质就是使⽤反射机制实现
Object res = method.invoke(target, args);
return res;
}
public void log(String msg){
System.out.println("【INFO】"+ msg);
}
}
public class Client {
public static void main(String[] args){
// 真实业务主题
Host host =new Host();
// ⽣成代理⾓⾊
ProxyInvocationHandler pih =new ProxyInvocationHandler();
pih.setTarget(host);// 设置代理对象
// 动态⽣成代理类
Rent proxy =(Rent) Proxy();
<();
}
}
SpringAOP
AOP(Aspect Oriented Programming),意思是⾯向切⾯编程,它是OOP(Object-Oriented Programming ⾯向对象编程)的⼀种延续在不破坏原有代码实现的基础上,利⽤“织⼊”的模式来实现⼀些代码的动态配置
利⽤AOP可以对业务逻辑的各个部分进⾏隔离,从⽽使得业务逻辑各部分之间的耦合度降低,提⾼代码可重⽤性,提⾼开发效率
使⽤SpringAOP需要额外导⼊相关依赖
<!-- mvnrepository/artifact/org.aspectj/aspectjweaver -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.5</version>
</dependency>
实现AOP的⽅式之⼀:使⽤Spring的接⼝
主要是通过实现Spring的接⼝来进⾏切⾯的处理
public interface UserService {
void insert();
void delete();
void update();
void select();
}
/*--------------两个类分开写----------------*/
public class UserServiceImpl implements UserService {
@Override
public void insert(){
System.out.println("【INSERT】增加了⼀个⽤户");
}
@Override
public void delete(){
System.out.println("【DELETE】删除了⼀个⽤户");
}
@Override
public void update(){
System.out.println("【UPDATE】修改了⼀个⽤户");
}
@Override
public void select(){
System.out.println("【SELECT】查询了⼀个⽤户");
}
}
import org.springframework.aop.MethodBeforeAdvice;
import flect.Method;
public class Log implements MethodBeforeAdvice {
/**
* 在实现操作业务之前⾸先要先做⼀些⽇志信息
* @param method 要执⾏的⽬标对象的⽅法
* @param objects 参数,对象数组
* @param target ⽬标对象
* @throws Throwable
*/
@Override
public void before(Method method, Object[] objects, Object target)throws Throwable {
System.out.Class().getName()+"的"+ Name()+"被执⾏了");
}
}
import org.springframework.aop.AfterReturningAdvice;
import flect.Method;
public class AfterLog implements AfterReturningAdvice {
// 后置通知,并且接收返回值
@Override
public void afterReturning(Object returnValue, Method method, Object[] args, Object target)throws Throwable { System.out.println("执⾏了"+ Name()+"⽅法,返回结果为"+ returnValue);
}
}
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论