Spring
Spring
IOC / AOP
Ioc—Inversion of Control,即“控制反转”,不是什么技术,而是一种设计思想。在Java开发中,Ioc意味着将你设计好的对象交给容器控制,而不是传统的在你的对象内部直接控制。如何理解好Ioc呢?理解好Ioc的关键是要明确“谁控制谁,控制什么,为何是反转(有反转就应该有正转了),哪些方面反转了”,那我们来深入分析一下:
●谁控制谁,控制什么:传统Java SE程序设计,我们直接在对象内部通过new进行创建对象,是程序主动去创建依赖对象;而IoC是有专门一个容器来创建这些对象,即由Ioc容器来控制对 象的创建;谁控制谁?当然是IoC 容器控制了对象;控制什么?那就是主要控制了外部资源获取(不只是对象包括比如文件等)。
●为何是反转,哪些方面反转了:有反转就有正转,传统应用程序是由我们自己在对象中主动控制去直接获取依赖对象,也就是正转;而反转则是由容器来帮忙创建及注入依赖对象;为何是反转?因为由容器帮我们查找及注入依赖对象,对象只是被动的接受依赖对象,所以是反转;哪些方面反转了?依赖对象的获取被反转了。
HelloSpring
package com.yrz.pojo;public class Hello { private String str; public String getStr() { return str; } public void setStr(String str) { this.str = str; } @Override public String toString() { return "Hello{" + "str='" + str + '\'' + '}'; }}
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="hello" class="com.yrz.pojo.Hello"> <property name="str" value="YRZ"/> </bean></beans>
import com.yrz.pojo.Hello;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;public class MyTest { public static void main(String[] args) { //获取spring的上下文对象 ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); Hello hello = (Hello) context.getBean("hello"); System.out.println(hello.toString()); } }
IOC创建对象的方式
package com.yrz.pojo;public class User { private String name; public User(String name){ this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } public void show() { System.out.println("name="+name); }}
构造器注入
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="user" class="com.yrz.pojo.User"> <constructor-arg index="0" value="yrz"/> </bean> <bean id="user" class="com.yrz.pojo.User"> <constructor-arg type="java.lang.String" value="yrz"/> </bean> <bean id="user" class="com.yrz.pojo.User"> <constructor-arg name="name" value="yrz"/> </bean></beans>
import com.yrz.pojo.User;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;public class Test { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); User user = (User) context.getBean("user"); user.show(); }}
依赖注入之–Set注入(重点)
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:util="http://www.springframework.org/schema/util"xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util https://www.springframework.org/schema/util/spring-util.xsd"> <bean id="address" class="com.yrz.pojo.Address"> <property name="address" value="上海"></property> </bean> <bean id="student" class="com.yrz.pojo.Student"> <property name="name" value="yrz"></property> <property name="address" ref="address"></property> <property name="books"> <array> <value>红楼梦</value> <value>西游记</value> <value>三国演义</value> <value>水浒传</value> </array> </property> <property name="hobbys"> <list> <value>听歌</value> <value>打游戏</value> <value>看电影</value> </list> </property> <property name="card"> <map> <entry key="身份证" value="6531"></entry> <entry key="学生证" value="1998"></entry> </map> </property> <property name="game"> <set><value>LOL</value><value>COC</value> </set> </property> <property name="wife"> <null></null> </property> <property name="info"> <props> <prop key="学号">132456</prop> <prop key="性别">男</prop> <prop key="名字">Y</prop> </props> </property></bean></beans>
注解自动装配
package com.yrz.pojo;import org.springframework.beans.factory.annotation.Autowired;public class People { private String name; @Autowired private Cat cat; @Autowired private Dog dog; public String getName() { return name; } public void setName(String name) { this.name = name; } public Cat getCat() { return cat; } public void setCat(Cat cat) { this.cat = cat; } public Dog getDog() { return dog; } public void setDog(Dog dog) { this.dog = dog; } @Override public String toString() { return "People{" + "name='" + name + '\'' + ", cat=" + cat + ", dog=" + dog + '}'; }}
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd <context:annotation-config/> <bean id="cat" class="com.yrz.pojo.Cat"></bean> <bean id="dog" class="com.yrz.pojo.Dog"></bean> <bean id="people" class="com.yrz.pojo.People"></bean></beans>
import com.yrz.pojo.People;import org.junit.Test;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;public class MyTest { @Test public void test1(){ ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); People people = context.getBean("people", People.class); people.getCat().shout(); people.getDog().shout(); } }
在xml中开启注解的支持
<context:component-scan base-package="com.yrz.pojo"/><context:annotation-config/>
@Autowired:自动装配先通过类型,再通过名字
@Resource:自动装配先通过名字,再通过类型
@Qualifier:使用@Qualifier(value="")去配置@Autowired的使用
@Component(“user”):// 相当于配置文件中
–dao【@Repository】
–service【@Service】
–controller【@Controller】【@RestController】-- 不走视图层,返回字符串
@Scope:作用域
@Configuration:代表这是一个配置类,和beans.xml一样
@Bean:作用于方法上,相当于bean标签,id是方法名,class是返回值
@ComponentScan:扫描Component
@Aspect:标志这个类是一个切面
package com.yrz.pojo;import org.springframework.beans.factory.annotation.Value;import org.springframework.context.annotation.Scope;import org.springframework.stereotype.Component;//相当于配置文件中 @Component//作用域@Scope("prototype")public class User { public String name; //相当于 @Value("YRZ") public void setName(String name) { this.name = name; }}
静态代理模式
UserService
package com.yrz.demo02;public interface UserService { public void add(); public void delete(); public void update(); public void query();}
UserServiceImpl
package com.yrz.demo02;public class UserServiceImpl implements UserService{ public void add() { System.out.println("add"); } public void delete() { System.out.println("delete"); } public void update() { System.out.println("update"); } public void query() { System.out.println("query"); }}
UserServiceProxy
package com.yrz.demo02;public class UserServiceProxy implements UserService{ private UserServiceImpl userService; public void setUserService(UserServiceImpl userService) { this.userService = userService; } public void add() { log("add"); userService.add(); } public void delete() { log("delete"); userService.delete(); } public void update() { log("update"); userService.update(); } public void query() { log("query"); userService.query(); } public void log(String msg){ System.out.println("[Debug]使用了"+msg+"方法"); }}
Client
package com.yrz.demo02;public class Client { public Client() { } public static void main(String[] args) { UserServiceImpl userService = new UserServiceImpl(); UserServiceProxy proxy = new UserServiceProxy(); proxy.setUserService(userService); proxy.add(); }}
动态代理模式
- 基于接口–JDK动态代理
了解两个类:
- Proxy–代理
- InvocationHandler–调用处理程序
ProxyInvocationHandler
package com.yrz.demo04;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;public class ProxyInvocationHandler implements InvocationHandler { //被代理的接口 private Object target; public void setTarget(Object target) { this.target = target; } //生成得到代理类 public Object getProxy(){ return Proxy.newProxyInstance(this.getClass().getClassLoader() ,target.getClass().getInterfaces(),this); } //处理代理实例,并返回结果 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { log(method.getName()); Object result = method.invoke(target, args); return result; } public void log(String msg){ System.out.println("使用了"+msg+"方法"); }}
Client
package com.yrz.demo04;import com.yrz.demo02.UserService;import com.yrz.demo02.UserServiceImpl;public class Client { public static void main(String[] args) { //真实角色 UserServiceImpl userService = new UserServiceImpl(); //代理角色,不存在 ProxyInvocationHandler pih = new ProxyInvocationHandler(); pih.setTarget(userService);//设置要代理的对象 //动态生成代理类 UserService proxy = (UserService) pih.getProxy(); proxy.delete(); }}
AOP实现方式一
使用原生Spring API接口(主要是Spring API接口实现)
package com.yrz.service;public class UserServiceImpl implements UserService{ public void add() { System.out.println("增"); } public void delete() { System.out.println("删"); } public void update() { System.out.println("改"); } public void select() { System.out.println("查"); }}
package com.yrz.service;import org.springframework.aop.MethodBeforeAdvice;import java.lang.reflect.Method;public class Log implements MethodBeforeAdvice { //method:要执行的目标对象方法 //args:参数 //target:目标 public void before(Method method, Object[] args, Object target) throws Throwable { System.out.println(target.getClass().getName()+"的"+method.getName()+"方法被执行了"); }}
package com.yrz.service;import org.springframework.aop.AfterReturningAdvice;import java.lang.reflect.Method;public class AfterLog implements AfterReturningAdvice { public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable { System.out.println("执行了"+method.getName()+"方法,返回值结果为:"+returnValue); }}
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:aop="http://www.springframework.org/schema/aop"xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd"> <bean id="userService" class="com.yrz.service.UserServiceImpl"></bean> <bean id="log" class="com.yrz.service.Log"></bean> <bean id="afterLog" class="com.yrz.service.AfterLog"></bean> <aop:config> <aop:pointcut id="pointcut" expression="execution(* com.yrz.service.UserServiceImpl.*(..))"/> <aop:advisor advice-ref="log" pointcut-ref="pointcut"></aop:advisor> <aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"></aop:advisor> </aop:config></beans>
import com.yrz.service.UserService;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;public class MyTest { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); UserService userService = (UserService) context.getBean("userService"); userService.add(); }}
AOP实现方式二
使用自定义类来实现AOP(主要是切面定义)
package com.yrz.diy;public class DiyPointCut { public void before(){ System.out.println("========方法执行前========"); } public void after(){ System.out.println("========方法执行后========"); }}
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:aop="http://www.springframework.org/schema/aop"xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd"> <bean id="userService" class="com.yrz.service.UserServiceImpl"></bean> <bean id="log" class="com.yrz.service.Log"></bean> <bean id="afterLog" class="com.yrz.service.AfterLog"></bean> <bean id="diy" class="com.yrz.diy.DiyPointCut"></bean> <aop:config> <aop:aspect ref="diy"> <aop:pointcut id="point" expression="execution(* com.yrz.service.UserServiceImpl.*(..))"/> <aop:before method="before" pointcut-ref="point"></aop:before> <aop:after method="after" pointcut-ref="point"></aop:after> </aop:aspect> </aop:config></beans>
AOP实现方式三
注解实现AOP
package com.yrz.diy;import org.aspectj.lang.annotation.After;import org.aspectj.lang.annotation.Aspect;import org.aspectj.lang.annotation.Before;@Aspect //标注这个类是一个切面public class AnnotationPointCut { @Before("execution(* com.yrz.service.UserServiceImpl.*(..))") public void before(){ System.out.println("执行前"); } @After("execution(* com.yrz.service.UserServiceImpl.*(..))") public void after(){ System.out.println("执行后"); }}
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:aop="http://www.springframework.org/schema/aop"xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd"> <bean id="userService" class="com.yrz.service.UserServiceImpl"></bean> <bean id="log" class="com.yrz.service.Log"></bean> <bean id="afterLog" class="com.yrz.service.AfterLog"></bean> <bean id="annotationPointCut" class="com.yrz.diy.AnnotationPointCut"></bean> <aop:aspectj-autoproxy></aop:aspectj-autoproxy></beans>