一.反向控制【Inversion of control】/依赖注入【Dependency Injection】
实现依赖抽象,类依赖接口,接口的实现通过bean注入。
注入
可以对一个对象注入字符串、map,另一个对象等信息。
https://blog.csdn.net/a909301740/article/details/78379720
1.接口注入
public class ClassA {
private InterfaceB clzB;
public Object doSomething(InterfaceB b) {
clzB = b;
return clzB.doIt();
}
}
2.构造器注入
public class DIByConstructor {
private final DataSourcedataSource;
public DIByConstructor(DataSource ds) {
this.dataSource = ds;
}
public class Role {
private int id;
private String roleName;
private String note;
public Role(){}
public Role(int id,String roleName, String note)
{
super();
this.id = id;
this.roleName = roleName;
this.note = note;
}
}
<bean id=
"Role"
class
=
"com.xiaojiang.Spring.Role"
>
<constructor-arg value=
"1"
type=
"int"
></constructor-arg>
<constructor-arg value=
"小江"
type=
"java.lang.String"
></constructor-arg>
<constructor-arg value=
"有点丑"
type=
"java.lang.String"
></constructor-arg>
</bean>
3.set注入
public class ClassA {
private InterfaceB clzB;
public void setClzB(InterfaceB clzB) {
this. clzB = clzB; }
}
<bean id=
"Role"
class
=
"com.xiaojiang.Spring.Role"
>
<property name=
"id"
value=
"1"
><property>
<property name=
"roleName"
value=
"小江"
><property>
<property name=
"note"
value=
"测试"
><property>
</bean>
set和构造器注入使用比较多。
主要配置和注解
<bean class="bean的完全限定名"
name/id="bean在容器内的唯一名称"
scope="bean的生命周期"
#https://www.cnblogs.com/jianyungsun/p/6839612.html
#singleton[default] /prototype/request[每一次http请求产生一个新的bean]/session
lazy-init="是否为延迟加载"
#https://blog.csdn.net/fhx007/article/details/7016704
#lazy-init 设置只对scop属性为singleton的bean起作用
init-method="bean的setter被调用之后调用该方法进行初始化"
destroy-method="容器在销毁该Bean后的调用的方法"
#https://www.cnblogs.com/soundcode/p/6367412.html
abstract="是否为抽象Bean,spring对于抽象bean不产生实例,主要用于继承"
parent="父Bean的名称,会继承父Bean的属性,与Java的Class无任何关系"
#https://blog.csdn.net/u010002184/article/details/80628657
factory-method="工厂方法的名字"
factory-bean="工厂Bean的名字"
#https://www.cnblogs.com/vickylinj/p/9474597.html
#实例化工厂类和方法,包括静态和非静态方法
depends-on ="依赖Bean的名字,保证初始化顺序。”
#http://zhaohe162.blog.163.com/blog/static/3821679720111171219156/
#管理依赖关系不明显或没哟直接依赖关系的对象,控制初始化顺序,
autowire="byType" dependency-check="simple/object/all/none"
#https://www.cnblogs.com/sishang/p/6583057.html
#自动装配,不显示制定注入的字段。配合使用做检查[基本类型、对象、所有类型、不检查]
#byType byName property属性设置方法同类型的bean或者和set方法同名的bean。
#eg. setDogId(Dog dog)
>
<!-- Constructor-arg给属性赋值写法一 -->
<constructor-arg type="int" value="10"/>
<!-- Constructor-arg给属性赋值写法二 -->
<constructor-arg name="age" value="10"/>
<!-- Constructor-arg给属性赋值写法三 -->
<constructor-arg index="0" value="10"/>
<!-- Properties给属性赋值写法一 -->
<property name="bean1">
<ref bean="另外一个bean的id"/>
</property>
<!-- Properties给属性赋值写法二 -->
<property name="bean1" ref="另外一个bean的id"/>
<!-- Properties给属性赋值写法三 -->
<property name="age" value="10"/>
集合注入方式
#https://www.cnblogs.com/lihuibin/p/7928893.html
</bean>
管理bean的方式
ApplicationContext和BeanFactory使用较多,ApplicationContext在BeanFactory基础上,增加了国际化支持,资源访问,时间传递等功能。
1.国际化支持:
https://blog.csdn.net/caomiao2006/article/details/51872442
https://www.cnblogs.com/tenWood/p/7535502.html
---todo
4AOP
4.1 代理
静态代理,动态代理 :接口代理【jdk代理】,cglib代理
静态AOP :AspectJ
动态AOP:Spring aop
静态AOP编译阶段生成class,性能较好些。
具体使用可参考:
http://www.cnblogs.com/cenyu/p/6289209.html#autoid-1-1-0
https://www.cnblogs.com/xiaofugua/articles/7251061.html
静态代理,动态代理(接口代理/cglib代理) 使用:https://www.jb51.net/article/110345.htm
代理原理:http://www.360doc.com/content/14/0801/14/1073512_398598312.shtml
动态代理调用原理:http://blog.csdn.net/wang_1997/article/details/52450549
反射打印:http://blog.csdn.net/rokii/article/details/4046098
接口代理需要实现InvocationHandler接口,cglib代理需要实现MethodIntercept解口
静态代理和接口代理:需要被代理类实现接口。
cglib代理:被代理的类可以是个普通的类,不需要实现接口。
接口代理:使用reflect包的反射部分,生成一个代理class文件,此class继承proxy并实现了对应的接口,并且在对应方法中调用
代理类【实现InvocationHandler】的invoke方法。
在运行过程生成代理二进制文件Proxy0,加载class,改class含有对动态代理类(InvocationHandler)的引用,以调用其invoke方法。
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;
import main.designer.proxy.justtest.IUser;
public final class $Proxy0
extends Proxy
implements IUser
{
private static Method m1;
private static Method m0;
private static Method m3;
private static Method m2;
public $Proxy0(InvocationHandler paramInvocationHandler)
throws
{
super(paramInvocationHandler);
}
public final boolean equals(Object paramObject)
throws
{
try
{
return ((Boolean)this.h.invoke(this, m1, new Object[] { paramObject })).booleanValue();
}
catch (Error|RuntimeException localError)
{
throw localError;
}
catch (Throwable localThrowable)
{
throw new UndeclaredThrowableException(localThrowable);
}
}
public final int hashCode()
throws
{
try
{
return ((Integer)this.h.invoke(this, m0, null)).intValue();
}
catch (Error|RuntimeException localError)
{
throw localError;
}
catch (Throwable localThrowable)
{
throw new UndeclaredThrowableException(localThrowable);
}
}
public final void showSkill()
throws
{
try
{
this.h.invoke(this, m3, null);
return;
}
catch (Error|RuntimeException localError)
{
throw localError;
}
catch (Throwable localThrowable)
{
throw new UndeclaredThrowableException(localThrowable);
}
}
public final String toString()
throws
{
try
{
return (String)this.h.invoke(this, m2, null);
}
catch (Error|RuntimeException localError)
{
throw localError;
}
catch (Throwable localThrowable)
{
throw new UndeclaredThrowableException(localThrowable);
}
}
static
{
try
{
m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[] { Class.forName("java.lang.Object") });
m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);
m3 = Class.forName("main.designer.proxy.justtest.IUser").getMethod("showSkill", new Class[0]);
m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
return;
}
catch (NoSuchMethodException localNoSuchMethodException)
{
throw new NoSuchMethodError(localNoSuchMethodException.getMessage());
}
catch (ClassNotFoundException localClassNotFoundException)
{
throw new NoClassDefFoundError(localClassNotFoundException.getMessage());
}
}
}
cglib代理:
public class CglibProxy implements MethodInterceptor
{
private static Logger logger = Logger.getLogger(Person.class);
/**
* {@inheritDoc}
*/
@Override
public Object intercept(Object arg0, Method arg1, Object[] arg2,
MethodProxy arg3) throws Throwable
{
logger.log(Level.INFO, "start to call:" + arg1);
Object object = arg3.invokeSuper(arg0, arg2);
logger.log(Level.INFO, "after call:" + arg1);
return object;
}
}
Enhancer hancEnhancer = new Enhancer();
CglibProxy proxy = new CglibProxy();
hancEnhancer.setSuperclass(Person.class);
hancEnhancer.setCallback(proxy);
Person p = (Person) hancEnhancer.create();
p.eat("apple");
CGLib创建的动态代理对象性能比JDK创建的动态代理对象的性能高不少,但是CGLib在创建代理对象时所花费的时间却比JDK多得多,所以对于单例的对象,因为无需频繁创建对象,用CGLib合适,反之,使用JDK方式要更为合适一些。同时,由于CGLib由于是采用动态创建子类的方法,对于final方法,无法进行代理
4.2spring配置aop
使用ProxyFactoryBean配置
<!-- 1.自动代理 -->
<!-- 制定哪些类和方法需要引入通知 -->
<!-- <bean id ="operaImple" class="com.spring.demo.conf.aop.business.InvOperationImpl" />
<bean id ="operaNormal" class="com.spring.demo.conf.aop.business.InvOperationNormal" />
<bean id="timeHanderAdvice" class="com.spring.demo.conf.aop.TimeHandler"/>
<bean id="timeHanderAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
<property name="advice" ref="timeHanderAdvice"/>
<property name="patterns" value=".*query.*"/>
</bean>
<bean id ="autoProxy" class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" /> -->
<!-- 2.ProxyFactoryBean接口代理 -->
<!--2.测试使用 timeProxy获取bean,调用方法会织入特定方法,interceptorNames如果为 timeHanderAdvice,则所有方法都会打印日志-->
<!-- <bean id ="operaImple" class="com.spring.demo.conf.aop.business.InvOperationImpl" />
<bean id ="operaNormal" class="com.spring.demo.conf.aop.business.InvOperationNormal" />
<bean id="timeHanderAdvice" class="com.spring.demo.conf.aop.TimeHandler"/>
<bean id="timeHanderAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
<property name="advice" ref="timeHanderAdvice"/>
<property name="patterns" value=".*query.*"/>
</bean>
<bean id="timeProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="target" ref="operaImple"/>
<property name="proxyInterfaces" value="com.spring.demo.conf.aop.business.InvOperationInterface"/>
<property name="interceptorNames" value="timeHanderAdvisor"/>
</bean> -->
<!-- 3.ProxyFactoryBean cglib代理 -->
<!-- <bean id ="operaImple" class="com.spring.demo.conf.aop.business.InvOperationImpl" />
<bean id ="operaNormal" class="com.spring.demo.conf.aop.business.InvOperationNormal" />
<bean id="timeHanderAdvice" class="com.spring.demo.conf.aop.TimeHandler"/>
<bean id="timecglibProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="target" ref="operaNormal"/>
<property name="interceptorNames" value="timeHanderAdvice"/>
</bean> -->
使用aspect
<!-- 4.aspect -->
<bean id ="operaImple" class="com.spring.demo.conf.aop.business.InvOperationImpl" />
<bean id ="operaNormal" class="com.spring.demo.conf.aop.business.InvOperationNormal" />
<bean id="timeHanderAdvice" class="com.spring.demo.conf.aop.TimeHandler"/>
<bean id="myaspect" class="com.spring.demo.conf.aop.MyAspect"/>
aspect:切面
pointcut:切点
<aop:config>
<aop:pointcut expression="execution(public * *(..))" id="mypointcut"/>
<aop:aspect ref="myaspect">
<aop:around method="aroundLog" pointcut-ref="mypointcut"/>
<aop:before method="beforeLog" pointcut-ref="mypointcut"/>
</aop:aspect>
</aop:config>
1.spring 的国际化
2.事件和监听
3.实现ApplicationContextWare(BeanFactoryAware)接口,bean会设置容器变量
BeanFactory和ApplicationContext
前者不会预先初始化bean,使用到再初始化,ApplicationContext会预先初始化容器中所有singleton bean。
bean输入方式
1.指定bean的class,调用构造器创建bean
<bean id ="manbean" class="com.test.man">
2.调用静态工厂方法创建bean
<bean id ="manbean" class="com.test.factory.Manfactory" factory-method="getBeing">
<constructor-arg value="dog"/>
</>
3.调用实例工厂方法创建bean
<bean id="personFactory" class="com.test.PersonFactory">
<bean id ="manbean" factory-bean="personFactory" factory-method="getPerson">
<constructor-arg value="dog"/>
</>
抽象bean和子bean 抽象bean配置abstract属性,子bean配置parent属性,子bean继承父bean的属性方法,和java继承不同可以是不同类型。
如果一个singleton的bean依赖一个prototype范围的bean,需要配置lookup-method属性,否则注入的都是一个单例。
#Chinese 定义为抽象类,getDog定义为抽象方法,spring会使用代理自动实现返回gunDog的实例。
<bean id="chinese" class="com.app.immple.Chinese">
<lookup-method name="getDog" bean="gunDog">
</bean>
<bean id="gunDog" class="com.app.imple.GunDog" scope="prototype"/>
注解
类
@Component("itemDao")
@Lazy(true)
@DependsOn({"steelAxe","abc"})
set方法,注入
@Resource(name="stongAxe")
@Autowired --type方式注入
@Autowired
@Qualifier("stongAxe")
@PostConstruct
init-method
@PreDestroy
destroy-methon
aspectj spring aop
spring aop只能针对方法
aspectj 还能针对属性赋值
spring整合事务,hibernate。