1.依赖注入
1.导包
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>cn.itsource</groupId>
<artifactId>SpringAoc</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<org.springframework.version>4.2.5.RELEASE</org.springframework.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.20</version>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
</resource>
<resource>
<directory>src/test/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
</resource>
</resources>
</build>
</project>
bean注入
<!--set方法注入:只要写了bean标签,就要求类中必须要有无参构造方法只要写了property标签,就一定是利用属性的set方法注入对象-->
<bean id="userDao" class="cn.itsource._01_DI_bean.dao.impl.UserDaoImpl"></bean>
<bean id="userService" class="cn.itsource._01_DI_bean.service.impl.UserServiceImpl">
<!-- property标签表示属性,name表示属性名称,ref表示引用另一个bean标签的id -->
<property name="userDao" ref="userDao"/>
</bean>
<bean id="userController" class="cn.itsource._01_DI_bean.controller.UserController">
<property name="userService" ref="userService"/>
</bean>
构造器注入
<!--
构造方法注入:
只要写了bean标签,就要求类中必须要有无参构造方法
constructor 构造方法-arg argument参数 构造方法参数
① 按构造方法的参数名称注入【推荐】
② 按构造方法的参数顺序注入【推荐】
③ 按构造方法的参数类型注入【一般不用这个,因为有可能出现构造方法参数的类型是相同的情况,那么还要再按照顺序来注入】
-->
<bean id="userDao" class="cn.itsource._02_DI_constructor.dao.impl.UserDaoImpl">
<constructor-arg type="java.lang.String" value="DAO层" />
<constructor-arg type="java.lang.String" value="3层" />
</bean>
<bean id="userService" class="cn.itsource._02_DI_constructor.service.impl.UserServiceImpl">
<constructor-arg name="userDao" ref="userDao" />
</bean>
<bean id="userController" class="cn.itsource._02_DI_constructor.controller.UserController">
<constructor-arg index="0" ref="userService" />
</bean>
注解注入
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!--自动扫描包-->
<context:component-scan base-package="cn.itsource._03_DI_annotation"></context:component-scan>
<context:annotation-config></context:annotation-config>
</beans>
内部的Bean注入
<!--
set方法注入:
只要写了bean标签,就要求类中必须要有无参构造方法
只要写了property标签,就一定是利用属性的set方法注入对象
property标签表示属性,name表示属性名称,ref表示引用另一个bean标签的id
外部bean:
需要使用ref属性去引用另一个bean标签的id
<property name="userDao" ref="userDao"/>
内部bean:
在property标签内部写一个bean标签,这个bean标签就可以不写id属性了
<property name="userDao">
<bean class="cn.itsource._04_DI_innerOrOuterBean.dao.impl.UserDaoImpl"></bean>
</property>
-->
<!--
外部bean的写法:
<bean id="userDao" class="cn.itsource._04_DI_innerOrOuterBean.dao.impl.UserDaoImpl"></bean>
<bean id="userService" class="cn.itsource._04_DI_innerOrOuterBean.service.impl.UserServiceImpl">
<property name="userDao" ref="userDao"/>
</bean>-->
<!-- 内部bean的写法 -->
<bean id="userService" class="cn.itsource._04_DI_innerOrOuterBean.service.impl.UserServiceImpl">
<property name="userDao">
<bean class="cn.itsource._04_DI_innerOrOuterBean.dao.impl.UserDaoImpl"></bean>
</property>
</bean>
<bean id="userController" class="cn.itsource._04_DI_innerOrOuterBean.controller.UserController">
<property name="userService" ref="userService"/>
</bean>
set
package cn.itsource._05_set;
import lombok.Data;
import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
@Data
public class Person {
// 简单属性【8种基本数据类型及其包装类型,String/BigDecimal】
private Long id;
private String name;
private Boolean sex;
private BigDecimal salary;
// 对象属性
private OtherBean otherBean;
private String[] arrays;
private List<String> list;
private Set<String> set;
//下面这个是重点
private Properties props1;
private Properties props2;
private List<OtherBean> otherBeanList;
private Set<OtherBean> otherBeanSet;
private Map<String, Object> map;
}
package cn.itsource._05_set;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:cn/itsource/_05_set/spring.xml")
public class DiTest {
@Autowired
private Person person;
@Test
public void test()throws Exception{
System.out.println(person);
}
}
package cn.itsource._05_set;
public class OtherBean {
}
<?xml version="1.0" encoding="UTF-8"?>
<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 http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="person" class="cn.itsource._05_set.Person" autowire="byType">
<property name="id" value="1"></property>
<property name="name" value="小猪"></property>
<property name="sex" value="false"></property>
<property name="salary" value="3000"></property>
<property name="arrays">
<array>
<value>x</value>
<value>y</value>
<value>z</value>
</array>
</property>
<property name="list">
<list>
<value>小</value>
<value>中</value>
<value>大</value>
<value>大</value>
</list>
</property>
<property name="set">
<set>
<value>小</value>
<value>中</value>
<value>大</value>
<value>大</value>
</set>
</property>
<property name="props1">
<props>
<prop key="name">小猪</prop>
<prop key="age">3</prop>
</props>
</property>
<property name="props2">
<value>
name=x
age=3
</value>
</property>
<property name="map">
<map>
<entry key="1" value="小猪"></entry>
<entry key="2" value="小虎"></entry>
<entry key="3" value="33"></entry>
</map>
</property>
<property name="otherBean" ref="otherBean01"></property>
<property name="otherBeanList">
<list>
<ref bean="otherBean02"></ref>
<ref bean="otherBean03"></ref>
<ref bean="otherBean04"></ref>
<ref bean="otherBean01"></ref>
</list>
</property>
<property name="otherBeanSet">
<set>
<ref bean="otherBean02"></ref>
<ref bean="otherBean01"></ref>
<ref bean="otherBean03"></ref>
<ref bean="otherBean04"></ref>
</set>
</property>
</bean>
<bean id="otherBean01" class="cn.itsource._05_set.OtherBean"></bean>
<bean id="otherBean02" class="cn.itsource._05_set.OtherBean"></bean>
<bean id="otherBean03" class="cn.itsource._05_set.OtherBean"></bean>
<bean id="otherBean04" class="cn.itsource._05_set.OtherBean"></bean>
</beans>
代理模式
代理模式定义
代理模式的英文叫做Proxy或Surrogate,中文都可译为”代理“,所谓代理,就是一个人或者一个机构代表另一个人或者另一个机构采取行动。在一些情况下,一个客户不想或者不能够直接引用一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用
定义可以比较难以理解,咱们把这个抽象的概念换成咱们现实中的代理:
火车票代理点
房屋中介
小王的好朋友小宋
开发术语
① 抽象主题角色:
声明了真实主题和代理主题的共同接口,这样一来在任何可以使用真实主题的地方都可以是使用代理主题。
② 代理主题(Proxy)角色:
代理主题角色内部含有对真实主题的引用,从而可以在任何时候操作真实主题对象;
代理主题角色提供一个与真实主题角色相同的接口,以便可以在任何时候都可以替代真实主题控制对真实主题的引用,负责在需要的时候创建真实主题对象(和删除真实主题对象);
代理角色通常在将客户端调用传递给真实的主题之前或之后(前置增强/通知,后置增强/通知),都要执行某个操作,而不是单纯地将调用传递给真实主题对象。
③ 真实主题角色:
定义了代理角色所代表地真实对象
1.静态代理
package cn.itsource._06_proxy_static;
public interface IRent {
//收钱
void rent();
//签合同
void asign();
}
package cn.itsource._06_proxy_static;
public class Intermidary implements IRent{
private IRent iRent;
public Intermidary(IRent iRent) {
this.iRent = iRent;
}
public void rent() {
System.out.println("调用之前插入逻辑");
this.iRent.rent();
System.out.println("调用之后插入逻辑");
}
public void asign() {
System.out.println("调用之前加入逻辑");
this.iRent.asign();
System.out.println("调用之后加入逻辑");
}
}
package cn.itsource._06_proxy_static;
public class Landlord implements IRent {
public void rent() {
System.out.println("房东收钱");
}
public void asign() {
System.out.println("房东签合同");
}
}
package cn.itsource._06_proxy_static;
import org.junit.Test;
public class StaticProxyTest {
@Test
public void test()throws Exception{
Landlord landlord = new Landlord();
Intermidary intermidary = new Intermidary(landlord);
intermidary.rent();
intermidary.asign();
}
}
2.动态代理
package cn.itsource._07_proxy_dynamic;
//抽象主题角色
public interface IRent {
//收钱
void rent();
//签合同
void asign();
}
package cn.itsource._07_proxy_dynamic;
public interface ITicket {
//订票
void order();
}
package cn.itsource._07_proxy_dynamic;
//房东:真实角色
public class Landlord implements IRent,ITicket{
public void rent() {
System.out.println("房东收钱");
}
public void asign() {
System.out.println("房东签合同");
}
public void order() {
System.out.println("订火车票");
}
}
package cn.itsource._07_proxy_dynamic;
import org.junit.Test;
import org.springframework.cglib.proxy.InvocationHandler;
import org.springframework.cglib.proxy.Proxy;
public class DynamicProxyTest {
@Test
public void test()throws Exception{
/**
* ClassLoader loader 类加载器
* Class<?>[] interfaces 被代理对象实现的所有接口形成的数组
* InvocationHandler h 执行处理器
*/
// ClassLoader loader = DynamicProxyTest.class.getClassLoader();
ClassLoader loader = Thread.currentThread().getContextClassLoader();//支持多线程并发
//创建一个被代理对象(真实主题角色)
IRent rent = new Landlord();
//获取被代理对象类实现过的所有接口,返回一个数组
Class<?>[] interfaces = rent.getClass().getInterfaces();
//执行处理器
InvocationHandler h = new MyInvocationHandler(rent);
//调用JDK自带的动态代理技术生成代理对象
IRent proxy = (IRent) Proxy.newProxyInstance(loader, interfaces,h);
System.out.println(proxy);
System.out.println(proxy.getClass());
proxy.asign();
proxy.rent();
}
}
package cn.itsource._07_proxy_dynamic;
import org.springframework.cglib.proxy.InvocationHandler;
import java.lang.reflect.Method;
public class MyInvocationHandler implements InvocationHandler {
private Object target;
public MyInvocationHandler(Object target) {
this.target = target;
}
public Object invoke(Object o, Method method, Object[] args ) throws Throwable {
//方法调用之前插入业务逻辑
System.out.println("方法调用之前插入业务逻辑");
//使用反射技术调用被代理对象的该方法
Object result = method.invoke(target, args);
//方法调用之后插入业务逻辑
System.out.println("方法调用之后插入业务逻辑");
return result;
}
}
底层
package cn.itsource._07_proxy_dynamic;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class $Proxy4 implements IRent,ITicket {
private Object target;
public $Proxy4(Object target) {
this.target = target;
}
public void rent() {
System.out.println("调用方法之前插入业务逻辑");
try {
Method rent = target.getClass().getDeclaredMethod("rent");
rent.invoke(target);
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
System.out.println("调用方法之后插入业务逻辑");
}
public void asign() {
System.out.println("调用方法之前插入业务逻辑");
try {
Method rent = target.getClass().getDeclaredMethod("asign");
rent.invoke(target);
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
System.out.println("调用方法之后插入业务逻辑");
}
public void order() {
System.out.println("调用方法之前插入业务逻辑");
try {
Method rent = target.getClass().getDeclaredMethod("order");
rent.invoke(target);
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
System.out.println("调用方法之后插入业务逻辑");
}
}